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 return implementingClass.newInstance(); 156 } catch (IllegalAccessException ex) { 157 Object exArgs[] = { algorithmURI, ex.getMessage() }; 158 throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs, ex); 159 } catch (InstantiationException ex) { 160 Object exArgs[] = { algorithmURI, ex.getMessage() }; 161 throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs, ex); 162 } catch (NullPointerException ex) { 163 Object exArgs[] = { algorithmURI, ex.getMessage() }; 164 throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs, ex); 165 } 166 } 167 168 169 /** 170 * Proxy method for {@link java.security.Signature#sign()} 171 * which is executed on the internal {@link java.security.Signature} object. 172 * 173 * @return the result of the {@link java.security.Signature#sign()} method 174 * @throws XMLSignatureException 175 */ 176 public byte[] sign() throws XMLSignatureException { 177 return signatureAlgorithm.engineSign(); 178 } 179 180 /** 181 * Proxy method for {@link java.security.Signature#getAlgorithm} 182 * which is executed on the internal {@link java.security.Signature} object. 183 * 184 * @return the result of the {@link java.security.Signature#getAlgorithm} method 185 */ 186 public String getJCEAlgorithmString() { 187 return signatureAlgorithm.engineGetJCEAlgorithmString(); 188 } 189 190 /** 191 * Method getJCEProviderName 192 * 193 * @return The Provider of this Signature Algorithm 194 */ 195 public String getJCEProviderName() { 196 return signatureAlgorithm.engineGetJCEProviderName(); 197 } 198 199 /** 200 * Proxy method for {@link java.security.Signature#update(byte[])} 201 * which is executed on the internal {@link java.security.Signature} object. 202 * 203 * @param input 204 * @throws XMLSignatureException 205 */ 206 public void update(byte[] input) throws XMLSignatureException { 207 signatureAlgorithm.engineUpdate(input); 208 } 209 210 /** 211 * Proxy method for {@link java.security.Signature#update(byte)} 212 * which is executed on the internal {@link java.security.Signature} object. 213 * 214 * @param input 215 * @throws XMLSignatureException 216 */ 217 public void update(byte input) throws XMLSignatureException { 218 signatureAlgorithm.engineUpdate(input); 219 } 220 221 /** 222 * Proxy method for {@link java.security.Signature#update(byte[], int, int)} 223 * which is executed on the internal {@link java.security.Signature} object. 224 * 225 * @param buf 226 * @param offset 227 * @param len 228 * @throws XMLSignatureException 229 */ 230 public void update(byte buf[], int offset, int len) throws XMLSignatureException { 231 signatureAlgorithm.engineUpdate(buf, offset, len); 232 } 233 234 /** 235 * Proxy method for {@link java.security.Signature#initSign(java.security.PrivateKey)} 236 * which is executed on the internal {@link java.security.Signature} object. 237 * 238 * @param signingKey 239 * @throws XMLSignatureException 240 */ 241 public void initSign(Key signingKey) throws XMLSignatureException { 242 signatureAlgorithm.engineInitSign(signingKey); 243 } 244 245 /** 246 * Proxy method for {@link java.security.Signature#initSign(java.security.PrivateKey, 247 * java.security.SecureRandom)} 248 * which is executed on the internal {@link java.security.Signature} object. 249 * 250 * @param signingKey 251 * @param secureRandom 252 * @throws XMLSignatureException 253 */ 254 public void initSign(Key signingKey, SecureRandom secureRandom) throws XMLSignatureException { 255 signatureAlgorithm.engineInitSign(signingKey, secureRandom); 256 } 257 258 /** 259 * Proxy method for {@link java.security.Signature#initSign(java.security.PrivateKey)} 260 * which is executed on the internal {@link java.security.Signature} object. 261 * 262 * @param signingKey 263 * @param algorithmParameterSpec 264 * @throws XMLSignatureException 265 */ 266 public void initSign( 267 Key signingKey, AlgorithmParameterSpec algorithmParameterSpec 268 ) throws XMLSignatureException { 269 signatureAlgorithm.engineInitSign(signingKey, algorithmParameterSpec); 270 } 271 272 /** 273 * Proxy method for {@link java.security.Signature#setParameter( 274 * java.security.spec.AlgorithmParameterSpec)} 275 * which is executed on the internal {@link java.security.Signature} object. 276 * 277 * @param params 278 * @throws XMLSignatureException 279 */ 280 public void setParameter(AlgorithmParameterSpec params) throws XMLSignatureException { 281 signatureAlgorithm.engineSetParameter(params); 282 } 283 284 /** 285 * Proxy method for {@link java.security.Signature#initVerify(java.security.PublicKey)} 286 * which is executed on the internal {@link java.security.Signature} object. 287 * 288 * @param verificationKey 289 * @throws XMLSignatureException 290 */ 291 public void initVerify(Key verificationKey) throws XMLSignatureException { 292 signatureAlgorithm.engineInitVerify(verificationKey); 293 } 294 295 /** 296 * Proxy method for {@link java.security.Signature#verify(byte[])} 297 * which is executed on the internal {@link java.security.Signature} object. 298 * 299 * @param signature 300 * @return true if the signature is valid. 301 * 302 * @throws XMLSignatureException 303 */ 304 public boolean verify(byte[] signature) throws XMLSignatureException { 305 return signatureAlgorithm.engineVerify(signature); 306 } 307 308 /** 309 * Returns the URI representation of Transformation algorithm 310 * 311 * @return the URI representation of Transformation algorithm 312 */ 313 public final String getURI() { 314 return constructionElement.getAttributeNS(null, Constants._ATT_ALGORITHM); 315 } 316 317 /** 318 * Registers implementing class of the SignatureAlgorithm with algorithmURI 319 * 320 * @param algorithmURI algorithmURI URI representation of <code>SignatureAlgorithm</code>. 321 * @param implementingClass <code>implementingClass</code> the implementing class of 322 * {@link SignatureAlgorithmSpi} 323 * @throws AlgorithmAlreadyRegisteredException if specified algorithmURI is already registered 324 * @throws XMLSignatureException 325 * @throws SecurityException if a security manager is installed and the 326 * caller does not have permission to register the signature algorithm 327 */ 328 @SuppressWarnings("unchecked") 329 public static void register(String algorithmURI, String implementingClass) 330 throws AlgorithmAlreadyRegisteredException, ClassNotFoundException, 331 XMLSignatureException { 332 JavaUtils.checkRegisterPermission(); 333 if (log.isLoggable(java.util.logging.Level.FINE)) { 334 log.log(java.util.logging.Level.FINE, "Try to register " + algorithmURI + " " + implementingClass); 335 } 336 337 // are we already registered? 338 Class<? extends SignatureAlgorithmSpi> registeredClass = algorithmHash.get(algorithmURI); 339 if (registeredClass != null) { 340 Object exArgs[] = { algorithmURI, registeredClass }; 341 throw new AlgorithmAlreadyRegisteredException( 342 "algorithm.alreadyRegistered", exArgs 343 ); 344 } 345 try { 346 Class<? extends SignatureAlgorithmSpi> clazz = 347 (Class<? extends SignatureAlgorithmSpi>) 348 ClassLoaderUtils.loadClass(implementingClass, SignatureAlgorithm.class); 349 algorithmHash.put(algorithmURI, clazz); 350 } catch (NullPointerException ex) { 351 Object exArgs[] = { algorithmURI, ex.getMessage() }; 352 throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs, ex); 353 } 354 } 355 356 /** 357 * Registers implementing class of the Transform algorithm with algorithmURI 358 * 359 * @param algorithmURI algorithmURI URI representation of <code>SignatureAlgorithm</code>. 360 * @param implementingClass <code>implementingClass</code> the implementing class of 361 * {@link SignatureAlgorithmSpi} 362 * @throws AlgorithmAlreadyRegisteredException if specified algorithmURI is already registered 363 * @throws XMLSignatureException 364 * @throws SecurityException if a security manager is installed and the 365 * caller does not have permission to register the signature algorithm 366 */ 367 public static void register(String algorithmURI, Class<? extends SignatureAlgorithmSpi> implementingClass) 368 throws AlgorithmAlreadyRegisteredException, ClassNotFoundException, 369 XMLSignatureException { 370 JavaUtils.checkRegisterPermission(); 371 if (log.isLoggable(java.util.logging.Level.FINE)) { 372 log.log(java.util.logging.Level.FINE, "Try to register " + algorithmURI + " " + implementingClass); 373 } 374 375 // are we already registered? 376 Class<? extends SignatureAlgorithmSpi> registeredClass = algorithmHash.get(algorithmURI); 377 if (registeredClass != null) { 378 Object exArgs[] = { algorithmURI, registeredClass }; 379 throw new AlgorithmAlreadyRegisteredException( 380 "algorithm.alreadyRegistered", exArgs 381 ); 382 } 383 algorithmHash.put(algorithmURI, implementingClass); 384 } 385 386 /** 387 * This method registers the default algorithms. 388 */ 389 public static void registerDefaultAlgorithms() { 390 algorithmHash.put( 391 XMLSignature.ALGO_ID_SIGNATURE_DSA, SignatureDSA.class 392 ); 393 algorithmHash.put( 394 XMLSignature.ALGO_ID_SIGNATURE_DSA_SHA256, SignatureDSA.SHA256.class 395 ); 396 algorithmHash.put( 397 XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1, SignatureBaseRSA.SignatureRSASHA1.class 398 ); 399 algorithmHash.put( 400 XMLSignature.ALGO_ID_MAC_HMAC_SHA1, IntegrityHmac.IntegrityHmacSHA1.class 401 ); 402 algorithmHash.put( 403 XMLSignature.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5, 404 SignatureBaseRSA.SignatureRSAMD5.class 405 ); 406 algorithmHash.put( 407 XMLSignature.ALGO_ID_SIGNATURE_RSA_RIPEMD160, 408 SignatureBaseRSA.SignatureRSARIPEMD160.class 409 ); 410 algorithmHash.put( 411 XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256, SignatureBaseRSA.SignatureRSASHA256.class 412 ); 413 algorithmHash.put( 414 XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384, SignatureBaseRSA.SignatureRSASHA384.class 415 ); 416 algorithmHash.put( 417 XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512, SignatureBaseRSA.SignatureRSASHA512.class 418 ); 419 algorithmHash.put( 420 XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA1, SignatureECDSA.SignatureECDSASHA1.class 421 ); 422 algorithmHash.put( 423 XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA256, SignatureECDSA.SignatureECDSASHA256.class 424 ); 425 algorithmHash.put( 426 XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA384, SignatureECDSA.SignatureECDSASHA384.class 427 ); 428 algorithmHash.put( 429 XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA512, SignatureECDSA.SignatureECDSASHA512.class 430 ); 431 algorithmHash.put( 432 XMLSignature.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5, IntegrityHmac.IntegrityHmacMD5.class 433 ); 434 algorithmHash.put( 435 XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160, IntegrityHmac.IntegrityHmacRIPEMD160.class 436 ); 437 algorithmHash.put( 438 XMLSignature.ALGO_ID_MAC_HMAC_SHA256, IntegrityHmac.IntegrityHmacSHA256.class 439 ); 440 algorithmHash.put( 441 XMLSignature.ALGO_ID_MAC_HMAC_SHA384, IntegrityHmac.IntegrityHmacSHA384.class 442 ); 443 algorithmHash.put( 444 XMLSignature.ALGO_ID_MAC_HMAC_SHA512, IntegrityHmac.IntegrityHmacSHA512.class 445 ); 446 } 447 448 /** 449 * Method getBaseNamespace 450 * 451 * @return URI of this element 452 */ 453 public String getBaseNamespace() { 454 return Constants.SignatureSpecNS; 455 } 456 457 /** 458 * Method getBaseLocalName 459 * 460 * @return Local name 461 */ 462 public String getBaseLocalName() { 463 return Constants._TAG_SIGNATUREMETHOD; 464 } 465 }