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