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: DOMSignatureMethod.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.dsig.*; 33 import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec; 34 35 import java.io.IOException; 36 import java.security.*; 37 import java.security.spec.AlgorithmParameterSpec; 38 import org.w3c.dom.Element; 39 40 import com.sun.org.apache.xml.internal.security.algorithms.implementations.SignatureECDSA; 41 import org.jcp.xml.dsig.internal.SignerOutputStream; 42 43 /** 44 * DOM-based abstract implementation of SignatureMethod. 45 * 46 * @author Sean Mullan 47 */ 48 public abstract class DOMSignatureMethod extends AbstractDOMSignatureMethod { 49 50 private static java.util.logging.Logger log = 51 java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom"); 52 53 private SignatureMethodParameterSpec params; 54 private Signature signature; 55 56 // see RFC 4051 for these algorithm definitions 57 static final String RSA_SHA256 = 58 "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; 59 static final String RSA_SHA384 = 60 "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"; 61 static final String RSA_SHA512 = 62 "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"; 63 static final String ECDSA_SHA1 = 64 "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"; 65 static final String ECDSA_SHA256 = 66 "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"; 67 static final String ECDSA_SHA384 = 68 "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384"; 69 static final String ECDSA_SHA512 = 70 "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"; 71 72 /** 73 * Creates a <code>DOMSignatureMethod</code>. 74 * 75 * @param params the algorithm-specific params (may be <code>null</code>) 76 * @throws InvalidAlgorithmParameterException if the parameters are not 77 * appropriate for this signature method 78 */ 79 DOMSignatureMethod(AlgorithmParameterSpec params) 80 throws InvalidAlgorithmParameterException 81 { 82 if (params != null && 83 !(params instanceof SignatureMethodParameterSpec)) { 84 throw new InvalidAlgorithmParameterException 85 ("params must be of type SignatureMethodParameterSpec"); 86 } 87 checkParams((SignatureMethodParameterSpec)params); 88 this.params = (SignatureMethodParameterSpec)params; 89 } 90 91 /** 92 * Creates a <code>DOMSignatureMethod</code> from an element. This ctor 93 * invokes the {@link #unmarshalParams unmarshalParams} method to 94 * unmarshal any algorithm-specific input parameters. 95 * 96 * @param smElem a SignatureMethod element 97 */ 98 DOMSignatureMethod(Element smElem) throws MarshalException { 99 Element paramsElem = DOMUtils.getFirstChildElement(smElem); 100 if (paramsElem != null) { 101 params = unmarshalParams(paramsElem); 102 } 103 try { 104 checkParams(params); 105 } catch (InvalidAlgorithmParameterException iape) { 106 throw new MarshalException(iape); 107 } 108 } 109 110 static SignatureMethod unmarshal(Element smElem) throws MarshalException { 111 String alg = DOMUtils.getAttributeValue(smElem, "Algorithm"); 112 if (alg.equals(SignatureMethod.RSA_SHA1)) { 113 return new SHA1withRSA(smElem); 114 } else if (alg.equals(RSA_SHA256)) { 115 return new SHA256withRSA(smElem); 116 } else if (alg.equals(RSA_SHA384)) { 117 return new SHA384withRSA(smElem); 118 } else if (alg.equals(RSA_SHA512)) { 119 return new SHA512withRSA(smElem); 120 } else if (alg.equals(SignatureMethod.DSA_SHA1)) { 121 return new SHA1withDSA(smElem); 122 } else if (alg.equals(ECDSA_SHA1)) { 123 return new SHA1withECDSA(smElem); 124 } else if (alg.equals(ECDSA_SHA256)) { 125 return new SHA256withECDSA(smElem); 126 } else if (alg.equals(ECDSA_SHA384)) { 127 return new SHA384withECDSA(smElem); 128 } else if (alg.equals(ECDSA_SHA512)) { 129 return new SHA512withECDSA(smElem); 130 } else if (alg.equals(SignatureMethod.HMAC_SHA1)) { 131 return new DOMHMACSignatureMethod.SHA1(smElem); 132 } else if (alg.equals(DOMHMACSignatureMethod.HMAC_SHA256)) { 133 return new DOMHMACSignatureMethod.SHA256(smElem); 134 } else if (alg.equals(DOMHMACSignatureMethod.HMAC_SHA384)) { 135 return new DOMHMACSignatureMethod.SHA384(smElem); 136 } else if (alg.equals(DOMHMACSignatureMethod.HMAC_SHA512)) { 137 return new DOMHMACSignatureMethod.SHA512(smElem); 138 } else { 139 throw new MarshalException 140 ("unsupported SignatureMethod algorithm: " + alg); 141 } 142 } 143 144 public final AlgorithmParameterSpec getParameterSpec() { 145 return params; 146 } 147 148 boolean verify(Key key, SignedInfo si, byte[] sig, 149 XMLValidateContext context) 150 throws InvalidKeyException, SignatureException, XMLSignatureException 151 { 152 if (key == null || si == null || sig == null) { 153 throw new NullPointerException(); 154 } 155 156 if (!(key instanceof PublicKey)) { 157 throw new InvalidKeyException("key must be PublicKey"); 158 } 159 if (signature == null) { 160 try { 161 Provider p = (Provider)context.getProperty 162 ("org.jcp.xml.dsig.internal.dom.SignatureProvider"); 163 signature = (p == null) 164 ? Signature.getInstance(getJCAAlgorithm()) 165 : Signature.getInstance(getJCAAlgorithm(), p); 166 } catch (NoSuchAlgorithmException nsae) { 167 throw new XMLSignatureException(nsae); 168 } 169 } 170 signature.initVerify((PublicKey)key); 171 if (log.isLoggable(java.util.logging.Level.FINE)) { 172 log.log(java.util.logging.Level.FINE, "Signature provider:" + signature.getProvider()); 173 log.log(java.util.logging.Level.FINE, "verifying with key: " + key); 174 } 175 ((DOMSignedInfo)si).canonicalize(context, 176 new SignerOutputStream(signature)); 177 178 try { 179 Type type = getAlgorithmType(); 180 if (type == Type.DSA) { 181 return signature.verify(convertXMLDSIGtoASN1(sig)); 182 } else if (type == Type.ECDSA) { 183 return signature.verify(SignatureECDSA.convertXMLDSIGtoASN1(sig)); 184 } else { 185 return signature.verify(sig); 186 } 187 } catch (IOException ioe) { 188 throw new XMLSignatureException(ioe); 189 } 190 } 191 192 byte[] sign(Key key, SignedInfo si, XMLSignContext context) 193 throws InvalidKeyException, XMLSignatureException 194 { 195 if (key == null || si == null) { 196 throw new NullPointerException(); 197 } 198 199 if (!(key instanceof PrivateKey)) { 200 throw new InvalidKeyException("key must be PrivateKey"); 201 } 202 if (signature == null) { 203 try { 204 Provider p = (Provider)context.getProperty 205 ("org.jcp.xml.dsig.internal.dom.SignatureProvider"); 206 signature = (p == null) 207 ? Signature.getInstance(getJCAAlgorithm()) 208 : Signature.getInstance(getJCAAlgorithm(), p); 209 } catch (NoSuchAlgorithmException nsae) { 210 throw new XMLSignatureException(nsae); 211 } 212 } 213 signature.initSign((PrivateKey)key); 214 if (log.isLoggable(java.util.logging.Level.FINE)) { 215 log.log(java.util.logging.Level.FINE, "Signature provider:" + signature.getProvider()); 216 log.log(java.util.logging.Level.FINE, "Signing with key: " + key); 217 } 218 219 ((DOMSignedInfo)si).canonicalize(context, 220 new SignerOutputStream(signature)); 221 222 try { 223 Type type = getAlgorithmType(); 224 if (type == Type.DSA) { 225 return convertASN1toXMLDSIG(signature.sign()); 226 } else if (type == Type.ECDSA) { 227 return SignatureECDSA.convertASN1toXMLDSIG(signature.sign()); 228 } else { 229 return signature.sign(); 230 } 231 } catch (SignatureException se) { 232 throw new XMLSignatureException(se); 233 } catch (IOException ioe) { 234 throw new XMLSignatureException(ioe); 235 } 236 } 237 238 /** 239 * Converts an ASN.1 DSA value to a XML Signature DSA Value. 240 * 241 * The JAVA JCE DSA Signature algorithm creates ASN.1 encoded (r,s) value 242 * pairs; the XML Signature requires the core BigInteger values. 243 * 244 * @param asn1Bytes 245 * 246 * @throws IOException 247 * @see <A HREF="http://www.w3.org/TR/xmldsig-core/#dsa-sha1">6.4.1 DSA</A> 248 */ 249 private static byte[] convertASN1toXMLDSIG(byte asn1Bytes[]) 250 throws IOException 251 { 252 byte rLength = asn1Bytes[3]; 253 int i; 254 255 for (i = rLength; (i > 0) && (asn1Bytes[(4 + rLength) - i] == 0); i--); 256 257 byte sLength = asn1Bytes[5 + rLength]; 258 int j; 259 260 for (j = sLength; 261 (j > 0) && (asn1Bytes[(6 + rLength + sLength) - j] == 0); j--); 262 263 if ((asn1Bytes[0] != 48) || (asn1Bytes[1] != asn1Bytes.length - 2) 264 || (asn1Bytes[2] != 2) || (i > 20) 265 || (asn1Bytes[4 + rLength] != 2) || (j > 20)) { 266 throw new IOException("Invalid ASN.1 format of DSA signature"); 267 } else { 268 byte xmldsigBytes[] = new byte[40]; 269 270 System.arraycopy(asn1Bytes, (4+rLength)-i, xmldsigBytes, 20-i, i); 271 System.arraycopy(asn1Bytes, (6+rLength+sLength)-j, xmldsigBytes, 272 40 - j, j); 273 274 return xmldsigBytes; 275 } 276 } 277 278 /** 279 * Converts a XML Signature DSA Value to an ASN.1 DSA value. 280 * 281 * The JAVA JCE DSA Signature algorithm creates ASN.1 encoded (r,s) value 282 * pairs; the XML Signature requires the core BigInteger values. 283 * 284 * @param xmldsigBytes 285 * 286 * @throws IOException 287 * @see <A HREF="http://www.w3.org/TR/xmldsig-core/#dsa-sha1">6.4.1 DSA</A> 288 */ 289 private static byte[] convertXMLDSIGtoASN1(byte xmldsigBytes[]) 290 throws IOException 291 { 292 if (xmldsigBytes.length != 40) { 293 throw new IOException("Invalid XMLDSIG format of DSA signature"); 294 } 295 296 int i; 297 298 for (i = 20; (i > 0) && (xmldsigBytes[20 - i] == 0); i--); 299 300 int j = i; 301 302 if (xmldsigBytes[20 - i] < 0) { 303 j += 1; 304 } 305 306 int k; 307 308 for (k = 20; (k > 0) && (xmldsigBytes[40 - k] == 0); k--); 309 310 int l = k; 311 312 if (xmldsigBytes[40 - k] < 0) { 313 l += 1; 314 } 315 316 byte asn1Bytes[] = new byte[6 + j + l]; 317 318 asn1Bytes[0] = 48; 319 asn1Bytes[1] = (byte)(4 + j + l); 320 asn1Bytes[2] = 2; 321 asn1Bytes[3] = (byte)j; 322 323 System.arraycopy(xmldsigBytes, 20 - i, asn1Bytes, (4 + j) - i, i); 324 325 asn1Bytes[4 + j] = 2; 326 asn1Bytes[5 + j] = (byte) l; 327 328 System.arraycopy(xmldsigBytes, 40 - k, asn1Bytes, (6 + j + l) - k, k); 329 330 return asn1Bytes; 331 } 332 333 static final class SHA1withRSA extends DOMSignatureMethod { 334 SHA1withRSA(AlgorithmParameterSpec params) 335 throws InvalidAlgorithmParameterException { 336 super(params); 337 } 338 SHA1withRSA(Element dmElem) throws MarshalException { 339 super(dmElem); 340 } 341 public String getAlgorithm() { 342 return SignatureMethod.RSA_SHA1; 343 } 344 String getJCAAlgorithm() { 345 return "SHA1withRSA"; 346 } 347 Type getAlgorithmType() { 348 return Type.RSA; 349 } 350 } 351 352 static final class SHA256withRSA extends DOMSignatureMethod { 353 SHA256withRSA(AlgorithmParameterSpec params) 354 throws InvalidAlgorithmParameterException { 355 super(params); 356 } 357 SHA256withRSA(Element dmElem) throws MarshalException { 358 super(dmElem); 359 } 360 public String getAlgorithm() { 361 return RSA_SHA256; 362 } 363 String getJCAAlgorithm() { 364 return "SHA256withRSA"; 365 } 366 Type getAlgorithmType() { 367 return Type.RSA; 368 } 369 } 370 371 static final class SHA384withRSA extends DOMSignatureMethod { 372 SHA384withRSA(AlgorithmParameterSpec params) 373 throws InvalidAlgorithmParameterException { 374 super(params); 375 } 376 SHA384withRSA(Element dmElem) throws MarshalException { 377 super(dmElem); 378 } 379 public String getAlgorithm() { 380 return RSA_SHA384; 381 } 382 String getJCAAlgorithm() { 383 return "SHA384withRSA"; 384 } 385 Type getAlgorithmType() { 386 return Type.RSA; 387 } 388 } 389 390 static final class SHA512withRSA extends DOMSignatureMethod { 391 SHA512withRSA(AlgorithmParameterSpec params) 392 throws InvalidAlgorithmParameterException { 393 super(params); 394 } 395 SHA512withRSA(Element dmElem) throws MarshalException { 396 super(dmElem); 397 } 398 public String getAlgorithm() { 399 return RSA_SHA512; 400 } 401 String getJCAAlgorithm() { 402 return "SHA512withRSA"; 403 } 404 Type getAlgorithmType() { 405 return Type.RSA; 406 } 407 } 408 409 static final class SHA1withDSA extends DOMSignatureMethod { 410 SHA1withDSA(AlgorithmParameterSpec params) 411 throws InvalidAlgorithmParameterException { 412 super(params); 413 } 414 SHA1withDSA(Element dmElem) throws MarshalException { 415 super(dmElem); 416 } 417 public String getAlgorithm() { 418 return SignatureMethod.DSA_SHA1; 419 } 420 String getJCAAlgorithm() { 421 return "SHA1withDSA"; 422 } 423 Type getAlgorithmType() { 424 return Type.DSA; 425 } 426 } 427 428 static final class SHA1withECDSA extends DOMSignatureMethod { 429 SHA1withECDSA(AlgorithmParameterSpec params) 430 throws InvalidAlgorithmParameterException { 431 super(params); 432 } 433 SHA1withECDSA(Element dmElem) throws MarshalException { 434 super(dmElem); 435 } 436 public String getAlgorithm() { 437 return ECDSA_SHA1; 438 } 439 String getJCAAlgorithm() { 440 return "SHA1withECDSA"; 441 } 442 Type getAlgorithmType() { 443 return Type.ECDSA; 444 } 445 } 446 447 static final class SHA256withECDSA extends DOMSignatureMethod { 448 SHA256withECDSA(AlgorithmParameterSpec params) 449 throws InvalidAlgorithmParameterException { 450 super(params); 451 } 452 SHA256withECDSA(Element dmElem) throws MarshalException { 453 super(dmElem); 454 } 455 public String getAlgorithm() { 456 return ECDSA_SHA256; 457 } 458 String getJCAAlgorithm() { 459 return "SHA256withECDSA"; 460 } 461 Type getAlgorithmType() { 462 return Type.ECDSA; 463 } 464 } 465 466 static final class SHA384withECDSA extends DOMSignatureMethod { 467 SHA384withECDSA(AlgorithmParameterSpec params) 468 throws InvalidAlgorithmParameterException { 469 super(params); 470 } 471 SHA384withECDSA(Element dmElem) throws MarshalException { 472 super(dmElem); 473 } 474 public String getAlgorithm() { 475 return ECDSA_SHA384; 476 } 477 String getJCAAlgorithm() { 478 return "SHA384withECDSA"; 479 } 480 Type getAlgorithmType() { 481 return Type.ECDSA; 482 } 483 } 484 485 static final class SHA512withECDSA extends DOMSignatureMethod { 486 SHA512withECDSA(AlgorithmParameterSpec params) 487 throws InvalidAlgorithmParameterException { 488 super(params); 489 } 490 SHA512withECDSA(Element dmElem) throws MarshalException { 491 super(dmElem); 492 } 493 public String getAlgorithm() { 494 return ECDSA_SHA512; 495 } 496 String getJCAAlgorithm() { 497 return "SHA512withECDSA"; 498 } 499 Type getAlgorithmType() { 500 return Type.ECDSA; 501 } 502 } 503 }