1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /** 6 * Licensed to the Apache Software Foundation (ASF) under one 7 * or more contributor license agreements. See the NOTICE file 8 * distributed with this work for additional information 9 * regarding copyright ownership. The ASF licenses this file 10 * to you under the Apache License, Version 2.0 (the 11 * "License"); you may not use this file except in compliance 12 * with the License. You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, 17 * software distributed under the License is distributed on an 18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19 * KIND, either express or implied. See the License for the 20 * specific language governing permissions and limitations 21 * under the License. 22 */ 23 /* 24 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. 25 */ 26 /* 27 * $Id: DOMDigestMethod.java 1333415 2012-05-03 12:03:51Z coheigea $ 28 */ 29 package org.jcp.xml.dsig.internal.dom; 30 31 import javax.xml.crypto.*; 32 import javax.xml.crypto.dom.DOMCryptoContext; 33 import javax.xml.crypto.dsig.*; 34 import javax.xml.crypto.dsig.spec.DigestMethodParameterSpec; 35 36 import java.security.InvalidAlgorithmParameterException; 37 import java.security.spec.AlgorithmParameterSpec; 38 import org.w3c.dom.Document; 39 import org.w3c.dom.Element; 40 import org.w3c.dom.Node; 41 42 /** 43 * DOM-based abstract implementation of DigestMethod. 44 * 45 * @author Sean Mullan 46 */ 47 public abstract class DOMDigestMethod extends DOMStructure 48 implements DigestMethod { 49 50 static final String SHA384 = 51 "http://www.w3.org/2001/04/xmldsig-more#sha384"; // see RFC 4051 52 private DigestMethodParameterSpec params; 53 54 /** 55 * Creates a <code>DOMDigestMethod</code>. 56 * 57 * @param params the algorithm-specific params (may be <code>null</code>) 58 * @throws InvalidAlgorithmParameterException if the parameters are not 59 * appropriate for this digest method 60 */ 61 DOMDigestMethod(AlgorithmParameterSpec params) 62 throws InvalidAlgorithmParameterException 63 { 64 if (params != null && !(params instanceof DigestMethodParameterSpec)) { 65 throw new InvalidAlgorithmParameterException 66 ("params must be of type DigestMethodParameterSpec"); 67 } 68 checkParams((DigestMethodParameterSpec)params); 69 this.params = (DigestMethodParameterSpec)params; 70 } 71 72 /** 73 * Creates a <code>DOMDigestMethod</code> from an element. This constructor 74 * invokes the abstract {@link #unmarshalParams unmarshalParams} method to 75 * unmarshal any algorithm-specific input parameters. 76 * 77 * @param dmElem a DigestMethod element 78 */ 79 DOMDigestMethod(Element dmElem) throws MarshalException { 80 Element paramsElem = DOMUtils.getFirstChildElement(dmElem); 81 if (paramsElem != null) { 82 params = unmarshalParams(paramsElem); 83 } 84 try { 85 checkParams(params); 86 } catch (InvalidAlgorithmParameterException iape) { 87 throw new MarshalException(iape); 88 } 89 } 90 91 static DigestMethod unmarshal(Element dmElem) throws MarshalException { 92 String alg = DOMUtils.getAttributeValue(dmElem, "Algorithm"); 93 if (alg.equals(DigestMethod.SHA1)) { 94 return new SHA1(dmElem); 95 } else if (alg.equals(DigestMethod.SHA256)) { 96 return new SHA256(dmElem); 97 } else if (alg.equals(SHA384)) { 98 return new SHA384(dmElem); 99 } else if (alg.equals(DigestMethod.SHA512)) { 100 return new SHA512(dmElem); 101 } else { 102 throw new MarshalException("unsupported DigestMethod algorithm: " + 103 alg); 104 } 105 } 106 107 /** 108 * Checks if the specified parameters are valid for this algorithm. By 109 * default, this method throws an exception if parameters are specified 110 * since most DigestMethod algorithms do not have parameters. Subclasses 111 * should override it if they have parameters. 112 * 113 * @param params the algorithm-specific params (may be <code>null</code>) 114 * @throws InvalidAlgorithmParameterException if the parameters are not 115 * appropriate for this digest method 116 */ 117 void checkParams(DigestMethodParameterSpec params) 118 throws InvalidAlgorithmParameterException 119 { 120 if (params != null) { 121 throw new InvalidAlgorithmParameterException("no parameters " + 122 "should be specified for the " + getMessageDigestAlgorithm() + 123 " DigestMethod algorithm"); 124 } 125 } 126 127 public final AlgorithmParameterSpec getParameterSpec() { 128 return params; 129 } 130 131 /** 132 * Unmarshals <code>DigestMethodParameterSpec</code> from the specified 133 * <code>Element</code>. By default, this method throws an exception since 134 * most DigestMethod algorithms do not have parameters. Subclasses should 135 * override it if they have parameters. 136 * 137 * @param paramsElem the <code>Element</code> holding the input params 138 * @return the algorithm-specific <code>DigestMethodParameterSpec</code> 139 * @throws MarshalException if the parameters cannot be unmarshalled 140 */ 141 DigestMethodParameterSpec unmarshalParams(Element paramsElem) 142 throws MarshalException 143 { 144 throw new MarshalException("no parameters should " + 145 "be specified for the " + 146 getMessageDigestAlgorithm() + 147 " DigestMethod algorithm"); 148 } 149 150 /** 151 * This method invokes the abstract {@link #marshalParams marshalParams} 152 * method to marshal any algorithm-specific parameters. 153 */ 154 public void marshal(Node parent, String prefix, DOMCryptoContext context) 155 throws MarshalException 156 { 157 Document ownerDoc = DOMUtils.getOwnerDocument(parent); 158 159 Element dmElem = DOMUtils.createElement(ownerDoc, "DigestMethod", 160 XMLSignature.XMLNS, prefix); 161 DOMUtils.setAttribute(dmElem, "Algorithm", getAlgorithm()); 162 163 if (params != null) { 164 marshalParams(dmElem, prefix); 165 } 166 167 parent.appendChild(dmElem); 168 } 169 170 @Override 171 public boolean equals(Object o) { 172 if (this == o) { 173 return true; 174 } 175 176 if (!(o instanceof DigestMethod)) { 177 return false; 178 } 179 DigestMethod odm = (DigestMethod)o; 180 181 boolean paramsEqual = (params == null ? odm.getParameterSpec() == null : 182 params.equals(odm.getParameterSpec())); 183 184 return (getAlgorithm().equals(odm.getAlgorithm()) && paramsEqual); 185 } 186 187 @Override 188 public int hashCode() { 189 int result = 17; 190 if (params != null) { 191 result = 31 * result + params.hashCode(); 192 } 193 result = 31 * result + getAlgorithm().hashCode(); 194 195 return result; 196 } 197 198 /** 199 * Marshals the algorithm-specific parameters to an Element and 200 * appends it to the specified parent element. By default, this method 201 * throws an exception since most DigestMethod algorithms do not have 202 * parameters. Subclasses should override it if they have parameters. 203 * 204 * @param parent the parent element to append the parameters to 205 * @param the namespace prefix to use 206 * @throws MarshalException if the parameters cannot be marshalled 207 */ 208 void marshalParams(Element parent, String prefix) 209 throws MarshalException 210 { 211 throw new MarshalException("no parameters should " + 212 "be specified for the " + 213 getMessageDigestAlgorithm() + 214 " DigestMethod algorithm"); 215 } 216 217 /** 218 * Returns the MessageDigest standard algorithm name. 219 */ 220 abstract String getMessageDigestAlgorithm(); 221 222 static final class SHA1 extends DOMDigestMethod { 223 SHA1(AlgorithmParameterSpec params) 224 throws InvalidAlgorithmParameterException { 225 super(params); 226 } 227 SHA1(Element dmElem) throws MarshalException { 228 super(dmElem); 229 } 230 public String getAlgorithm() { 231 return DigestMethod.SHA1; 232 } 233 String getMessageDigestAlgorithm() { 234 return "SHA-1"; 235 } 236 } 237 238 static final class SHA256 extends DOMDigestMethod { 239 SHA256(AlgorithmParameterSpec params) 240 throws InvalidAlgorithmParameterException { 241 super(params); 242 } 243 SHA256(Element dmElem) throws MarshalException { 244 super(dmElem); 245 } 246 public String getAlgorithm() { 247 return DigestMethod.SHA256; 248 } 249 String getMessageDigestAlgorithm() { 250 return "SHA-256"; 251 } 252 } 253 254 static final class SHA384 extends DOMDigestMethod { 255 SHA384(AlgorithmParameterSpec params) 256 throws InvalidAlgorithmParameterException { 257 super(params); 258 } 259 SHA384(Element dmElem) throws MarshalException { 260 super(dmElem); 261 } 262 public String getAlgorithm() { 263 return SHA384; 264 } 265 String getMessageDigestAlgorithm() { 266 return "SHA-384"; 267 } 268 } 269 270 static final class SHA512 extends DOMDigestMethod { 271 SHA512(AlgorithmParameterSpec params) 272 throws InvalidAlgorithmParameterException { 273 super(params); 274 } 275 SHA512(Element dmElem) throws MarshalException { 276 super(dmElem); 277 } 278 public String getAlgorithm() { 279 return DigestMethod.SHA512; 280 } 281 String getMessageDigestAlgorithm() { 282 return "SHA-512"; 283 } 284 } 285 }