1 /* 2 * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @bug 4635230 6283345 6303830 6824440 6867348 7094155 8038184 27 * 8038349 8074784 8210736 28 * @summary Basic unit tests for generating XML Signatures with JSR 105 29 * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java 30 * X509KeySelector.java GenerationTests.java 31 * @run main/othervm -Dsun.net.httpserver.nodelay=true GenerationTests 32 * @author Sean Mullan 33 */ 34 35 import com.sun.net.httpserver.HttpExchange; 36 import com.sun.net.httpserver.HttpHandler; 37 import com.sun.net.httpserver.HttpServer; 38 import java.io.*; 39 import java.math.BigInteger; 40 import java.net.InetSocketAddress; 41 import java.security.Key; 42 import java.security.KeyFactory; 43 import java.security.KeyPair; 44 import java.security.KeyPairGenerator; 45 import java.security.KeyStore; 46 import java.security.NoSuchAlgorithmException; 47 import java.security.PrivateKey; 48 import java.security.PublicKey; 49 import java.security.SecureRandom; 50 import java.security.Security; 51 import java.security.cert.Certificate; 52 import java.security.cert.CertificateFactory; 53 import java.security.cert.X509CRL; 54 import java.security.spec.KeySpec; 55 import java.security.spec.DSAPrivateKeySpec; 56 import java.security.spec.DSAPublicKeySpec; 57 import java.security.spec.RSAPrivateKeySpec; 58 import java.security.spec.RSAPublicKeySpec; 59 import java.util.*; 60 import javax.crypto.KeyGenerator; 61 import javax.crypto.SecretKey; 62 import javax.xml.XMLConstants; 63 import javax.xml.parsers.*; 64 import javax.xml.crypto.Data; 65 import javax.xml.crypto.KeySelector; 66 import javax.xml.crypto.OctetStreamData; 67 import javax.xml.crypto.URIDereferencer; 68 import javax.xml.crypto.URIReference; 69 import javax.xml.crypto.URIReferenceException; 70 import javax.xml.crypto.XMLCryptoContext; 71 import javax.xml.crypto.XMLStructure; 72 import javax.xml.crypto.dsig.*; 73 import javax.xml.crypto.dom.*; 74 import javax.xml.crypto.dsig.dom.DOMSignContext; 75 import javax.xml.crypto.dsig.dom.DOMValidateContext; 76 import javax.xml.crypto.dsig.keyinfo.*; 77 import javax.xml.crypto.dsig.spec.*; 78 import javax.xml.transform.*; 79 import javax.xml.transform.dom.DOMSource; 80 import javax.xml.transform.stream.StreamResult; 81 import org.w3c.dom.*; 82 83 /** 84 * Test that recreates merlin-xmldsig-twenty-three test vectors but with 85 * different keys and X.509 data. 86 */ 87 public class GenerationTests { 88 89 private static XMLSignatureFactory fac; 90 private static KeyInfoFactory kifac; 91 private static DocumentBuilder db; 92 private static CanonicalizationMethod withoutComments; 93 private static SignatureMethod dsaSha1, dsaSha256, rsaSha1, 94 rsaSha256, rsaSha384, rsaSha512; 95 private static DigestMethod sha1, sha256, sha384, sha512; 96 private static KeyInfo dsa1024, dsa2048, rsa, rsa1024; 97 private static KeySelector kvks = new KeySelectors.KeyValueKeySelector(); 98 private static KeySelector sks; 99 private static Key signingKey; 100 private static PublicKey validatingKey; 101 private static Certificate signingCert; 102 private static KeyStore ks; 103 private final static String DIR = System.getProperty("test.src", "."); 104 // private final static String DIR = "."; 105 private final static String DATA_DIR = 106 DIR + System.getProperty("file.separator") + "data"; 107 private final static String KEYSTORE = 108 DATA_DIR + System.getProperty("file.separator") + "certs" + 109 System.getProperty("file.separator") + "test.jks"; 110 private final static String CRL = 111 DATA_DIR + System.getProperty("file.separator") + "certs" + 112 System.getProperty("file.separator") + "crl"; 113 private final static String ENVELOPE = 114 DATA_DIR + System.getProperty("file.separator") + "envelope.xml"; 115 private static URIDereferencer httpUd = null; 116 private final static String STYLESHEET = 117 "http://www.w3.org/TR/xml-stylesheet"; 118 private final static String STYLESHEET_B64 = 119 "http://www.w3.org/Signature/2002/04/xml-stylesheet.b64"; 120 private final static String DSA_SHA256 = 121 "http://www.w3.org/2009/xmldsig11#dsa-sha256"; 122 123 private static final String BOGUS = "bogus"; 124 125 private static final String OS = System.getProperty("os.name"); 126 private static boolean secondChanceGranted = false; 127 128 private static final String xslt = "" 129 + "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'\n" 130 + " xmlns='http://www.w3.org/TR/xhtml1/strict' \n" 131 + " exclude-result-prefixes='foo' \n" 132 + " version='1.0'>\n" 133 + " <xsl:output encoding='UTF-8' \n" 134 + " indent='no' \n" 135 + " method='xml' />\n" 136 + " <xsl:template match='/'>\n" 137 + " <html>\n" 138 + " <head>\n" 139 + " <title>Notaries</title>\n" 140 + " </head>\n" 141 + " <body>\n" 142 + " <table>\n" 143 + " <xsl:for-each select='Notaries/Notary'>\n" 144 + " <tr>\n" 145 + " <th>\n" 146 + " <xsl:value-of select='@name' />\n" 147 + " </th>\n" 148 + " </tr>\n" 149 + " </xsl:for-each>\n" 150 + " </table>\n" 151 + " </body>\n" 152 + " </html>\n" 153 + " </xsl:template>\n" 154 + "</xsl:stylesheet>\n"; 155 156 private static final String[] canonicalizationMethods = new String[] { 157 CanonicalizationMethod.EXCLUSIVE, 158 CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS, 159 CanonicalizationMethod.INCLUSIVE, 160 CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS 161 }; 162 163 private static final String[] xml_transforms = new String[] { 164 Transform.XSLT, 165 Transform.XPATH, 166 Transform.XPATH2, 167 CanonicalizationMethod.EXCLUSIVE, 168 CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS, 169 CanonicalizationMethod.INCLUSIVE, 170 CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, 171 }; 172 173 private static final String[] non_xml_transforms = new String[] { 174 null, Transform.BASE64 175 }; 176 177 private static final String[] signatureMethods = new String[] { 178 SignatureMethod.DSA_SHA1, 179 SignatureMethod.RSA_SHA1, 180 SignatureMethod.HMAC_SHA1 181 }; 182 183 private static enum Content { 184 Xml, Text, Base64, NotExisitng 185 } 186 187 private static enum KeyInfoType { 188 KeyValue, x509data, KeyName 189 } 190 191 private static boolean result = true; 192 193 public static void main(String args[]) throws Exception { 194 setup(); 195 test_create_signature_enveloped_dsa(1024); 196 test_create_signature_enveloped_dsa(2048); 197 test_create_signature_enveloping_b64_dsa(); 198 test_create_signature_enveloping_dsa(); 199 test_create_signature_enveloping_hmac_sha1_40(); 200 test_create_signature_enveloping_hmac_sha256(); 201 test_create_signature_enveloping_hmac_sha384(); 202 test_create_signature_enveloping_hmac_sha512(); 203 test_create_signature_enveloping_rsa(); 204 test_create_signature_external_b64_dsa(); 205 test_create_signature_external_dsa(); 206 test_create_signature_keyname(); 207 test_create_signature_retrievalmethod_rawx509crt(); 208 test_create_signature_x509_crt_crl(); 209 test_create_signature_x509_crt(); 210 test_create_signature_x509_is(); 211 test_create_signature_x509_ski(); 212 test_create_signature_x509_sn(); 213 test_create_signature(); 214 test_create_exc_signature(); 215 test_create_sign_spec(); 216 test_create_signature_enveloping_sha256_dsa(); 217 test_create_signature_enveloping_sha384_rsa_sha256(); 218 test_create_signature_enveloping_sha512_rsa_sha384(); 219 test_create_signature_enveloping_sha512_rsa_sha512(); 220 test_create_signature_reference_dependency(); 221 test_create_signature_with_attr_in_no_namespace(); 222 test_create_signature_with_empty_id(); 223 224 // run tests for detached signatures with local http server 225 try (Http server = Http.startServer()) { 226 server.start(); 227 228 // tests for XML documents 229 Arrays.stream(canonicalizationMethods).forEach(c -> 230 Arrays.stream(signatureMethods).forEach(s -> 231 Arrays.stream(xml_transforms).forEach(t -> 232 Arrays.stream(KeyInfoType.values()).forEach(k -> { 233 test_create_detached_signature(c, s, t, k, 234 Content.Xml, server.getPort(), false, null); 235 })))); 236 237 // tests for text data with no transform 238 Arrays.stream(canonicalizationMethods).forEach(c -> 239 Arrays.stream(signatureMethods).forEach(s -> 240 Arrays.stream(KeyInfoType.values()).forEach(k -> { 241 test_create_detached_signature(c, s, null, k, 242 Content.Text, server.getPort(), false, null); 243 }))); 244 245 // tests for base64 data 246 Arrays.stream(canonicalizationMethods).forEach(c -> 247 Arrays.stream(signatureMethods).forEach(s -> 248 Arrays.stream(non_xml_transforms).forEach(t -> 249 Arrays.stream(KeyInfoType.values()).forEach(k -> { 250 test_create_detached_signature(c, s, t, k, 251 Content.Base64, server.getPort(), 252 false, null); 253 })))); 254 255 // negative tests 256 257 // unknown CanonicalizationMethod 258 test_create_detached_signature( 259 CanonicalizationMethod.EXCLUSIVE + BOGUS, 260 SignatureMethod.DSA_SHA1, 261 CanonicalizationMethod.INCLUSIVE, 262 KeyInfoType.KeyName, 263 Content.Xml, 264 server.getPort(), 265 true, 266 NoSuchAlgorithmException.class); 267 268 // unknown SignatureMethod 269 test_create_detached_signature( 270 CanonicalizationMethod.EXCLUSIVE, 271 SignatureMethod.DSA_SHA1 + BOGUS, 272 CanonicalizationMethod.INCLUSIVE, 273 KeyInfoType.KeyName, Content.Xml, 274 server.getPort(), 275 true, 276 NoSuchAlgorithmException.class); 277 278 // unknown Transform 279 test_create_detached_signature( 280 CanonicalizationMethod.EXCLUSIVE, 281 SignatureMethod.DSA_SHA1, 282 CanonicalizationMethod.INCLUSIVE + BOGUS, 283 KeyInfoType.KeyName, Content.Xml, 284 server.getPort(), 285 true, 286 NoSuchAlgorithmException.class); 287 288 // no source document 289 test_create_detached_signature( 290 CanonicalizationMethod.EXCLUSIVE, 291 SignatureMethod.DSA_SHA1, 292 CanonicalizationMethod.INCLUSIVE, 293 KeyInfoType.KeyName, 294 Content.NotExisitng, 295 server.getPort(), 296 true, 297 XMLSignatureException.class); 298 299 // wrong transform for text data 300 test_create_detached_signature( 301 CanonicalizationMethod.EXCLUSIVE, 302 SignatureMethod.DSA_SHA1, 303 CanonicalizationMethod.INCLUSIVE, 304 KeyInfoType.KeyName, 305 Content.Text, 306 server.getPort(), 307 true, 308 XMLSignatureException.class); 309 } 310 311 if (!result) { 312 throw new RuntimeException("At least one test case failed"); 313 } 314 } 315 316 private static void setup() throws Exception { 317 fac = XMLSignatureFactory.getInstance(); 318 kifac = fac.getKeyInfoFactory(); 319 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 320 dbf.setNamespaceAware(true); 321 db = dbf.newDocumentBuilder(); 322 323 // get key & self-signed certificate from keystore 324 FileInputStream fis = new FileInputStream(KEYSTORE); 325 ks = KeyStore.getInstance("JKS"); 326 ks.load(fis, "changeit".toCharArray()); 327 signingKey = ks.getKey("user", "changeit".toCharArray()); 328 signingCert = ks.getCertificate("user"); 329 validatingKey = signingCert.getPublicKey(); 330 331 // create common objects 332 withoutComments = fac.newCanonicalizationMethod 333 (CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec)null); 334 dsaSha1 = fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null); 335 dsaSha256 = fac.newSignatureMethod(DSA_SHA256, null); 336 sha1 = fac.newDigestMethod(DigestMethod.SHA1, null); 337 sha256 = fac.newDigestMethod(DigestMethod.SHA256, null); 338 sha384 = fac.newDigestMethod 339 ("http://www.w3.org/2001/04/xmldsig-more#sha384", null); 340 sha512 = fac.newDigestMethod(DigestMethod.SHA512, null); 341 dsa1024 = kifac.newKeyInfo(Collections.singletonList 342 (kifac.newKeyValue(validatingKey))); 343 dsa2048 = kifac.newKeyInfo(Collections.singletonList 344 (kifac.newKeyValue(getPublicKey("DSA", 2048)))); 345 rsa = kifac.newKeyInfo(Collections.singletonList 346 (kifac.newKeyValue(getPublicKey("RSA", 512)))); 347 rsa1024 = kifac.newKeyInfo(Collections.singletonList 348 (kifac.newKeyValue(getPublicKey("RSA", 1024)))); 349 rsaSha1 = fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null); 350 rsaSha256 = fac.newSignatureMethod 351 ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", null); 352 rsaSha384 = fac.newSignatureMethod 353 ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", null); 354 rsaSha512 = fac.newSignatureMethod 355 ("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", null); 356 sks = new KeySelectors.SecretKeySelector("secret".getBytes("ASCII")); 357 358 httpUd = new HttpURIDereferencer(); 359 } 360 361 static void test_create_signature_enveloped_dsa(int size) throws Exception { 362 System.out.println("* Generating signature-enveloped-dsa-" 363 + size + ".xml"); 364 SignatureMethod sm = null; 365 KeyInfo ki = null; 366 Key privKey; 367 if (size == 1024) { 368 sm = dsaSha1; 369 ki = dsa1024; 370 privKey = signingKey; 371 } else if (size == 2048) { 372 sm = dsaSha256; 373 ki = dsa2048; 374 privKey = getPrivateKey("DSA", 2048); 375 } else throw new RuntimeException("unsupported keysize:" + size); 376 377 // create SignedInfo 378 SignedInfo si = fac.newSignedInfo 379 (withoutComments, sm, Collections.singletonList 380 (fac.newReference 381 ("", sha1, Collections.singletonList 382 (fac.newTransform(Transform.ENVELOPED, 383 (TransformParameterSpec) null)), 384 null, null))); 385 386 // create XMLSignature 387 XMLSignature sig = fac.newXMLSignature(si, ki); 388 389 Document doc = db.newDocument(); 390 Element envelope = doc.createElementNS 391 ("http://example.org/envelope", "Envelope"); 392 envelope.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, 393 "xmlns", "http://example.org/envelope"); 394 doc.appendChild(envelope); 395 396 DOMSignContext dsc = new DOMSignContext(privKey, envelope); 397 398 sig.sign(dsc); 399 // StringWriter sw = new StringWriter(); 400 // dumpDocument(doc, sw); 401 // System.out.println(sw.toString()); 402 403 DOMValidateContext dvc = new DOMValidateContext 404 (kvks, envelope.getFirstChild()); 405 XMLSignature sig2 = fac.unmarshalXMLSignature(dvc); 406 407 if (sig.equals(sig2) == false) { 408 throw new Exception 409 ("Unmarshalled signature is not equal to generated signature"); 410 } 411 412 if (sig2.validate(dvc) == false) { 413 throw new Exception("Validation of generated signature failed"); 414 } 415 System.out.println(); 416 } 417 418 static void test_create_signature_enveloping_b64_dsa() throws Exception { 419 System.out.println("* Generating signature-enveloping-b64-dsa.xml"); 420 test_create_signature_enveloping 421 (sha1, dsaSha1, dsa1024, signingKey, kvks, true); 422 System.out.println(); 423 } 424 425 static void test_create_signature_enveloping_dsa() throws Exception { 426 System.out.println("* Generating signature-enveloping-dsa.xml"); 427 test_create_signature_enveloping 428 (sha1, dsaSha1, dsa1024, signingKey, kvks, false); 429 System.out.println(); 430 } 431 432 static void test_create_signature_enveloping_sha256_dsa() throws Exception { 433 System.out.println("* Generating signature-enveloping-sha256-dsa.xml"); 434 test_create_signature_enveloping 435 (sha256, dsaSha1, dsa1024, signingKey, kvks, false); 436 System.out.println(); 437 } 438 439 static void test_create_signature_enveloping_hmac_sha1_40() 440 throws Exception { 441 System.out.println("* Generating signature-enveloping-hmac-sha1-40.xml"); 442 SignatureMethod hmacSha1 = fac.newSignatureMethod 443 (SignatureMethod.HMAC_SHA1, new HMACParameterSpec(40)); 444 try { 445 test_create_signature_enveloping(sha1, hmacSha1, null, 446 getSecretKey("secret".getBytes("ASCII")), sks, false); 447 } catch (Exception e) { 448 if (!(e instanceof XMLSignatureException)) { 449 throw e; 450 } 451 } 452 System.out.println(); 453 } 454 455 static void test_create_signature_enveloping_hmac_sha256() 456 throws Exception { 457 System.out.println("* Generating signature-enveloping-hmac-sha256.xml"); 458 SignatureMethod hmacSha256 = fac.newSignatureMethod 459 ("http://www.w3.org/2001/04/xmldsig-more#hmac-sha256", null); 460 test_create_signature_enveloping(sha1, hmacSha256, null, 461 getSecretKey("secret".getBytes("ASCII")), sks, false); 462 System.out.println(); 463 } 464 465 static void test_create_signature_enveloping_hmac_sha384() 466 throws Exception { 467 System.out.println("* Generating signature-enveloping-hmac-sha384.xml"); 468 SignatureMethod hmacSha384 = fac.newSignatureMethod 469 ("http://www.w3.org/2001/04/xmldsig-more#hmac-sha384", null); 470 test_create_signature_enveloping(sha1, hmacSha384, null, 471 getSecretKey("secret".getBytes("ASCII")), sks, false); 472 System.out.println(); 473 } 474 475 static void test_create_signature_enveloping_hmac_sha512() 476 throws Exception { 477 System.out.println("* Generating signature-enveloping-hmac-sha512.xml"); 478 SignatureMethod hmacSha512 = fac.newSignatureMethod 479 ("http://www.w3.org/2001/04/xmldsig-more#hmac-sha512", null); 480 test_create_signature_enveloping(sha1, hmacSha512, null, 481 getSecretKey("secret".getBytes("ASCII")), sks, false); 482 System.out.println(); 483 } 484 485 static void test_create_signature_enveloping_rsa() throws Exception { 486 System.out.println("* Generating signature-enveloping-rsa.xml"); 487 test_create_signature_enveloping(sha1, rsaSha1, rsa, 488 getPrivateKey("RSA", 512), kvks, false); 489 System.out.println(); 490 } 491 492 static void test_create_signature_enveloping_sha384_rsa_sha256() 493 throws Exception { 494 System.out.println("* Generating signature-enveloping-sha384-rsa_sha256.xml"); 495 test_create_signature_enveloping(sha384, rsaSha256, rsa, 496 getPrivateKey("RSA", 512), kvks, false); 497 System.out.println(); 498 } 499 500 static void test_create_signature_enveloping_sha512_rsa_sha384() 501 throws Exception { 502 System.out.println("* Generating signature-enveloping-sha512-rsa_sha384.xml"); 503 test_create_signature_enveloping(sha512, rsaSha384, rsa1024, 504 getPrivateKey("RSA", 1024), kvks, false); 505 System.out.println(); 506 } 507 508 static void test_create_signature_enveloping_sha512_rsa_sha512() 509 throws Exception { 510 System.out.println("* Generating signature-enveloping-sha512-rsa_sha512.xml"); 511 test_create_signature_enveloping(sha512, rsaSha512, rsa1024, 512 getPrivateKey("RSA", 1024), kvks, false); 513 System.out.println(); 514 } 515 516 static void test_create_signature_external_b64_dsa() throws Exception { 517 System.out.println("* Generating signature-external-b64-dsa.xml"); 518 test_create_signature_external(dsaSha1, dsa1024, signingKey, kvks, true); 519 System.out.println(); 520 } 521 522 static void test_create_signature_external_dsa() throws Exception { 523 System.out.println("* Generating signature-external-dsa.xml"); 524 test_create_signature_external(dsaSha1, dsa1024, signingKey, kvks, false); 525 System.out.println(); 526 } 527 528 static void test_create_signature_keyname() throws Exception { 529 System.out.println("* Generating signature-keyname.xml"); 530 KeyInfo kn = kifac.newKeyInfo(Collections.singletonList 531 (kifac.newKeyName("user"))); 532 test_create_signature_external(dsaSha1, kn, signingKey, 533 new X509KeySelector(ks), false); 534 System.out.println(); 535 } 536 537 static void test_create_signature_retrievalmethod_rawx509crt() 538 throws Exception { 539 System.out.println( 540 "* Generating signature-retrievalmethod-rawx509crt.xml"); 541 KeyInfo rm = kifac.newKeyInfo(Collections.singletonList 542 (kifac.newRetrievalMethod 543 ("certs/user.crt", X509Data.RAW_X509_CERTIFICATE_TYPE, null))); 544 test_create_signature_external(dsaSha1, rm, signingKey, 545 new X509KeySelector(ks), false); 546 System.out.println(); 547 } 548 549 static void test_create_signature_x509_crt_crl() throws Exception { 550 System.out.println("* Generating signature-x509-crt-crl.xml"); 551 List<Object> xds = new ArrayList<Object>(); 552 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 553 xds.add(signingCert); 554 FileInputStream fis = new FileInputStream(CRL); 555 X509CRL crl = (X509CRL) cf.generateCRL(fis); 556 fis.close(); 557 xds.add(crl); 558 KeyInfo crt_crl = kifac.newKeyInfo(Collections.singletonList 559 (kifac.newX509Data(xds))); 560 561 test_create_signature_external(dsaSha1, crt_crl, signingKey, 562 new X509KeySelector(ks), false); 563 System.out.println(); 564 } 565 566 static void test_create_signature_x509_crt() throws Exception { 567 System.out.println("* Generating signature-x509-crt.xml"); 568 KeyInfo crt = kifac.newKeyInfo(Collections.singletonList 569 (kifac.newX509Data(Collections.singletonList(signingCert)))); 570 571 test_create_signature_external(dsaSha1, crt, signingKey, 572 new X509KeySelector(ks), false); 573 System.out.println(); 574 } 575 576 static void test_create_signature_x509_is() throws Exception { 577 System.out.println("* Generating signature-x509-is.xml"); 578 KeyInfo is = kifac.newKeyInfo(Collections.singletonList 579 (kifac.newX509Data(Collections.singletonList 580 (kifac.newX509IssuerSerial 581 ("CN=User", new BigInteger("45ef2729", 16)))))); 582 test_create_signature_external(dsaSha1, is, signingKey, 583 new X509KeySelector(ks), false); 584 System.out.println(); 585 } 586 587 static void test_create_signature_x509_ski() throws Exception { 588 System.out.println("* Generating signature-x509-ski.xml"); 589 KeyInfo ski = kifac.newKeyInfo(Collections.singletonList 590 (kifac.newX509Data(Collections.singletonList 591 ("keyid".getBytes("ASCII"))))); 592 593 test_create_signature_external(dsaSha1, ski, signingKey, 594 KeySelector.singletonKeySelector(validatingKey), false); 595 System.out.println(); 596 } 597 598 static void test_create_signature_x509_sn() throws Exception { 599 System.out.println("* Generating signature-x509-sn.xml"); 600 KeyInfo sn = kifac.newKeyInfo(Collections.singletonList 601 (kifac.newX509Data(Collections.singletonList("CN=User")))); 602 603 test_create_signature_external(dsaSha1, sn, signingKey, 604 new X509KeySelector(ks), false); 605 System.out.println(); 606 } 607 608 static void test_create_signature_reference_dependency() throws Exception { 609 System.out.println("* Generating signature-reference-dependency.xml"); 610 // create references 611 List<Reference> refs = Collections.singletonList 612 (fac.newReference("#object-1", sha1)); 613 614 // create SignedInfo 615 SignedInfo si = fac.newSignedInfo(withoutComments, rsaSha1, refs); 616 617 // create objects 618 List<XMLStructure> objs = new ArrayList<XMLStructure>(); 619 620 // Object 1 621 List<Reference> manRefs = Collections.singletonList 622 (fac.newReference("#object-2", sha1)); 623 objs.add(fac.newXMLObject(Collections.singletonList 624 (fac.newManifest(manRefs, "manifest-1")), "object-1", null, null)); 625 626 // Object 2 627 Document doc = db.newDocument(); 628 Element nc = doc.createElementNS(null, "NonCommentandus"); 629 nc.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", ""); 630 nc.appendChild(doc.createComment(" Commentandum ")); 631 objs.add(fac.newXMLObject(Collections.singletonList 632 (new DOMStructure(nc)), "object-2", null, null)); 633 634 // create XMLSignature 635 XMLSignature sig = fac.newXMLSignature(si, rsa, objs, "signature", null); 636 DOMSignContext dsc = new DOMSignContext(getPrivateKey("RSA", 512), doc); 637 638 sig.sign(dsc); 639 640 // dumpDocument(doc, new PrintWriter(System.out)); 641 642 DOMValidateContext dvc = new DOMValidateContext 643 (kvks, doc.getDocumentElement()); 644 XMLSignature sig2 = fac.unmarshalXMLSignature(dvc); 645 646 if (sig.equals(sig2) == false) { 647 throw new Exception 648 ("Unmarshalled signature is not equal to generated signature"); 649 } 650 if (sig2.validate(dvc) == false) { 651 throw new Exception("Validation of generated signature failed"); 652 } 653 654 System.out.println(); 655 } 656 657 static void test_create_signature_with_attr_in_no_namespace() 658 throws Exception 659 { 660 System.out.println 661 ("* Generating signature-with-attr-in-no-namespace.xml"); 662 663 // create references 664 List<Reference> refs = Collections.singletonList 665 (fac.newReference("#unknown", sha1)); 666 667 // create SignedInfo 668 SignedInfo si = fac.newSignedInfo(withoutComments, rsaSha1, refs); 669 670 // create object-1 671 Document doc = db.newDocument(); 672 Element nc = doc.createElementNS(null, "NonCommentandus"); 673 // add attribute with no namespace 674 nc.setAttribute("Id", "unknown"); 675 XMLObject obj = fac.newXMLObject(Collections.singletonList 676 (new DOMStructure(nc)), "object-1", null, null); 677 678 // create XMLSignature 679 XMLSignature sig = fac.newXMLSignature(si, rsa, 680 Collections.singletonList(obj), 681 "signature", null); 682 DOMSignContext dsc = new DOMSignContext(getPrivateKey("RSA", 512), doc); 683 dsc.setIdAttributeNS(nc, null, "Id"); 684 685 sig.sign(dsc); 686 687 // dumpDocument(doc, new PrintWriter(System.out)); 688 689 DOMValidateContext dvc = new DOMValidateContext 690 (kvks, doc.getDocumentElement()); 691 dvc.setIdAttributeNS(nc, null, "Id"); 692 XMLSignature sig2 = fac.unmarshalXMLSignature(dvc); 693 694 if (sig.equals(sig2) == false) { 695 throw new Exception 696 ("Unmarshalled signature is not equal to generated signature"); 697 } 698 if (sig2.validate(dvc) == false) { 699 throw new Exception("Validation of generated signature failed"); 700 } 701 702 System.out.println(); 703 } 704 705 static void test_create_signature_with_empty_id() throws Exception { 706 System.out.println("* Generating signature-with-empty-id.xml"); 707 708 // create references 709 List<Reference> refs = Collections.singletonList 710 (fac.newReference("#", sha1)); 711 712 // create SignedInfo 713 SignedInfo si = fac.newSignedInfo(withoutComments, rsaSha1, refs); 714 715 // create object with empty id 716 Document doc = db.newDocument(); 717 XMLObject obj = fac.newXMLObject(Collections.singletonList 718 (new DOMStructure(doc.createTextNode("I am the text."))), 719 "", "text/plain", null); 720 721 // create XMLSignature 722 XMLSignature sig = fac.newXMLSignature(si, rsa, 723 Collections.singletonList(obj), 724 "signature", null); 725 DOMSignContext dsc = new DOMSignContext(getPrivateKey("RSA", 512), doc); 726 sig.sign(dsc); 727 } 728 729 static void test_create_signature() throws Exception { 730 System.out.println("* Generating signature.xml"); 731 732 // create references 733 List<Reference> refs = new ArrayList<Reference>(); 734 735 // Reference 1 736 refs.add(fac.newReference(STYLESHEET, sha1)); 737 738 // Reference 2 739 refs.add(fac.newReference 740 (STYLESHEET_B64, 741 sha1, Collections.singletonList 742 (fac.newTransform(Transform.BASE64, 743 (TransformParameterSpec) null)), null, null)); 744 745 // Reference 3 746 refs.add(fac.newReference("#object-1", sha1, Collections.singletonList 747 (fac.newTransform(Transform.XPATH, 748 new XPathFilterParameterSpec("self::text()"))), 749 XMLObject.TYPE, null)); 750 751 // Reference 4 752 String expr = "\n" 753 + " ancestor-or-self::dsig:SignedInfo " + "\n" 754 + " and " + "\n" 755 + " count(ancestor-or-self::dsig:Reference | " + "\n" 756 + " here()/ancestor::dsig:Reference[1]) > " + "\n" 757 + " count(ancestor-or-self::dsig:Reference) " + "\n" 758 + " or " + "\n" 759 + " count(ancestor-or-self::node() | " + "\n" 760 + " id('notaries')) = " + "\n" 761 + " count(ancestor-or-self::node()) " + "\n"; 762 763 XPathFilterParameterSpec xfp = new XPathFilterParameterSpec(expr, 764 Collections.singletonMap("dsig", XMLSignature.XMLNS)); 765 refs.add(fac.newReference("", sha1, Collections.singletonList 766 (fac.newTransform(Transform.XPATH, xfp)), 767 XMLObject.TYPE, null)); 768 769 // Reference 5 770 refs.add(fac.newReference("#object-2", sha1, Collections.singletonList 771 (fac.newTransform 772 (Transform.BASE64, (TransformParameterSpec) null)), 773 XMLObject.TYPE, null)); 774 775 // Reference 6 776 refs.add(fac.newReference 777 ("#manifest-1", sha1, null, Manifest.TYPE, null)); 778 779 // Reference 7 780 refs.add(fac.newReference("#signature-properties-1", sha1, null, 781 SignatureProperties.TYPE, null)); 782 783 // Reference 8 784 List<Transform> transforms = new ArrayList<Transform>(); 785 transforms.add(fac.newTransform 786 (Transform.ENVELOPED, (TransformParameterSpec) null)); 787 refs.add(fac.newReference("", sha1, transforms, null, null)); 788 789 // Reference 9 790 transforms.add(fac.newTransform 791 (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, 792 (TransformParameterSpec) null)); 793 refs.add(fac.newReference("", sha1, transforms, null, null)); 794 795 // Reference 10 796 Transform env = fac.newTransform 797 (Transform.ENVELOPED, (TransformParameterSpec) null); 798 refs.add(fac.newReference("#xpointer(/)", 799 sha1, Collections.singletonList(env), null, null)); 800 801 // Reference 11 802 transforms.clear(); 803 transforms.add(fac.newTransform 804 (Transform.ENVELOPED, (TransformParameterSpec) null)); 805 transforms.add(fac.newTransform 806 (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, 807 (TransformParameterSpec) null)); 808 refs.add(fac.newReference("#xpointer(/)", sha1, transforms, 809 null, null)); 810 811 // Reference 12 812 refs.add 813 (fac.newReference("#object-3", sha1, null, XMLObject.TYPE, null)); 814 815 // Reference 13 816 Transform withComments = fac.newTransform 817 (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, 818 (TransformParameterSpec) null); 819 refs.add(fac.newReference("#object-3", sha1, 820 Collections.singletonList(withComments), XMLObject.TYPE, null)); 821 822 // Reference 14 823 refs.add(fac.newReference("#xpointer(id('object-3'))", sha1, null, 824 XMLObject.TYPE, null)); 825 826 // Reference 15 827 withComments = fac.newTransform 828 (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, 829 (TransformParameterSpec) null); 830 refs.add(fac.newReference("#xpointer(id('object-3'))", sha1, 831 Collections.singletonList(withComments), XMLObject.TYPE, null)); 832 833 // Reference 16 834 refs.add(fac.newReference("#reference-2", sha1)); 835 836 // Reference 17 837 refs.add(fac.newReference("#manifest-reference-1", sha1, null, 838 null, "reference-1")); 839 840 // Reference 18 841 refs.add(fac.newReference("#reference-1", sha1, null, null, 842 "reference-2")); 843 844 // create SignedInfo 845 SignedInfo si = fac.newSignedInfo(withoutComments, dsaSha1, refs); 846 847 // create keyinfo 848 XPathFilterParameterSpec xpf = new XPathFilterParameterSpec( 849 "ancestor-or-self::dsig:X509Data", 850 Collections.singletonMap("dsig", XMLSignature.XMLNS)); 851 RetrievalMethod rm = kifac.newRetrievalMethod("#object-4", 852 X509Data.TYPE, Collections.singletonList(fac.newTransform 853 (Transform.XPATH, xpf))); 854 KeyInfo ki = kifac.newKeyInfo(Collections.singletonList(rm), null); 855 856 Document doc = db.newDocument(); 857 858 // create objects 859 List<XMLStructure> objs = new ArrayList<XMLStructure>(); 860 861 // Object 1 862 objs.add(fac.newXMLObject(Collections.singletonList 863 (new DOMStructure(doc.createTextNode("I am the text."))), 864 "object-1", "text/plain", null)); 865 866 // Object 2 867 objs.add(fac.newXMLObject(Collections.singletonList 868 (new DOMStructure(doc.createTextNode("SSBhbSB0aGUgdGV4dC4="))), 869 "object-2", "text/plain", Transform.BASE64)); 870 871 // Object 3 872 Element nc = doc.createElementNS(null, "NonCommentandus"); 873 nc.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", ""); 874 nc.appendChild(doc.createComment(" Commentandum ")); 875 objs.add(fac.newXMLObject(Collections.singletonList 876 (new DOMStructure(nc)), "object-3", null, null)); 877 878 // Manifest 879 List<Reference> manRefs = new ArrayList<Reference>(); 880 881 // Manifest Reference 1 882 manRefs.add(fac.newReference(STYLESHEET, 883 sha1, null, null, "manifest-reference-1")); 884 885 // Manifest Reference 2 886 manRefs.add(fac.newReference("#reference-1", sha1)); 887 888 // Manifest Reference 3 889 List<Transform> manTrans = new ArrayList<Transform>(); 890 Document docxslt = db.parse(new ByteArrayInputStream(xslt.getBytes())); 891 Node xslElem = docxslt.getDocumentElement(); 892 893 manTrans.add(fac.newTransform(Transform.XSLT, 894 new XSLTTransformParameterSpec(new DOMStructure(xslElem)))); 895 manTrans.add(fac.newTransform(CanonicalizationMethod.INCLUSIVE, 896 (TransformParameterSpec) null)); 897 manRefs.add(fac.newReference("#notaries", sha1, manTrans, null, null)); 898 899 objs.add(fac.newXMLObject(Collections.singletonList 900 (fac.newManifest(manRefs, "manifest-1")), null, null, null)); 901 902 // SignatureProperties 903 Element sa = doc.createElementNS("urn:demo", "SignerAddress"); 904 sa.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "urn:demo"); 905 Element ip = doc.createElementNS("urn:demo", "IP"); 906 ip.appendChild(doc.createTextNode("192.168.21.138")); 907 sa.appendChild(ip); 908 SignatureProperty sp = fac.newSignatureProperty 909 (Collections.singletonList(new DOMStructure(sa)), 910 "#signature", null); 911 SignatureProperties sps = fac.newSignatureProperties 912 (Collections.singletonList(sp), "signature-properties-1"); 913 objs.add(fac.newXMLObject(Collections.singletonList(sps), null, 914 null, null)); 915 916 // Object 4 917 List<Object> xds = new ArrayList<Object>(); 918 xds.add("CN=User"); 919 xds.add(kifac.newX509IssuerSerial 920 ("CN=User", new BigInteger("45ef2729", 16))); 921 xds.add(signingCert); 922 objs.add(fac.newXMLObject(Collections.singletonList 923 (kifac.newX509Data(xds)), "object-4", null, null)); 924 925 // create XMLSignature 926 XMLSignature sig = fac.newXMLSignature(si, ki, objs, "signature", null); 927 928 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 929 dbf.setNamespaceAware(true); 930 dbf.setValidating(false); 931 Document envDoc = dbf.newDocumentBuilder().parse 932 (new FileInputStream(ENVELOPE)); 933 Element ys = (Element) 934 envDoc.getElementsByTagName("YoursSincerely").item(0); 935 936 DOMSignContext dsc = new DOMSignContext(signingKey, ys); 937 dsc.setURIDereferencer(httpUd); 938 939 sig.sign(dsc); 940 941 // StringWriter sw = new StringWriter(); 942 // dumpDocument(envDoc, sw); 943 944 NodeList nl = 945 envDoc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); 946 if (nl.getLength() == 0) { 947 throw new Exception("Couldn't find signature Element"); 948 } 949 Element sigElement = (Element) nl.item(0); 950 951 DOMValidateContext dvc = new DOMValidateContext 952 (new X509KeySelector(ks), sigElement); 953 dvc.setURIDereferencer(httpUd); 954 File f = new File( 955 System.getProperty("dir.test.vector.baltimore") + 956 System.getProperty("file.separator") + 957 "merlin-xmldsig-twenty-three" + 958 System.getProperty("file.separator")); 959 dvc.setBaseURI(f.toURI().toString()); 960 961 XMLSignature sig2 = fac.unmarshalXMLSignature(dvc); 962 963 if (sig.equals(sig2) == false) { 964 throw new Exception 965 ("Unmarshalled signature is not equal to generated signature"); 966 } 967 if (sig2.validate(dvc) == false) { 968 throw new Exception("Validation of generated signature failed"); 969 } 970 System.out.println(); 971 } 972 973 private static void dumpDocument(Document doc, Writer w) throws Exception { 974 TransformerFactory tf = TransformerFactory.newInstance(); 975 Transformer trans = tf.newTransformer(); 976 // trans.setOutputProperty(OutputKeys.INDENT, "yes"); 977 trans.transform(new DOMSource(doc), new StreamResult(w)); 978 } 979 980 private static void test_create_signature_external 981 (SignatureMethod sm, KeyInfo ki, Key signingKey, KeySelector ks, 982 boolean b64) throws Exception { 983 984 // create reference 985 Reference ref; 986 if (b64) { 987 ref = fac.newReference 988 (STYLESHEET_B64, 989 sha1, Collections.singletonList 990 (fac.newTransform(Transform.BASE64, 991 (TransformParameterSpec) null)), null, null); 992 } else { 993 ref = fac.newReference(STYLESHEET, sha1); 994 } 995 996 // create SignedInfo 997 SignedInfo si = fac.newSignedInfo(withoutComments, sm, 998 Collections.singletonList(ref)); 999 1000 Document doc = db.newDocument(); 1001 1002 // create XMLSignature 1003 XMLSignature sig = fac.newXMLSignature(si, ki); 1004 1005 DOMSignContext dsc = new DOMSignContext(signingKey, doc); 1006 dsc.setURIDereferencer(httpUd); 1007 1008 sig.sign(dsc); 1009 1010 DOMValidateContext dvc = new DOMValidateContext 1011 (ks, doc.getDocumentElement()); 1012 File f = new File(DATA_DIR); 1013 dvc.setBaseURI(f.toURI().toString()); 1014 dvc.setURIDereferencer(httpUd); 1015 1016 XMLSignature sig2 = fac.unmarshalXMLSignature(dvc); 1017 1018 if (sig.equals(sig2) == false) { 1019 throw new Exception 1020 ("Unmarshalled signature is not equal to generated signature"); 1021 } 1022 if (sig2.validate(dvc) == false) { 1023 throw new Exception("Validation of generated signature failed"); 1024 } 1025 } 1026 1027 private static void test_create_signature_enveloping 1028 (DigestMethod dm, SignatureMethod sm, KeyInfo ki, Key signingKey, 1029 KeySelector ks, boolean b64) throws Exception { 1030 1031 // create reference 1032 Reference ref; 1033 if (b64) { 1034 ref = fac.newReference("#object", dm, Collections.singletonList 1035 (fac.newTransform(Transform.BASE64, 1036 (TransformParameterSpec) null)), null, null); 1037 } else { 1038 ref = fac.newReference("#object", dm); 1039 } 1040 1041 // create SignedInfo 1042 SignedInfo si = fac.newSignedInfo(withoutComments, sm, 1043 Collections.singletonList(ref)); 1044 1045 Document doc = db.newDocument(); 1046 // create Objects 1047 String text = b64 ? "c29tZSB0ZXh0" : "some text"; 1048 XMLObject obj = fac.newXMLObject(Collections.singletonList 1049 (new DOMStructure(doc.createTextNode(text))), 1050 "object", null, null); 1051 1052 // create XMLSignature 1053 XMLSignature sig = fac.newXMLSignature 1054 (si, ki, Collections.singletonList(obj), null, null); 1055 1056 DOMSignContext dsc = new DOMSignContext(signingKey, doc); 1057 1058 sig.sign(dsc); 1059 1060 // dumpDocument(doc, new FileWriter("/tmp/foo.xml")); 1061 1062 DOMValidateContext dvc = new DOMValidateContext 1063 (ks, doc.getDocumentElement()); 1064 XMLSignature sig2 = fac.unmarshalXMLSignature(dvc); 1065 1066 if (sig.equals(sig2) == false) { 1067 throw new Exception 1068 ("Unmarshalled signature is not equal to generated signature"); 1069 } 1070 if (sig2.validate(dvc) == false) { 1071 throw new Exception("Validation of generated signature failed"); 1072 } 1073 } 1074 1075 static void test_create_exc_signature() throws Exception { 1076 System.out.println("* Generating exc_signature.xml"); 1077 List<Reference> refs = new ArrayList<Reference>(4); 1078 1079 // create reference 1 1080 refs.add(fac.newReference 1081 ("#xpointer(id('to-be-signed'))", 1082 fac.newDigestMethod(DigestMethod.SHA1, null), 1083 Collections.singletonList 1084 (fac.newTransform(CanonicalizationMethod.EXCLUSIVE, 1085 (TransformParameterSpec) null)), 1086 null, null)); 1087 1088 // create reference 2 1089 List<String> prefixList = new ArrayList<String>(2); 1090 prefixList.add("bar"); 1091 prefixList.add("#default"); 1092 ExcC14NParameterSpec params = new ExcC14NParameterSpec(prefixList); 1093 refs.add(fac.newReference 1094 ("#xpointer(id('to-be-signed'))", 1095 fac.newDigestMethod(DigestMethod.SHA1, null), 1096 Collections.singletonList 1097 (fac.newTransform(CanonicalizationMethod.EXCLUSIVE, params)), 1098 null, null)); 1099 1100 // create reference 3 1101 refs.add(fac.newReference 1102 ("#xpointer(id('to-be-signed'))", 1103 fac.newDigestMethod(DigestMethod.SHA1, null), 1104 Collections.singletonList(fac.newTransform 1105 (CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS, 1106 (TransformParameterSpec) null)), 1107 null, null)); 1108 1109 // create reference 4 1110 prefixList = new ArrayList<String>(2); 1111 prefixList.add("bar"); 1112 prefixList.add("#default"); 1113 params = new ExcC14NParameterSpec(prefixList); 1114 refs.add(fac.newReference 1115 ("#xpointer(id('to-be-signed'))", 1116 fac.newDigestMethod(DigestMethod.SHA1, null), 1117 Collections.singletonList(fac.newTransform 1118 (CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS, params)), 1119 null, null)); 1120 1121 // create SignedInfo 1122 SignedInfo si = fac.newSignedInfo( 1123 fac.newCanonicalizationMethod 1124 (CanonicalizationMethod.EXCLUSIVE, 1125 (C14NMethodParameterSpec) null), 1126 fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null), refs); 1127 1128 // create KeyInfo 1129 List<XMLStructure> kits = new ArrayList<XMLStructure>(2); 1130 kits.add(kifac.newKeyValue(validatingKey)); 1131 KeyInfo ki = kifac.newKeyInfo(kits); 1132 1133 // create Objects 1134 Document doc = db.newDocument(); 1135 Element baz = doc.createElementNS("urn:bar", "bar:Baz"); 1136 Comment com = doc.createComment(" comment "); 1137 baz.appendChild(com); 1138 XMLObject obj = fac.newXMLObject(Collections.singletonList 1139 (new DOMStructure(baz)), "to-be-signed", null, null); 1140 1141 // create XMLSignature 1142 XMLSignature sig = fac.newXMLSignature 1143 (si, ki, Collections.singletonList(obj), null, null); 1144 1145 Element foo = doc.createElementNS("urn:foo", "Foo"); 1146 foo.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "urn:foo"); 1147 foo.setAttributeNS 1148 ("http://www.w3.org/2000/xmlns/", "xmlns:bar", "urn:bar"); 1149 doc.appendChild(foo); 1150 1151 DOMSignContext dsc = new DOMSignContext(signingKey, foo); 1152 dsc.putNamespacePrefix(XMLSignature.XMLNS, "dsig"); 1153 1154 sig.sign(dsc); 1155 1156 // dumpDocument(doc, new FileWriter("/tmp/foo.xml")); 1157 1158 DOMValidateContext dvc = new DOMValidateContext 1159 (new KeySelectors.KeyValueKeySelector(), foo.getLastChild()); 1160 XMLSignature sig2 = fac.unmarshalXMLSignature(dvc); 1161 1162 if (sig.equals(sig2) == false) { 1163 throw new Exception 1164 ("Unmarshalled signature is not equal to generated signature"); 1165 } 1166 if (sig2.validate(dvc) == false) { 1167 throw new Exception("Validation of generated signature failed"); 1168 } 1169 System.out.println(); 1170 } 1171 1172 static void test_create_sign_spec() throws Exception { 1173 System.out.println("* Generating sign-spec.xml"); 1174 List<Reference> refs = new ArrayList<Reference>(2); 1175 1176 // create reference 1 1177 List<XPathType> types = new ArrayList<XPathType>(3); 1178 types.add(new XPathType(" //ToBeSigned ", XPathType.Filter.INTERSECT)); 1179 types.add(new XPathType(" //NotToBeSigned ", 1180 XPathType.Filter.SUBTRACT)); 1181 types.add(new XPathType(" //ReallyToBeSigned ", 1182 XPathType.Filter.UNION)); 1183 XPathFilter2ParameterSpec xp1 = new XPathFilter2ParameterSpec(types); 1184 refs.add(fac.newReference 1185 ("", fac.newDigestMethod(DigestMethod.SHA1, null), 1186 Collections.singletonList(fac.newTransform(Transform.XPATH2, xp1)), 1187 null, null)); 1188 1189 // create reference 2 1190 List<Transform> trans2 = new ArrayList<Transform>(2); 1191 trans2.add(fac.newTransform(Transform.ENVELOPED, 1192 (TransformParameterSpec) null)); 1193 XPathFilter2ParameterSpec xp2 = new XPathFilter2ParameterSpec 1194 (Collections.singletonList 1195 (new XPathType(" / ", XPathType.Filter.UNION))); 1196 trans2.add(fac.newTransform(Transform.XPATH2, xp2)); 1197 refs.add(fac.newReference("#signature-value", 1198 fac.newDigestMethod(DigestMethod.SHA1, null), trans2, null, null)); 1199 1200 // create SignedInfo 1201 SignedInfo si = fac.newSignedInfo( 1202 fac.newCanonicalizationMethod 1203 (CanonicalizationMethod.INCLUSIVE, 1204 (C14NMethodParameterSpec) null), 1205 fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null), refs); 1206 1207 // create KeyInfo 1208 List<XMLStructure> kits = new ArrayList<XMLStructure>(2); 1209 kits.add(kifac.newKeyValue(validatingKey)); 1210 List<Object> xds = new ArrayList<Object>(2); 1211 xds.add("CN=User"); 1212 xds.add(signingCert); 1213 kits.add(kifac.newX509Data(xds)); 1214 KeyInfo ki = kifac.newKeyInfo(kits); 1215 1216 // create XMLSignature 1217 XMLSignature sig = fac.newXMLSignature 1218 (si, ki, null, null, "signature-value"); 1219 1220 Document doc = db.newDocument(); 1221 Element tbs1 = doc.createElementNS(null, "ToBeSigned"); 1222 Comment tbs1Com = doc.createComment(" comment "); 1223 Element tbs1Data = doc.createElementNS(null, "Data"); 1224 Element tbs1ntbs = doc.createElementNS(null, "NotToBeSigned"); 1225 Element tbs1rtbs = doc.createElementNS(null, "ReallyToBeSigned"); 1226 Comment tbs1rtbsCom = doc.createComment(" comment "); 1227 Element tbs1rtbsData = doc.createElementNS(null, "Data"); 1228 tbs1rtbs.appendChild(tbs1rtbsCom); 1229 tbs1rtbs.appendChild(tbs1rtbsData); 1230 tbs1ntbs.appendChild(tbs1rtbs); 1231 tbs1.appendChild(tbs1Com); 1232 tbs1.appendChild(tbs1Data); 1233 tbs1.appendChild(tbs1ntbs); 1234 1235 Element tbs2 = doc.createElementNS(null, "ToBeSigned"); 1236 Element tbs2Data = doc.createElementNS(null, "Data"); 1237 Element tbs2ntbs = doc.createElementNS(null, "NotToBeSigned"); 1238 Element tbs2ntbsData = doc.createElementNS(null, "Data"); 1239 tbs2ntbs.appendChild(tbs2ntbsData); 1240 tbs2.appendChild(tbs2Data); 1241 tbs2.appendChild(tbs2ntbs); 1242 1243 Element document = doc.createElementNS(null, "Document"); 1244 document.appendChild(tbs1); 1245 document.appendChild(tbs2); 1246 doc.appendChild(document); 1247 1248 DOMSignContext dsc = new DOMSignContext(signingKey, document); 1249 1250 sig.sign(dsc); 1251 1252 // dumpDocument(doc, new FileWriter("/tmp/foo.xml")); 1253 1254 DOMValidateContext dvc = new DOMValidateContext 1255 (new KeySelectors.KeyValueKeySelector(), document.getLastChild()); 1256 XMLSignature sig2 = fac.unmarshalXMLSignature(dvc); 1257 1258 if (sig.equals(sig2) == false) { 1259 throw new Exception 1260 ("Unmarshalled signature is not equal to generated signature"); 1261 } 1262 if (sig2.validate(dvc) == false) { 1263 throw new Exception("Validation of generated signature failed"); 1264 } 1265 System.out.println(); 1266 } 1267 1268 static void test_create_detached_signature(String canonicalizationMethod, 1269 String signatureMethod, String transform, KeyInfoType keyInfo, 1270 Content contentType, int port, boolean expectedFailure, 1271 Class expectedException) { 1272 1273 final String digestMethod = DigestMethod.SHA1; 1274 System.out.println("Test detached signature:"); 1275 System.out.println(" Canonicalization method: " 1276 + canonicalizationMethod); 1277 System.out.println(" Signature method: " + signatureMethod); 1278 System.out.println(" Transform: " + transform); 1279 System.out.println(" Digest method: " + digestMethod); 1280 System.out.println(" KeyInfoType: " + keyInfo); 1281 System.out.println(" Content type: " + contentType); 1282 System.out.println(" Expected failure: " 1283 + (expectedFailure ? "yes" : "no")); 1284 System.out.println(" Expected exception: " 1285 + (expectedException == null ? 1286 "no" : expectedException.getName())); 1287 1288 try { 1289 boolean success = test_create_detached_signature( 1290 canonicalizationMethod, 1291 signatureMethod, 1292 digestMethod, 1293 transform, 1294 keyInfo, 1295 contentType, 1296 port); 1297 1298 if (success && expectedFailure) { 1299 System.out.println("Signature validation unexpectedly passed"); 1300 result = false; 1301 } else if (!success && !expectedFailure) { 1302 System.out.println("Signature validation unexpectedly failed"); 1303 result = false; 1304 } else if (expectedException != null) { 1305 System.out.println("Expected " + expectedException 1306 + " not thrown"); 1307 result = false; 1308 } 1309 } catch (Exception e) { 1310 if (expectedException == null 1311 || !e.getClass().isAssignableFrom(expectedException)) { 1312 System.out.println("Unexpected exception: " + e); 1313 e.printStackTrace(System.out); 1314 result = false; 1315 } else { 1316 System.out.println("Expected exception: " + e); 1317 } 1318 } 1319 1320 if (result) System.out.println("Test case passed"); 1321 } 1322 1323 static boolean test_create_detached_signature(String canonicalizationMethod, 1324 String signatureMethod, String digestMethod, String transform, 1325 KeyInfoType keyInfo, Content contentType, int port) 1326 throws Exception { 1327 1328 System.out.print("Sign ..."); 1329 1330 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 1331 dbf.setNamespaceAware(true); 1332 dbf.setValidating(false); 1333 1334 // Create SignedInfo 1335 DigestMethod dm = fac.newDigestMethod(digestMethod, null); 1336 1337 List transformList = null; 1338 if (transform != null) { 1339 TransformParameterSpec params = null; 1340 switch (transform) { 1341 case Transform.XPATH: 1342 params = new XPathFilterParameterSpec("//."); 1343 break; 1344 case Transform.XPATH2: 1345 params = new XPathFilter2ParameterSpec( 1346 Collections.singletonList(new XPathType("//.", 1347 XPathType.Filter.INTERSECT))); 1348 break; 1349 case Transform.XSLT: 1350 Element element = dbf.newDocumentBuilder() 1351 .parse(new ByteArrayInputStream(xslt.getBytes())) 1352 .getDocumentElement(); 1353 DOMStructure stylesheet = new DOMStructure(element); 1354 params = new XSLTTransformParameterSpec(stylesheet); 1355 break; 1356 } 1357 transformList = Collections.singletonList(fac.newTransform( 1358 transform, params)); 1359 } 1360 1361 String url = String.format("http://localhost:%d/%s", port, contentType); 1362 List refs = Collections.singletonList(fac.newReference(url, dm, 1363 transformList, null, null)); 1364 1365 CanonicalizationMethod cm = fac.newCanonicalizationMethod( 1366 canonicalizationMethod, (C14NMethodParameterSpec) null); 1367 1368 SignatureMethod sm = fac.newSignatureMethod(signatureMethod, null); 1369 1370 Key signingKey; 1371 Key validationKey; 1372 switch (signatureMethod) { 1373 case SignatureMethod.DSA_SHA1: 1374 case SignatureMethod.RSA_SHA1: 1375 KeyPair kp = generateKeyPair(sm); 1376 validationKey = kp.getPublic(); 1377 signingKey = kp.getPrivate(); 1378 break; 1379 case SignatureMethod.HMAC_SHA1: 1380 KeyGenerator kg = KeyGenerator.getInstance("HmacSHA1"); 1381 signingKey = kg.generateKey(); 1382 validationKey = signingKey; 1383 break; 1384 default: 1385 throw new RuntimeException("Unsupported signature algorithm"); 1386 } 1387 1388 SignedInfo si = fac.newSignedInfo(cm, sm, refs, null); 1389 1390 // Create KeyInfo 1391 KeyInfoFactory kif = fac.getKeyInfoFactory(); 1392 List list = null; 1393 if (keyInfo == KeyInfoType.KeyValue) { 1394 if (validationKey instanceof PublicKey) { 1395 KeyValue kv = kif.newKeyValue((PublicKey) validationKey); 1396 list = Collections.singletonList(kv); 1397 } 1398 } else if (keyInfo == KeyInfoType.x509data) { 1399 list = Collections.singletonList( 1400 kif.newX509Data(Collections.singletonList("cn=Test"))); 1401 } else if (keyInfo == KeyInfoType.KeyName) { 1402 list = Collections.singletonList(kif.newKeyName("Test")); 1403 } else { 1404 throw new RuntimeException("Unexpected KeyInfo: " + keyInfo); 1405 } 1406 KeyInfo ki = list != null ? kif.newKeyInfo(list) : null; 1407 1408 // Create an empty doc for detached signature 1409 Document doc = dbf.newDocumentBuilder().newDocument(); 1410 DOMSignContext xsc = new DOMSignContext(signingKey, doc); 1411 1412 // Generate signature 1413 XMLSignature signature = fac.newXMLSignature(si, ki); 1414 signature.sign(xsc); 1415 1416 // Save signature 1417 String signatureString; 1418 try (StringWriter writer = new StringWriter()) { 1419 TransformerFactory tf = TransformerFactory.newInstance(); 1420 Transformer trans = tf.newTransformer(); 1421 Node parent = xsc.getParent(); 1422 trans.transform(new DOMSource(parent), new StreamResult(writer)); 1423 signatureString = writer.toString(); 1424 } 1425 1426 System.out.print("Validate ... "); 1427 try (ByteArrayInputStream bis = new ByteArrayInputStream( 1428 signatureString.getBytes())) { 1429 doc = dbf.newDocumentBuilder().parse(bis); 1430 } 1431 1432 NodeList nodeLst = doc.getElementsByTagName("Signature"); 1433 Node node = nodeLst.item(0); 1434 if (node == null) { 1435 throw new RuntimeException("Couldn't find Signature element"); 1436 } 1437 if (!(node instanceof Element)) { 1438 throw new RuntimeException("Unexpected node type"); 1439 } 1440 Element sig = (Element) node; 1441 1442 // Validate signature 1443 DOMValidateContext vc = new DOMValidateContext(validationKey, sig); 1444 vc.setProperty("org.jcp.xml.dsig.secureValidation", Boolean.FALSE); 1445 signature = fac.unmarshalXMLSignature(vc); 1446 1447 boolean success = signature.validate(vc); 1448 if (!success) { 1449 System.out.println("Core signature validation failed"); 1450 if (!secondChanceGranted && OS.contains("SunOS")) { 1451 removePKCS11Provider(); 1452 // set up the test again 1453 return test_create_detached_signature(canonicalizationMethod, 1454 signatureMethod, digestMethod, transform, 1455 keyInfo, contentType, port); 1456 } else { 1457 return false; 1458 } 1459 } 1460 1461 success = signature.getSignatureValue().validate(vc); 1462 if (!success) { 1463 System.out.println("Cryptographic validation of signature failed"); 1464 return false; 1465 } 1466 1467 return true; 1468 } 1469 1470 /* 1471 * Helper method for cases where we're running on unpatched 1472 * solaris systems where PKCS11 native libraries are unpatched 1473 */ 1474 private static void removePKCS11Provider() throws Exception { 1475 secondChanceGranted = true; 1476 Security.removeProvider("SunPKCS11-Solaris"); 1477 System.out.println("Second chance granted. Provider list: " 1478 + Arrays.toString(Security.getProviders())); 1479 setup(); 1480 } 1481 1482 private static final String DSA_Y = 1483 "070662842167565771936588335128634396171789331656318483584455493822" + 1484 "400811200853331373030669235424928346190274044631949560438023934623" + 1485 "71310375123430985057160"; 1486 private static final String DSA_P = 1487 "013232376895198612407547930718267435757728527029623408872245156039" + 1488 "757713029036368719146452186041204237350521785240337048752071462798" + 1489 "273003935646236777459223"; 1490 private static final String DSA_Q = 1491 "0857393771208094202104259627990318636601332086981"; 1492 private static final String DSA_G = 1493 "054216440574364751416096484883257051280474283943804743768346673007" + 1494 "661082626139005426812890807137245973106730741193551360857959820973" + 1495 "90670890367185141189796"; 1496 private static final String DSA_X = 1497 "0527140396812450214498055937934275626078768840117"; 1498 private static final String DSA_2048_Y = 1499 "15119007057343785981993995134621348945077524760182795513668325877793414638620983617627033248732235626178802906346261435991040697338468329634416089753032362617771631199351767336660070462291411472735835843440140283101463231807789628656218830720378705090795271104661936237385140354825159080766174663596286149653433914842868551355716015585570827642835307073681358328172009941968323702291677280809277843998510864653406122348712345584706761165794179850728091522094227603562280855104749858249588234915206290448353957550635709520273178475097150818955098638774564910092913714625772708285992586894795017709678223469405896699928"; 1500 private static final String DSA_2048_P = 1501 "18111848663142005571178770624881214696591339256823507023544605891411707081617152319519180201250440615163700426054396403795303435564101919053459832890139496933938670005799610981765220283775567361483662648340339405220348871308593627647076689407931875483406244310337925809427432681864623551598136302441690546585427193224254314088256212718983105131138772434658820375111735710449331518776858786793875865418124429269409118756812841019074631004956409706877081612616347900606555802111224022921017725537417047242635829949739109274666495826205002104010355456981211025738812433088757102520562459649777989718122219159982614304359"; 1502 private static final String DSA_2048_Q = 1503 "19689526866605154788513693571065914024068069442724893395618704484701"; 1504 private static final String DSA_2048_G = 1505 "2859278237642201956931085611015389087970918161297522023542900348087718063098423976428252369340967506010054236052095950169272612831491902295835660747775572934757474194739347115870723217560530672532404847508798651915566434553729839971841903983916294692452760249019857108409189016993380919900231322610083060784269299257074905043636029708121288037909739559605347853174853410208334242027740275688698461842637641566056165699733710043802697192696426360843173620679214131951400148855611740858610821913573088059404459364892373027492936037789337011875710759208498486908611261954026964574111219599568903257472567764789616958430"; 1506 private static final String DSA_2048_X = 1507 "14562787764977288900757387442281559936279834964901963465277698843172"; 1508 private static final String RSA_MOD = 1509 "010800185049102889923150759252557522305032794699952150943573164381" + 1510 "936603255999071981574575044810461362008102247767482738822150129277" + 1511 "490998033971789476107463"; 1512 private static final String RSA_PRIV = 1513 "016116973584421969795445996229612671947635798429212816611707210835" + 1514 "915586591340598683996088487065438751488342251960069575392056288063" + 1515 "6800379454345804879553"; 1516 private static final String RSA_PUB = "065537"; 1517 private static final String RSA_1024_MOD = "098871307553789439961130765" + 1518 "909423744508062468450669519128736624058048856940468016843888594585" + 1519 "322862378444314635412341974900625010364163960238734457710620107530" + 1520 "573945081856371709138380902553309075505688814637544923038853658690" + 1521 "857672483016239697038853418682988686871489963827000080098971762923" + 1522 "833614557257607521"; 1523 private static final String RSA_1024_PRIV = "03682574144968491431483287" + 1524 "297021581096848810374110568017963075809477047466189822987258068867" + 1525 "704855380407747867998863645890602646601140183818953428006646987710" + 1526 "237008997971129772408397621801631622129297063463868593083106979716" + 1527 "204903524890556839550490384015324575598723478554854070823335021842" + 1528 "210112348400928769"; 1529 1530 private static PublicKey getPublicKey(String algo, int keysize) 1531 throws Exception { 1532 KeyFactory kf = KeyFactory.getInstance(algo); 1533 KeySpec kspec; 1534 if (algo.equalsIgnoreCase("DSA")) { 1535 if (keysize == 1024) { 1536 kspec = new DSAPublicKeySpec(new BigInteger(DSA_Y), 1537 new BigInteger(DSA_P), 1538 new BigInteger(DSA_Q), 1539 new BigInteger(DSA_G)); 1540 } else if (keysize == 2048) { 1541 kspec = new DSAPublicKeySpec(new BigInteger(DSA_2048_Y), 1542 new BigInteger(DSA_2048_P), 1543 new BigInteger(DSA_2048_Q), 1544 new BigInteger(DSA_2048_G)); 1545 } else throw new RuntimeException("Unsupported keysize:" + keysize); 1546 } else if (algo.equalsIgnoreCase("RSA")) { 1547 if (keysize == 512) { 1548 kspec = new RSAPublicKeySpec(new BigInteger(RSA_MOD), 1549 new BigInteger(RSA_PUB)); 1550 } else if (keysize == 1024) { 1551 kspec = new RSAPublicKeySpec(new BigInteger(RSA_1024_MOD), 1552 new BigInteger(RSA_PUB)); 1553 } else throw new RuntimeException("Unsupported keysize:" + keysize); 1554 } else throw new RuntimeException("Unsupported key algorithm " + algo); 1555 return kf.generatePublic(kspec); 1556 } 1557 1558 private static PrivateKey getPrivateKey(String algo, int keysize) 1559 throws Exception { 1560 KeyFactory kf = KeyFactory.getInstance(algo); 1561 KeySpec kspec; 1562 if (algo.equalsIgnoreCase("DSA")) { 1563 if (keysize == 1024) { 1564 kspec = new DSAPrivateKeySpec 1565 (new BigInteger(DSA_X), new BigInteger(DSA_P), 1566 new BigInteger(DSA_Q), new BigInteger(DSA_G)); 1567 } else if (keysize == 2048) { 1568 kspec = new DSAPrivateKeySpec 1569 (new BigInteger(DSA_2048_X), new BigInteger(DSA_2048_P), 1570 new BigInteger(DSA_2048_Q), new BigInteger(DSA_2048_G)); 1571 } else throw new RuntimeException("Unsupported keysize:" + keysize); 1572 } else if (algo.equalsIgnoreCase("RSA")) { 1573 if (keysize == 512) { 1574 kspec = new RSAPrivateKeySpec 1575 (new BigInteger(RSA_MOD), new BigInteger(RSA_PRIV)); 1576 } else { 1577 kspec = new RSAPrivateKeySpec(new BigInteger(RSA_1024_MOD), 1578 new BigInteger(RSA_1024_PRIV)); 1579 } 1580 } else throw new RuntimeException("Unsupported key algorithm " + algo); 1581 return kf.generatePrivate(kspec); 1582 } 1583 1584 private static SecretKey getSecretKey(final byte[] secret) { 1585 return new SecretKey() { 1586 public String getFormat() { return "RAW"; } 1587 public byte[] getEncoded() { return secret; } 1588 public String getAlgorithm(){ return "SECRET"; } 1589 }; 1590 } 1591 1592 static KeyPair generateKeyPair(SignatureMethod sm) 1593 throws NoSuchAlgorithmException { 1594 KeyPairGenerator keygen; 1595 switch (sm.getAlgorithm()) { 1596 case SignatureMethod.DSA_SHA1: 1597 keygen = KeyPairGenerator.getInstance("DSA"); 1598 break; 1599 case SignatureMethod.RSA_SHA1: 1600 keygen = KeyPairGenerator.getInstance("RSA"); 1601 break; 1602 default: 1603 throw new RuntimeException("Unsupported signature algorithm"); 1604 } 1605 1606 SecureRandom random = new SecureRandom(); 1607 keygen.initialize(1024, random); 1608 return keygen.generateKeyPair(); 1609 } 1610 1611 /** 1612 * This URIDereferencer returns locally cached copies of http content to 1613 * avoid test failures due to network glitches, etc. 1614 */ 1615 private static class HttpURIDereferencer implements URIDereferencer { 1616 private URIDereferencer defaultUd; 1617 1618 HttpURIDereferencer() { 1619 defaultUd = XMLSignatureFactory.getInstance().getURIDereferencer(); 1620 } 1621 1622 public Data dereference(final URIReference ref, XMLCryptoContext ctx) 1623 throws URIReferenceException { 1624 String uri = ref.getURI(); 1625 if (uri.equals(STYLESHEET) || uri.equals(STYLESHEET_B64)) { 1626 try { 1627 FileInputStream fis = new FileInputStream(new File 1628 (DATA_DIR, uri.substring(uri.lastIndexOf('/')))); 1629 return new OctetStreamData(fis,ref.getURI(),ref.getType()); 1630 } catch (Exception e) { throw new URIReferenceException(e); } 1631 } 1632 1633 // fallback on builtin deref 1634 return defaultUd.dereference(ref, ctx); 1635 } 1636 } 1637 1638 // local http server 1639 static class Http implements HttpHandler, AutoCloseable { 1640 1641 private final HttpServer server; 1642 1643 private Http(HttpServer server) { 1644 this.server = server; 1645 } 1646 1647 static Http startServer() throws IOException { 1648 HttpServer server = HttpServer.create(new InetSocketAddress(0), 0); 1649 return new Http(server); 1650 } 1651 1652 void start() { 1653 server.createContext("/", this); 1654 server.start(); 1655 } 1656 1657 void stop() { 1658 server.stop(0); 1659 } 1660 1661 int getPort() { 1662 return server.getAddress().getPort(); 1663 } 1664 1665 @Override 1666 public void handle(HttpExchange t) throws IOException { 1667 try { 1668 String type; 1669 String path = t.getRequestURI().getPath(); 1670 if (path.startsWith("/")) { 1671 type = path.substring(1); 1672 } else { 1673 type = path; 1674 } 1675 1676 String contentTypeHeader = ""; 1677 byte[] output = new byte[] {}; 1678 int code = 200; 1679 Content testContentType = Content.valueOf(type); 1680 switch (testContentType) { 1681 case Base64: 1682 contentTypeHeader = "application/octet-stream"; 1683 output = "VGVzdA==".getBytes(); 1684 break; 1685 case Text: 1686 contentTypeHeader = "text/plain"; 1687 output = "Text".getBytes(); 1688 break; 1689 case Xml: 1690 contentTypeHeader = "application/xml"; 1691 output = "<tag>test</tag>".getBytes(); 1692 break; 1693 case NotExisitng: 1694 code = 404; 1695 break; 1696 default: 1697 throw new IOException("Unknown test content type"); 1698 } 1699 1700 t.getResponseHeaders().set("Content-Type", contentTypeHeader); 1701 t.sendResponseHeaders(code, output.length); 1702 t.getResponseBody().write(output); 1703 } catch (IOException e) { 1704 System.out.println("Exception: " + e); 1705 t.sendResponseHeaders(500, 0); 1706 } 1707 t.close(); 1708 } 1709 1710 @Override 1711 public void close() { 1712 stop(); 1713 } 1714 } 1715 }