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 package com.sun.org.apache.xml.internal.security.algorithms; 24 25 import java.security.Key; 26 import java.security.SecureRandom; 27 import java.security.spec.AlgorithmParameterSpec; 28 import java.util.Map; 29 import java.util.concurrent.ConcurrentHashMap; 30 31 import com.sun.org.apache.xml.internal.security.algorithms.implementations.IntegrityHmac; 32 import com.sun.org.apache.xml.internal.security.algorithms.implementations.SignatureBaseRSA; 33 import com.sun.org.apache.xml.internal.security.algorithms.implementations.SignatureDSA; 34 import com.sun.org.apache.xml.internal.security.algorithms.implementations.SignatureECDSA; 35 import com.sun.org.apache.xml.internal.security.exceptions.AlgorithmAlreadyRegisteredException; 36 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; 37 import com.sun.org.apache.xml.internal.security.signature.XMLSignature; 38 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException; 39 import com.sun.org.apache.xml.internal.security.utils.Constants; 40 import org.w3c.dom.Attr; 41 import org.w3c.dom.Document; 42 import org.w3c.dom.Element; 43 44 /** 45 * Allows selection of digital signature's algorithm, private keys, other 46 * security parameters, and algorithm's ID. 47 * 48 * @author Christian Geuer-Pollmann 49 */ 50 public class SignatureAlgorithm extends Algorithm { 51 52 /** {@link org.apache.commons.logging} logging facility */ 53 private static java.util.logging.Logger log = 54 java.util.logging.Logger.getLogger(SignatureAlgorithm.class.getName()); 55 56 /** All available algorithm classes are registered here */ 57 private static Map<String, Class<? extends SignatureAlgorithmSpi>> algorithmHash = 58 new ConcurrentHashMap<String, Class<? extends SignatureAlgorithmSpi>>(); 59 60 /** Field signatureAlgorithm */ 61 private final SignatureAlgorithmSpi signatureAlgorithm; 62 63 private final String algorithmURI; 64 65 /** 66 * Constructor SignatureAlgorithm 67 * 68 * @param doc 69 * @param algorithmURI 70 * @throws XMLSecurityException 71 */ 72 public SignatureAlgorithm(Document doc, String algorithmURI) throws XMLSecurityException { 73 super(doc, algorithmURI); 74 this.algorithmURI = algorithmURI; 75 76 signatureAlgorithm = getSignatureAlgorithmSpi(algorithmURI); 77 signatureAlgorithm.engineGetContextFromElement(this.constructionElement); 78 } 79 80 /** 81 * Constructor SignatureAlgorithm 82 * 83 * @param doc 84 * @param algorithmURI 85 * @param hmacOutputLength 86 * @throws XMLSecurityException 87 */ 88 public SignatureAlgorithm( 89 Document doc, String algorithmURI, int hmacOutputLength 90 ) throws XMLSecurityException { 91 super(doc, algorithmURI); 92 this.algorithmURI = algorithmURI; 93 94 signatureAlgorithm = getSignatureAlgorithmSpi(algorithmURI); 95 signatureAlgorithm.engineGetContextFromElement(this.constructionElement); 96 97 signatureAlgorithm.engineSetHMACOutputLength(hmacOutputLength); 98 ((IntegrityHmac)signatureAlgorithm).engineAddContextToElement(constructionElement); 99 } 100 101 /** 102 * Constructor SignatureAlgorithm 103 * 104 * @param element 105 * @param baseURI 106 * @throws XMLSecurityException 107 */ 108 public SignatureAlgorithm(Element element, String baseURI) throws XMLSecurityException { 109 this(element, baseURI, false); 110 } 111 112 /** 113 * Constructor SignatureAlgorithm 114 * 115 * @param element 116 * @param baseURI 117 * @param secureValidation 118 * @throws XMLSecurityException 119 */ 120 public SignatureAlgorithm( 121 Element element, String baseURI, boolean secureValidation 122 ) throws XMLSecurityException { 123 super(element, baseURI); 124 algorithmURI = this.getURI(); 125 126 Attr attr = element.getAttributeNodeNS(null, "Id"); 127 if (attr != null) { 128 element.setIdAttributeNode(attr, true); 129 } 130 131 if (secureValidation && (XMLSignature.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5.equals(algorithmURI) 132 || XMLSignature.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5.equals(algorithmURI))) { 133 Object exArgs[] = { algorithmURI }; 134 135 throw new XMLSecurityException("signature.signatureAlgorithm", exArgs); 136 } 137 138 signatureAlgorithm = getSignatureAlgorithmSpi(algorithmURI); 139 signatureAlgorithm.engineGetContextFromElement(this.constructionElement); 140 } 141 142 /** 143 * Get a SignatureAlgorithmSpi object corresponding to the algorithmURI argument 144 */ 145 private static SignatureAlgorithmSpi getSignatureAlgorithmSpi(String algorithmURI) 146 throws XMLSignatureException { 147 try { 148 Class<? extends SignatureAlgorithmSpi> implementingClass = 149 algorithmHash.get(algorithmURI); 150 if (log.isLoggable(java.util.logging.Level.FINE)) { 151 log.log(java.util.logging.Level.FINE, "Create URI \"" + algorithmURI + "\" class \"" 152 + implementingClass + "\""); 153 } 154 return implementingClass.newInstance(); 155 } catch (IllegalAccessException ex) { 156 Object exArgs[] = { algorithmURI, ex.getMessage() }; 157 throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs, ex); 158 } catch (InstantiationException ex) { 159 Object exArgs[] = { algorithmURI, ex.getMessage() }; 160 throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs, ex); 161 } catch (NullPointerException ex) { 162 Object exArgs[] = { algorithmURI, ex.getMessage() }; 163 throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs, ex); 164 } 165 } 166 167 168 /** 169 * Proxy method for {@link java.security.Signature#sign()} 170 * which is executed on the internal {@link java.security.Signature} object. 171 * 172 * @return the result of the {@link java.security.Signature#sign()} method 173 * @throws XMLSignatureException 174 */ 175 public byte[] sign() throws XMLSignatureException { 176 return signatureAlgorithm.engineSign(); 177 } 178 179 /** 180 * Proxy method for {@link java.security.Signature#getAlgorithm} 181 * which is executed on the internal {@link java.security.Signature} object. 182 * 183 * @return the result of the {@link java.security.Signature#getAlgorithm} method 184 */ 185 public String getJCEAlgorithmString() { 186 return signatureAlgorithm.engineGetJCEAlgorithmString(); 187 } 188 189 /** 190 * Method getJCEProviderName 191 * 192 * @return The Provider of this Signature Algorithm 193 */ 194 public String getJCEProviderName() { 195 return signatureAlgorithm.engineGetJCEProviderName(); 196 } 197 198 /** 199 * Proxy method for {@link java.security.Signature#update(byte[])} 200 * which is executed on the internal {@link java.security.Signature} object. 201 * 202 * @param input 203 * @throws XMLSignatureException 204 */ 205 public void update(byte[] input) throws XMLSignatureException { 206 signatureAlgorithm.engineUpdate(input); 207 } 208 209 /** 210 * Proxy method for {@link java.security.Signature#update(byte)} 211 * which is executed on the internal {@link java.security.Signature} object. 212 * 213 * @param input 214 * @throws XMLSignatureException 215 */ 216 public void update(byte input) throws XMLSignatureException { 217 signatureAlgorithm.engineUpdate(input); 218 } 219 220 /** 221 * Proxy method for {@link java.security.Signature#update(byte[], int, int)} 222 * which is executed on the internal {@link java.security.Signature} object. 223 * 224 * @param buf 225 * @param offset 226 * @param len 227 * @throws XMLSignatureException 228 */ 229 public void update(byte buf[], int offset, int len) throws XMLSignatureException { 230 signatureAlgorithm.engineUpdate(buf, offset, len); 231 } 232 233 /** 234 * Proxy method for {@link java.security.Signature#initSign(java.security.PrivateKey)} 235 * which is executed on the internal {@link java.security.Signature} object. 236 * 237 * @param signingKey 238 * @throws XMLSignatureException 239 */ 240 public void initSign(Key signingKey) throws XMLSignatureException { 241 signatureAlgorithm.engineInitSign(signingKey); 242 } 243 244 /** 245 * Proxy method for {@link java.security.Signature#initSign(java.security.PrivateKey, 246 * java.security.SecureRandom)} 247 * which is executed on the internal {@link java.security.Signature} object. 248 * 249 * @param signingKey 250 * @param secureRandom 251 * @throws XMLSignatureException 252 */ 253 public void initSign(Key signingKey, SecureRandom secureRandom) throws XMLSignatureException { 254 signatureAlgorithm.engineInitSign(signingKey, secureRandom); 255 } 256 257 /** 258 * Proxy method for {@link java.security.Signature#initSign(java.security.PrivateKey)} 259 * which is executed on the internal {@link java.security.Signature} object. 260 * 261 * @param signingKey 262 * @param algorithmParameterSpec 263 * @throws XMLSignatureException 264 */ 265 public void initSign( 266 Key signingKey, AlgorithmParameterSpec algorithmParameterSpec 267 ) throws XMLSignatureException { 268 signatureAlgorithm.engineInitSign(signingKey, algorithmParameterSpec); 269 } 270 271 /** 272 * Proxy method for {@link java.security.Signature#setParameter( 273 * java.security.spec.AlgorithmParameterSpec)} 274 * which is executed on the internal {@link java.security.Signature} object. 275 * 276 * @param params 277 * @throws XMLSignatureException 278 */ 279 public void setParameter(AlgorithmParameterSpec params) throws XMLSignatureException { 280 signatureAlgorithm.engineSetParameter(params); 281 } 282 283 /** 284 * Proxy method for {@link java.security.Signature#initVerify(java.security.PublicKey)} 285 * which is executed on the internal {@link java.security.Signature} object. 286 * 287 * @param verificationKey 288 * @throws XMLSignatureException 289 */ 290 public void initVerify(Key verificationKey) throws XMLSignatureException { 291 signatureAlgorithm.engineInitVerify(verificationKey); 292 } 293 294 /** 295 * Proxy method for {@link java.security.Signature#verify(byte[])} 296 * which is executed on the internal {@link java.security.Signature} object. 297 * 298 * @param signature 299 * @return true if if the signature is valid. 300 * 301 * @throws XMLSignatureException 302 */ 303 public boolean verify(byte[] signature) throws XMLSignatureException { 304 return signatureAlgorithm.engineVerify(signature); 305 } 306 307 /** 308 * Returns the URI representation of Transformation algorithm 309 * 310 * @return the URI representation of Transformation algorithm 311 */ 312 public final String getURI() { 313 return constructionElement.getAttributeNS(null, Constants._ATT_ALGORITHM); 314 } 315 316 /** 317 * Registers implementing class of the Transform algorithm with algorithmURI 318 * 319 * @param algorithmURI algorithmURI URI representation of <code>Transform algorithm</code>. 320 * @param implementingClass <code>implementingClass</code> the implementing class of 321 * {@link SignatureAlgorithmSpi} 322 * @throws AlgorithmAlreadyRegisteredException if specified algorithmURI is already registered 323 * @throws XMLSignatureException 324 */ 325 @SuppressWarnings("unchecked") 326 public static void register(String algorithmURI, String implementingClass) 327 throws AlgorithmAlreadyRegisteredException, ClassNotFoundException, 328 XMLSignatureException { 329 if (log.isLoggable(java.util.logging.Level.FINE)) { 330 log.log(java.util.logging.Level.FINE, "Try to register " + algorithmURI + " " + implementingClass); 331 } 332 333 // are we already registered? 334 Class<? extends SignatureAlgorithmSpi> registeredClass = algorithmHash.get(algorithmURI); 335 if (registeredClass != null) { 336 Object exArgs[] = { algorithmURI, registeredClass }; 337 throw new AlgorithmAlreadyRegisteredException( 338 "algorithm.alreadyRegistered", exArgs 339 ); 340 } 341 try { 342 Class<? extends SignatureAlgorithmSpi> clazz = 343 (Class<? extends SignatureAlgorithmSpi>) 344 ClassLoaderUtils.loadClass(implementingClass, SignatureAlgorithm.class); 345 algorithmHash.put(algorithmURI, clazz); 346 } catch (NullPointerException ex) { 347 Object exArgs[] = { algorithmURI, ex.getMessage() }; 348 throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs, ex); 349 } 350 } 351 352 /** 353 * Registers implementing class of the Transform algorithm with algorithmURI 354 * 355 * @param algorithmURI algorithmURI URI representation of <code>Transform algorithm</code>. 356 * @param implementingClass <code>implementingClass</code> the implementing class of 357 * {@link SignatureAlgorithmSpi} 358 * @throws AlgorithmAlreadyRegisteredException if specified algorithmURI is already registered 359 * @throws XMLSignatureException 360 */ 361 public static void register(String algorithmURI, Class<? extends SignatureAlgorithmSpi> implementingClass) 362 throws AlgorithmAlreadyRegisteredException, ClassNotFoundException, 363 XMLSignatureException { 364 if (log.isLoggable(java.util.logging.Level.FINE)) { 365 log.log(java.util.logging.Level.FINE, "Try to register " + algorithmURI + " " + implementingClass); 366 } 367 368 // are we already registered? 369 Class<? extends SignatureAlgorithmSpi> registeredClass = algorithmHash.get(algorithmURI); 370 if (registeredClass != null) { 371 Object exArgs[] = { algorithmURI, registeredClass }; 372 throw new AlgorithmAlreadyRegisteredException( 373 "algorithm.alreadyRegistered", exArgs 374 ); 375 } 376 algorithmHash.put(algorithmURI, implementingClass); 377 } 378 379 /** 380 * This method registers the default algorithms. 381 */ 382 public static void registerDefaultAlgorithms() { 383 algorithmHash.put(SignatureDSA.URI, SignatureDSA.class); 384 algorithmHash.put( 385 XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1, SignatureBaseRSA.SignatureRSASHA1.class 386 ); 387 algorithmHash.put( 388 XMLSignature.ALGO_ID_MAC_HMAC_SHA1, IntegrityHmac.IntegrityHmacSHA1.class 389 ); 390 algorithmHash.put( 391 XMLSignature.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5, 392 SignatureBaseRSA.SignatureRSAMD5.class 393 ); 394 algorithmHash.put( 395 XMLSignature.ALGO_ID_SIGNATURE_RSA_RIPEMD160, 396 SignatureBaseRSA.SignatureRSARIPEMD160.class 397 ); 398 algorithmHash.put( 399 XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256, SignatureBaseRSA.SignatureRSASHA256.class 400 ); 401 algorithmHash.put( 402 XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384, SignatureBaseRSA.SignatureRSASHA384.class 403 ); 404 algorithmHash.put( 405 XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512, SignatureBaseRSA.SignatureRSASHA512.class 406 ); 407 algorithmHash.put( 408 XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA1, SignatureECDSA.SignatureECDSASHA1.class 409 ); 410 algorithmHash.put( 411 XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA256, SignatureECDSA.SignatureECDSASHA256.class 412 ); 413 algorithmHash.put( 414 XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA384, SignatureECDSA.SignatureECDSASHA384.class 415 ); 416 algorithmHash.put( 417 XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA512, SignatureECDSA.SignatureECDSASHA512.class 418 ); 419 algorithmHash.put( 420 XMLSignature.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5, IntegrityHmac.IntegrityHmacMD5.class 421 ); 422 algorithmHash.put( 423 XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160, IntegrityHmac.IntegrityHmacRIPEMD160.class 424 ); 425 algorithmHash.put( 426 XMLSignature.ALGO_ID_MAC_HMAC_SHA256, IntegrityHmac.IntegrityHmacSHA256.class 427 ); 428 algorithmHash.put( 429 XMLSignature.ALGO_ID_MAC_HMAC_SHA384, IntegrityHmac.IntegrityHmacSHA384.class 430 ); 431 algorithmHash.put( 432 XMLSignature.ALGO_ID_MAC_HMAC_SHA512, IntegrityHmac.IntegrityHmacSHA512.class 433 ); 434 } 435 436 /** 437 * Method getBaseNamespace 438 * 439 * @return URI of this element 440 */ 441 public String getBaseNamespace() { 442 return Constants.SignatureSpecNS; 443 } 444 445 /** 446 * Method getBaseLocalName 447 * 448 * @return Local name 449 */ 450 public String getBaseLocalName() { 451 return Constants._TAG_SIGNATUREMETHOD; 452 } 453 }