This project has retired. For details please refer to its
Attic page.
DigSigUtil xref
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.juddi.v3.client.cryptor;
17
18 import java.io.ByteArrayInputStream;
19 import java.io.File;
20 import java.io.FileInputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.StringWriter;
24 import java.net.MalformedURLException;
25 import java.net.URI;
26 import java.net.URL;
27 import java.security.InvalidAlgorithmParameterException;
28 import java.security.KeyStore;
29 import java.security.NoSuchAlgorithmException;
30 import java.security.PrivateKey;
31 import java.security.PublicKey;
32 import java.security.Security;
33 import java.security.cert.CRLException;
34 import java.security.cert.CertPath;
35 import java.security.cert.CertPathValidator;
36 import java.security.cert.CertPathValidatorException;
37 import java.security.cert.CertPathValidatorResult;
38 import java.security.cert.Certificate;
39 import java.security.cert.CertificateException;
40 import java.security.cert.CertificateFactory;
41 import java.security.cert.PKIXCertPathValidatorResult;
42 import java.security.cert.PKIXParameters;
43 import java.security.cert.TrustAnchor;
44 import java.security.cert.X509CRL;
45 import java.security.cert.X509CertSelector;
46 import java.security.cert.X509Certificate;
47 import java.util.ArrayList;
48 import java.util.Arrays;
49 import java.util.Collections;
50 import java.util.Enumeration;
51 import java.util.Iterator;
52 import java.util.List;
53 import java.util.Properties;
54 import java.util.concurrent.atomic.AtomicReference;
55 import javax.security.auth.x500.X500Principal;
56 import javax.xml.bind.JAXB;
57 import javax.xml.crypto.dsig.CanonicalizationMethod;
58 import javax.xml.crypto.dsig.DigestMethod;
59 import javax.xml.crypto.dsig.Reference;
60 import javax.xml.crypto.dsig.SignatureMethod;
61 import javax.xml.crypto.dsig.SignedInfo;
62 import javax.xml.crypto.dsig.Transform;
63 import javax.xml.crypto.dsig.XMLSignature;
64 import javax.xml.crypto.dsig.XMLSignatureFactory;
65 import javax.xml.crypto.dsig.dom.DOMSignContext;
66 import javax.xml.crypto.dsig.dom.DOMValidateContext;
67 import javax.xml.crypto.dsig.keyinfo.KeyInfo;
68 import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
69 import javax.xml.crypto.dsig.keyinfo.X509Data;
70 import javax.xml.crypto.dsig.keyinfo.X509IssuerSerial;
71 import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
72 import javax.xml.crypto.dsig.spec.TransformParameterSpec;
73 import javax.xml.transform.dom.DOMResult;
74 import javax.xml.transform.dom.DOMSource;
75 import org.apache.commons.logging.Log;
76 import org.apache.commons.logging.LogFactory;
77 import org.w3c.dom.Document;
78 import org.w3c.dom.Element;
79 import org.w3c.dom.Node;
80 import org.w3c.dom.NodeList;
81 import sun.security.provider.certpath.CertId;
82 import sun.security.provider.certpath.OCSP;
83 import sun.security.provider.certpath.OCSP.RevocationStatus;
84 import static sun.security.provider.certpath.OCSP.getResponderURI;
85 import sun.security.x509.X509CertImpl;
86
87
88
89
90
91
92
93
94
95
96
97 public class DigSigUtil {
98 public final static String SIGNATURE_KEYSTORE_KEY_PASSWORD_PROVIDER="signatureKeystoreKeyPassENCProvider";
99 public final static String SIGNATURE_KEYSTORE_KEY_PASSWORD_WAS_ENC="signatureKeystoreKeyPassENC";
100 public final static String SIGNATURE_KEYSTORE_KEY_PASSWORD_CIPHER="signatureKeyStoreCipherPass";
101
102 public final static String SIGNATURE_KEYSTORE_FILE_PASSWORD_WASENC="signatureKeystoreFilePassENC";
103 public final static String SIGNATURE_KEYSTORE_FILE_PASSWORD_PROVIDER="signatureKeystoreFileENCProvider";
104 public final static String TRUSTSTORE_FILE_PASSWORD_WASENC="truststoreFilePassENC";
105 public final static String TRUSTSTORE_FILE_PASSWORD_PROVIDER="truststoreFilePassENCProvider";
106 public final static String SIGNATURE_KEYSTORE_FILE_PASSWORD_CIPHER="signatureKeystoreFileKeyPass";
107 public final static String TRUSTSTORE_FILE_PASSWORD_CIPHER="truststoreFilePass";
108
109
110
111
112
113
114
115 public DigSigUtil(Properties config) throws CertificateException {
116 cf = CertificateFactory.getInstance("X.509");
117 this.map = config;
118 }
119
120
121
122
123
124 public DigSigUtil() throws CertificateException {
125 cf = CertificateFactory.getInstance("X.509");
126 }
127 private Log logger = LogFactory.getLog(this.getClass());
128
129 public void put(String key, String value) {
130 map.put(key, value);
131 }
132
133
134
135
136 public void clear() {
137 map.clear();
138 }
139 private Properties map = new Properties();
140
141
142
143
144
145
146
147
148
149 public final static String SIGNATURE_KEYSTORE_FILE = "keyStorePath";
150
151
152
153
154
155 public final static String SIGNATURE_KEYSTORE_FILETYPE = "keyStoreType";
156 public final static String SIGNATURE_KEYSTORE_FILE_PASSWORD = "filePassword";
157 public final static String SIGNATURE_KEYSTORE_KEY_PASSWORD = "keyPassword";
158 public final static String SIGNATURE_KEYSTORE_KEY_ALIAS = "keyAlias";
159
160
161
162
163
164
165
166
167
168
169 public final static String TRUSTSTORE_FILE = "trustStorePath";
170
171
172
173
174
175
176
177
178
179
180 public final static String TRUSTSTORE_FILETYPE = "trustStoreType";
181
182
183
184
185
186
187
188
189
190
191 public final static String TRUSTSTORE_FILE_PASSWORD = "trustStorePassword";
192
193
194
195
196
197
198 public final static String CANONICALIZATIONMETHOD = "CanonicalizationMethod";
199
200
201
202
203
204 public final static String SIGNATURE_METHOD = "SignatureMethod";
205
206
207
208
209
210
211
212
213
214
215 public final static String SIGNATURE_OPTION_CERT_INCLUSION_BASE64 = "BASE64";
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232 public final static String SIGNATURE_OPTION_CERT_INCLUSION_SERIAL = "SERIAL";
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248 public final static String SIGNATURE_OPTION_CERT_INCLUSION_SUBJECTDN = "SUBJECTDN";
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 public final static String XML_DIGSIG_NS = "http://www.w3.org/2000/09/xmldsig#";
270
271
272
273
274
275
276 public final static String SIGNATURE_OPTION_DIGEST_METHOD = "digestMethod";
277
278
279
280
281
282
283
284
285
286
287
288 public final static String CHECK_TIMESTAMPS = "checkTimestamps";
289 private CertificateFactory cf = null;
290 public final static String CHECK_REVOCATION_STATUS_OCSP = "checkRevocationOCSP";
291 public final static String CHECK_REVOCATION_STATUS_CRL = "checkRevocationCRL";
292 public final static String CHECK_TRUST_CHAIN = "checkTrust";
293
294
295
296
297
298
299
300
301
302
303
304
305 public <T> T signUddiEntity(T jaxbObj) {
306 DOMResult domResult = new DOMResult();
307 JAXB.marshal(jaxbObj, domResult);
308 Document doc = ((Document) domResult.getNode());
309 Element docElement = doc.getDocumentElement();
310
311 try {
312 KeyStore ks = KeyStore.getInstance(map.getProperty(SIGNATURE_KEYSTORE_FILETYPE));
313 URL url = Thread.currentThread().getContextClassLoader().getResource(map.getProperty(SIGNATURE_KEYSTORE_FILE));
314 if (url == null) {
315 try {
316 url = new File(map.getProperty(SIGNATURE_KEYSTORE_FILE)).toURI().toURL();
317 } catch (Exception x) {
318 }
319 }
320 if (url == null) {
321 try {
322 url = this.getClass().getClassLoader().getResource(map.getProperty(SIGNATURE_KEYSTORE_FILE));
323 } catch (Exception x) {
324 }
325 }
326 KeyStore.PrivateKeyEntry keyEntry = null;
327 if (!map.getProperty(SIGNATURE_KEYSTORE_FILETYPE).equalsIgnoreCase("WINDOWS-MY")) {
328 ks.load(url.openStream(), (map.getProperty(SIGNATURE_KEYSTORE_FILE_PASSWORD)).toCharArray());
329 if (map.getProperty(SIGNATURE_KEYSTORE_KEY_PASSWORD) == null) {
330 keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(map.getProperty(SIGNATURE_KEYSTORE_KEY_ALIAS),
331 new KeyStore.PasswordProtection(map.getProperty(SIGNATURE_KEYSTORE_FILE_PASSWORD).toCharArray()));
332 } else {
333 keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(map.getProperty(SIGNATURE_KEYSTORE_KEY_ALIAS),
334 new KeyStore.PasswordProtection(map.getProperty(SIGNATURE_KEYSTORE_KEY_PASSWORD).toCharArray()));
335 }
336 } else {
337
338 ks.load(null, null);
339 keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(map.getProperty(SIGNATURE_KEYSTORE_KEY_ALIAS),
340 null);
341 }
342
343 PrivateKey privateKey = keyEntry.getPrivateKey();
344 Certificate origCert = keyEntry.getCertificate();
345
346 this.signDOM(docElement, privateKey, origCert);
347
348 DOMSource domSource = new DOMSource(doc);
349 T result = (T) JAXB.unmarshal(domSource, jaxbObj.getClass());
350 return result;
351 } catch (Exception e) {
352 throw new RuntimeException("Signature failure due to: " + e.getMessage(), e);
353 }
354 }
355
356
357
358
359
360
361
362
363
364
365
366
367
368 public <T> T signUddiEntity(T jaxbObj, Certificate publicKey, PrivateKey privateKey) {
369 DOMResult domResult = new DOMResult();
370 JAXB.marshal(jaxbObj, domResult);
371 Document doc = ((Document) domResult.getNode());
372 Element docElement = doc.getDocumentElement();
373 try {
374
375
376 this.signDOM(docElement, privateKey, publicKey);
377 DOMSource domSource = new DOMSource(doc);
378 T result = (T) JAXB.unmarshal(domSource, jaxbObj.getClass());
379 return result;
380 } catch (Exception e) {
381 throw new RuntimeException("Signature failure due to: " + e.getMessage(), e);
382 }
383 }
384
385
386
387
388
389
390 public static void JAXB_ToStdOut(Object obj) {
391 StringWriter sw = new StringWriter();
392 JAXB.marshal(obj, sw);
393 System.out.println(sw.toString());
394 }
395
396
397
398
399
400
401
402 public static String JAXB_ToString(Object obj) {
403 StringWriter sw = new StringWriter();
404 JAXB.marshal(obj, sw);
405 return (sw.toString());
406 }
407
408
409
410
411
412
413
414
415
416
417
418
419 public X509Certificate getSigningCertificatePublicKey(Object obj) throws IllegalArgumentException, CertificateException {
420 DOMResult domResult = new DOMResult();
421 JAXB.marshal(obj, domResult);
422
423 Document doc = ((Document) domResult.getNode());
424 Element docElement = doc.getDocumentElement();
425 return getSigningCertificatePublicKey(docElement);
426 }
427
428
429
430
431
432
433
434
435
436
437
438 private X509Certificate getSigningCertificatePublicKey(Element docElement) throws IllegalArgumentException, CertificateException {
439 if (docElement == null) {
440 throw new IllegalArgumentException();
441 }
442
443 NodeList childNodes = docElement.getChildNodes();
444
445 for (int i = 0; i < childNodes.getLength(); i++) {
446
447 if (childNodes.item(i).getNamespaceURI().equalsIgnoreCase(XML_DIGSIG_NS) && childNodes.item(i).getLocalName().equalsIgnoreCase("Signature")) {
448 Node sig = childNodes.item(i);
449 for (int k = 0; k < sig.getChildNodes().getLength(); k++) {
450
451 if ("KeyInfo".equalsIgnoreCase(sig.getChildNodes().item(k).getLocalName())) {
452
453 for (int j = 0; j < sig.getChildNodes().item(k).getChildNodes().getLength(); j++) {
454 if ("X509Data".equalsIgnoreCase(sig.getChildNodes().item(k).getChildNodes().item(j).getLocalName())) {
455 Node X509Data = sig.getChildNodes().item(k).getChildNodes().item(j);
456 for (int x = 0; x < X509Data.getChildNodes().getLength(); x++) {
457 if ("X509Certificate".equalsIgnoreCase(X509Data.getChildNodes().item(x).getLocalName())) {
458
459
460 String c
461 = "-----BEGIN CERTIFICATE-----\n"
462 + X509Data.getChildNodes().item(x).getTextContent()
463 + "\n-----END CERTIFICATE-----";
464
465 InputStream is = new ByteArrayInputStream(c.getBytes());
466 X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
467
468 logger.info("embedded certificate found, X509 public key " + cert.getSubjectDN().toString());
469 return cert;
470
471 }
472
473
474
475 }
476 X509Certificate cert = FindCert(X509Data.getChildNodes());
477 if (cert != null) {
478 logger.info("certificate loaded from local trust store, X509 public key " + cert.getSubjectDN().toString());
479 return cert;
480 }
481 }
482
483 }
484 break;
485 }
486
487 }
488
489 break;
490 }
491 }
492 return null;
493 }
494
495
496
497
498 public static RevocationStatus check(X509Certificate cert,
499 X509Certificate issuerCert)
500 throws IOException, CertPathValidatorException, CertificateException {
501 CertId certId = null;
502 URI responderURI = null;
503
504 X509CertImpl certImpl = X509CertImpl.toImpl(cert);
505 responderURI = getResponderURI(certImpl);
506 if (responderURI == null) {
507 throw new CertPathValidatorException
508 ("No OCSP Responder URI in certificate");
509 }
510 return OCSP.check(cert, issuerCert, responderURI, cert, null);
511 }
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531 public boolean verifySignedUddiEntity(Object obj, AtomicReference<String> OutErrorMessage) throws IllegalArgumentException {
532 if (OutErrorMessage == null) {
533 OutErrorMessage = new AtomicReference<String>();
534 OutErrorMessage.set("");
535 }
536 if (obj == null) {
537 throw new IllegalArgumentException("obj");
538 }
539 try {
540 DOMResult domResult = new DOMResult();
541 JAXB.marshal(obj, domResult);
542
543 Document doc = ((Document) domResult.getNode());
544 Element docElement = doc.getDocumentElement();
545
546 X509Certificate signingcert = getSigningCertificatePublicKey(docElement);
547
548 if (signingcert != null) {
549 logger.info("verifying signature based on X509 public key " + signingcert.getSubjectDN().toString());
550 if (map.containsKey(CHECK_TIMESTAMPS) && Boolean.parseBoolean(map.getProperty(CHECK_TIMESTAMPS))) {
551 signingcert.checkValidity();
552 }
553 if (map.containsKey(CHECK_REVOCATION_STATUS_OCSP)
554 && Boolean.parseBoolean(map.getProperty(CHECK_REVOCATION_STATUS_OCSP))) {
555 logger.info("verifying revocation status via OSCP for X509 public key " + signingcert.getSubjectDN().toString());
556 X500Principal issuerX500Principal = signingcert.getIssuerX500Principal();
557 logger.info("certificate " + signingcert.getSubjectDN().toString() + " was issued by " + issuerX500Principal.getName() + ", attempting to retrieve certificate");
558 Security.setProperty("ocsp.enable", "false");
559 X509Certificate issuer = FindCertByDN(issuerX500Principal);
560 if (issuer == null) {
561 OutErrorMessage.set("Unable to verify certificate status from OCSP because the issuer of the certificate is not in the trust store. " + OutErrorMessage.get());
562 } else {
563 RevocationStatus check = check(signingcert, issuer);
564 logger.info("certificate " + signingcert.getSubjectDN().toString() + " revocation status is " + check.getCertStatus().toString() + " reason " + check.getRevocationReason().toString());
565 if (check.getCertStatus() != RevocationStatus.CertStatus.GOOD) {
566 OutErrorMessage.set("Certificate status is " + check.getCertStatus().toString() + " reason " + check.getRevocationReason().toString() + "." + OutErrorMessage.get());
567 }
568
569 }
570 }
571 if (map.containsKey(CHECK_REVOCATION_STATUS_CRL) && Boolean.parseBoolean(map.getProperty(CHECK_REVOCATION_STATUS_CRL))) {
572 logger.info("verifying revokation status via CRL for X509 public key " + signingcert.getSubjectDN().toString());
573
574 Security.setProperty("ocsp.enable", "false");
575 System.setProperty("com.sun.security.enableCRLDP", "true");
576
577 X509CertSelector targetConstraints = new X509CertSelector();
578 targetConstraints.setCertificate(signingcert);
579 PKIXParameters params = new PKIXParameters(GetTrustStore());
580 params.setRevocationEnabled(true);
581 CertPath certPath = cf.generateCertPath(Arrays.asList(signingcert));
582
583 CertPathValidator certPathValidator = CertPathValidator.getInstance(CertPathValidator.getDefaultType());
584 CertPathValidatorResult result = certPathValidator.validate(certPath, params);
585 try {
586 PKIXCertPathValidatorResult pkixResult = (PKIXCertPathValidatorResult) result;
587 logger.info("revokation status via CRL PASSED for X509 public key " + signingcert.getSubjectDN().toString() + " " + pkixResult.toString());
588 } catch (Exception ex) {
589 OutErrorMessage.set("Certificate status is via CRL Failed: " + ex.getMessage() + "." + OutErrorMessage.get());
590 }
591 }
592 if (map.containsKey(CHECK_TRUST_CHAIN) && Boolean.parseBoolean(map.getProperty(CHECK_TRUST_CHAIN))) {
593 logger.info("verifying trust chain X509 public key " + signingcert.getSubjectDN().toString());
594 try {
595 PKIXParameters params = new PKIXParameters(GetTrustStore());
596 params.setRevocationEnabled(false);
597 CertPath certPath = cf.generateCertPath(Arrays.asList(signingcert));
598
599 CertPathValidator certPathValidator = CertPathValidator.getInstance(CertPathValidator.getDefaultType());
600 CertPathValidatorResult result = certPathValidator.validate(certPath, params);
601
602 PKIXCertPathValidatorResult pkixResult = (PKIXCertPathValidatorResult) result;
603
604 TrustAnchor ta = pkixResult.getTrustAnchor();
605 X509Certificate cert = ta.getTrustedCert();
606
607 logger.info("trust chain validated X509 public key " + signingcert.getSubjectDN().toString() + " issued by " + cert.getPublicKey().toString());
608 } catch (Exception ex) {
609 OutErrorMessage.set("Certificate status Trust validation failed: " + ex.getMessage() + "." + OutErrorMessage.get());
610 }
611 }
612 boolean b = verifySignature(docElement, signingcert.getPublicKey(), OutErrorMessage);
613 if ((OutErrorMessage.get() == null || OutErrorMessage.get().length() == 0) && b) {
614
615 return true;
616 }
617 return false;
618 }
619
620
621 logger.info("signature did not have an embedded X509 public key. reverting to user specified certificate");
622
623 KeyStore ks = KeyStore.getInstance(map.getProperty(SIGNATURE_KEYSTORE_FILETYPE));
624 URL url = Thread.currentThread().getContextClassLoader().getResource(map.getProperty(SIGNATURE_KEYSTORE_FILE));
625 if (url == null) {
626 try {
627 url = new File(map.getProperty(SIGNATURE_KEYSTORE_FILE)).toURI().toURL();
628 } catch (Exception x) {
629 }
630 }
631 if (url == null) {
632 try {
633 url = this.getClass().getClassLoader().getResource(map.getProperty(SIGNATURE_KEYSTORE_FILE));
634 } catch (Exception x) {
635 }
636 }
637 if (url == null) {
638 logger.error("");
639 OutErrorMessage.set("The signed entity is signed but does not have a certificate attached and"
640 + "you didn't specify a keystore for me to look it up in. " + OutErrorMessage.get());
641 return false;
642 }
643 KeyStore.PrivateKeyEntry keyEntry = null;
644
645 ks.load(url.openStream(), map.getProperty(SIGNATURE_KEYSTORE_FILE_PASSWORD).toCharArray());
646
647 if (map.getProperty(SIGNATURE_KEYSTORE_KEY_PASSWORD) == null) {
648 keyEntry
649 = (KeyStore.PrivateKeyEntry) ks.getEntry(map.getProperty(SIGNATURE_KEYSTORE_KEY_ALIAS),
650 new KeyStore.PasswordProtection(map.getProperty(SIGNATURE_KEYSTORE_FILE_PASSWORD).toCharArray()));
651 } else {
652 keyEntry
653 = (KeyStore.PrivateKeyEntry) ks.getEntry(map.getProperty(SIGNATURE_KEYSTORE_KEY_ALIAS),
654 new KeyStore.PasswordProtection(map.getProperty(SIGNATURE_KEYSTORE_KEY_PASSWORD).toCharArray()));
655 }
656
657 Certificate origCert = keyEntry.getCertificate();
658 if (map.containsKey(CHECK_TIMESTAMPS)) {
659 if (origCert.getPublicKey() instanceof X509Certificate) {
660 X509Certificate x = (X509Certificate) origCert.getPublicKey();
661 x.checkValidity();
662 }
663 }
664 PublicKey validatingKey = origCert.getPublicKey();
665 return verifySignature(docElement, validatingKey, OutErrorMessage);
666 } catch (Exception e) {
667
668 logger.error("Error caught validating signature", e);
669 OutErrorMessage.set(e.getMessage());
670 return false;
671 }
672 }
673
674
675
676
677
678
679
680
681
682
683
684
685 private KeyStore GetTrustStore() throws Exception {
686 String type = map.getProperty(TRUSTSTORE_FILETYPE);
687 if (type == null) {
688 type = "JKS";
689 }
690 KeyStore ks = KeyStore.getInstance(type);
691 boolean ksLoaded = false;
692
693 if (!ksLoaded) {
694 String truststore = System.getProperty("javax.net.ssl.keyStore");
695 try {
696
697 String pwd = System.getProperty("javax.net.ssl.keyStorePassword");
698 if (truststore != null && pwd != null) {
699 ks.load(new File(truststore).toURI().toURL().openStream(), pwd.toCharArray());
700 ksLoaded = true;
701 logger.info("trust store loaded from sysprop " + truststore);
702 }
703 } catch (Exception ex) {
704 logger.warn("unable to load truststore from sysprop " + truststore + " " + ex.getMessage());
705 logger.debug("unable to load truststore from sysprop " + ex.getMessage(),ex);
706 }
707 }
708
709 File f=new File(map.getProperty(TRUSTSTORE_FILE));
710
711 if (!ksLoaded) {
712 try {
713 if (f.exists()){
714 URL url = f.toURI().toURL();
715 ks.load(url.openStream(), (map.getProperty(TRUSTSTORE_FILE_PASSWORD)).toCharArray());
716 ksLoaded = true;
717 logger.info("trust store loaded from file " + map.getProperty(TRUSTSTORE_FILE));
718 }
719 } catch (Exception x) {
720 logger.warn("unable to load truststore from file "+map.getProperty(TRUSTSTORE_FILE)+" "+ x.getMessage());
721 logger.debug("unable to load truststore from file "+ x.getMessage(), x);
722
723 }
724 }
725
726 if (!ksLoaded) {
727 FileInputStream fis=null;
728 try {
729
730 if (f.exists())
731 {
732 fis = new FileInputStream(f);
733 ks.load(fis, (map.getProperty(TRUSTSTORE_FILE_PASSWORD)).toCharArray());
734 fis.close();
735 ksLoaded = true;
736 logger.info("trust store loaded from file " + map.getProperty(TRUSTSTORE_FILE));
737 }
738 } catch (Exception x) {
739 logger.warn("unable to load truststore from file "+map.getProperty(TRUSTSTORE_FILE)+" "+ x.getMessage());
740 logger.debug("unable to load truststore from file "+ x.getMessage(), x);
741 }
742 finally {
743 if (fis!=null)
744 fis.close();
745 }
746 }
747
748
749
750
751
752
753 if (!ksLoaded) {
754 try {
755 URL url = Thread.currentThread().getContextClassLoader().getResource(map.getProperty(TRUSTSTORE_FILE));
756 ks.load(url.openStream(), (map.getProperty(TRUSTSTORE_FILE_PASSWORD)).toCharArray());
757 ksLoaded = true;
758 logger.info("trust store loaded from classpath(1) " + map.getProperty(TRUSTSTORE_FILE));
759 } catch (Exception x) {
760 logger.warn("unable to load truststore from classpath" + map.getProperty(TRUSTSTORE_FILE) + " " +x.getMessage());
761 logger.debug("unable to load truststore from classpath", x);
762 }
763 }
764
765
766 if (!ksLoaded) {
767 try {
768 URL url = this.getClass().getClassLoader().getResource(map.getProperty(TRUSTSTORE_FILE));
769 ks.load(url.openStream(), (map.getProperty(TRUSTSTORE_FILE_PASSWORD)).toCharArray());
770 ksLoaded = true;
771 logger.info("trust store loaded from classpath(2) " + map.getProperty(TRUSTSTORE_FILE));
772 } catch (Exception x) {
773 logger.warn("unable to load truststore from classpath "+ map.getProperty(TRUSTSTORE_FILE) + " " +x.getMessage());
774 logger.debug("unable to load truststore from classpath", x);
775 }
776 }
777
778
779 if (!ksLoaded) {
780 try {
781 URL cacerts = new File(System.getenv("JAVA_HOME") + File.separator + "lib" + File.separator + "security" + File.separator + "cacerts").toURI().toURL();
782 ks.load(cacerts.openStream(), "changeit".toCharArray());
783 logger.info("trust store loaded from JRE " + cacerts.toExternalForm());
784 ksLoaded = true;
785 } catch (Exception c) {
786 logger.warn("unable to load default JDK truststore "+ c.getMessage());
787 logger.debug("unable to load default JDK truststore",c);
788 }
789 }
790
791
792 try {
793 if (map.getProperty(TRUSTSTORE_FILETYPE).equalsIgnoreCase("WINDOWS-ROOT")) {
794 ks.load(null, null);
795 ksLoaded = true;
796 logger.info("trust store loaded from windows");
797 }
798 } catch (Exception ex) {
799 logger.warn("unable to load truststore from windows " +ex.getMessage());
800 logger.debug("unable to load truststore from windows", ex);
801 }
802
803 if (!ksLoaded) {
804 try {
805 URL cacerts = new File(System.getenv("JAVA_HOME") + File.separator + "jre" + File.separator + "lib" + File.separator + "security" + File.separator + "cacerts").toURI().toURL();
806 ks.load(cacerts.openStream(), "changeit".toCharArray());
807 logger.info("trust store loaded from JRE " + cacerts.toExternalForm());
808 ksLoaded = true;
809 } catch (Exception c) {
810 logger.warn("unable to load default jdk/jre truststore " +c.getMessage());
811 logger.debug("unable to load default jdk/jre truststore", c);
812 }
813 }
814 if (!ksLoaded) {
815 logger.warn("unable to load trust store!");
816 }
817
818 return ks;
819 }
820
821 private XMLSignatureFactory initXMLSigFactory() {
822 XMLSignatureFactory fac = XMLSignatureFactory.getInstance();
823 return fac;
824 }
825
826 private Reference initReference(XMLSignatureFactory fac) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
827 List transformers = new ArrayList();
828 transformers.add(fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null));
829
830 String dm = map.getProperty(SIGNATURE_OPTION_DIGEST_METHOD);
831 if (dm == null) {
832 dm = DigestMethod.SHA1;
833 }
834 Reference ref = fac.newReference("", fac.newDigestMethod(dm, null), transformers, null, null);
835 return ref;
836 }
837
838 private SignedInfo initSignedInfo(XMLSignatureFactory fac) throws Exception {
839 Reference ref = initReference(fac);
840 String cm = null;
841 cm = map.getProperty(CANONICALIZATIONMETHOD);
842 String sigmethod = null;
843 sigmethod = map.getProperty(SIGNATURE_METHOD);
844 if (sigmethod == null) {
845 sigmethod = SignatureMethod.RSA_SHA1;
846 }
847 if (cm == null) {
848 cm = CanonicalizationMethod.EXCLUSIVE;
849 }
850 SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(
851 cm,
852 (C14NMethodParameterSpec) null),
853 fac.newSignatureMethod(sigmethod,
854 null), Collections.singletonList(ref));
855 return si;
856 }
857
858 private boolean verifySignature(Element element, PublicKey validatingKey, AtomicReference<String> OutReadableErrorMessage) {
859 if (OutReadableErrorMessage == null) {
860 OutReadableErrorMessage = new AtomicReference<String>();
861 }
862 XMLSignatureFactory fac = initXMLSigFactory();
863 NodeList nl = element.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
864 if (nl.getLength() == 0) {
865 throw new RuntimeException("Cannot find Signature element");
866 }
867 DOMValidateContext valContext = new DOMValidateContext(validatingKey, nl.item(0));
868 try {
869 valContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE);
870 XMLSignature signature = fac.unmarshalXMLSignature(valContext);
871 boolean coreValidity = signature.validate(valContext);
872
873 if (coreValidity == false) {
874 logger.warn("Signature failed core validation");
875 boolean sv = signature.getSignatureValue().validate(valContext);
876 logger.debug("signature validation status: " + sv);
877 OutReadableErrorMessage.set("signature validation failed: " + sv + "." + OutReadableErrorMessage.get());
878
879 @SuppressWarnings("unchecked")
880 Iterator<Reference> i = signature.getSignedInfo().getReferences().iterator();
881
882 for (int j = 0; i.hasNext(); j++) {
883 Reference ref = (Reference) i.next();
884 boolean refValid = ref.validate(valContext);
885 logger.debug(j);
886 logger.debug("ref[" + j + "] validity status: " + refValid);
887 if (!refValid) {
888 OutReadableErrorMessage.set("signature reference " + j + " invalid. " + OutReadableErrorMessage.get());
889 }
890 logger.debug("Ref type: " + ref.getType() + ", URI: " + ref.getURI());
891 for (Object xform : ref.getTransforms()) {
892 logger.debug("Transform: " + xform);
893 }
894 String calcDigValStr = digestToString(ref.getCalculatedDigestValue());
895 String expectedDigValStr = digestToString(ref.getDigestValue());
896 logger.warn(" Calc Digest: " + calcDigValStr);
897 logger.warn("Expected Digest: " + expectedDigValStr);
898 if (!calcDigValStr.equalsIgnoreCase(expectedDigValStr)) {
899 OutReadableErrorMessage.set("digest mismatch for signature ref " + j + "." + OutReadableErrorMessage.get());
900 }
901 }
902 } else {
903 logger.info("Signature passed core validation");
904 }
905 return coreValidity;
906 } catch (Exception e) {
907 OutReadableErrorMessage.set("signature validation failed: " + e.getMessage() + OutReadableErrorMessage.get());
908 logger.fatal(e);
909 return false;
910 }
911 }
912
913 private String digestToString(byte[] digest) {
914 StringBuilder sb = new StringBuilder();
915 for (byte b : digest) {
916 String hex = Integer.toHexString(0xFF & b);
917 if (hex.length() == 1) {
918 sb.append('0');
919 }
920 sb.append(hex);
921 }
922 return sb.toString();
923 }
924
925 private void signDOM(Node node, PrivateKey privateKey, Certificate origCert) {
926 XMLSignatureFactory fac = initXMLSigFactory();
927 X509Certificate cert = (X509Certificate) origCert;
928
929
930 KeyInfoFactory kif = fac.getKeyInfoFactory();
931
932 List<Object> x509Content = null;
933 List<X509Data> data = new ArrayList<X509Data>();
934 if (map.containsKey(SIGNATURE_OPTION_CERT_INCLUSION_SUBJECTDN)) {
935 x509Content = new ArrayList<Object>();
936
937 x509Content.add(cert.getSubjectDN().getName());
938
939
940 X509Data xd = kif.newX509Data(x509Content);
941 data.add(xd);
942 }
943
944
945
946 if (map.containsKey(SIGNATURE_OPTION_CERT_INCLUSION_BASE64)) {
947 x509Content = new ArrayList<Object>();
948 x509Content.add(cert);
949
950 X509Data xd = kif.newX509Data(x509Content);
951 data.add(xd);
952 }
953 if (map.containsKey(SIGNATURE_OPTION_CERT_INCLUSION_SERIAL)) {
954 x509Content = new ArrayList<Object>();
955
956 X509IssuerSerial issuer = kif.newX509IssuerSerial(cert.getIssuerX500Principal().getName(), cert.getSerialNumber());
957
958 x509Content.add(issuer);
959 X509Data xd = kif.newX509Data(x509Content);
960 data.add(xd);
961 }
962
963
964
965 KeyInfo ki = kif.newKeyInfo(data);
966
967
968
969 DOMSignContext dsc = new DOMSignContext(privateKey, node);
970 dsc.putNamespacePrefix(XML_DIGSIG_NS, "ns2");
971
972
973 try {
974 SignedInfo si = initSignedInfo(fac);
975 XMLSignature signature = fac.newXMLSignature(si, ki);
976
977
978 signature.sign(dsc);
979 } catch (Exception e) {
980 throw new RuntimeException(e);
981 }
982 }
983
984
985
986
987
988
989
990 private X509Certificate FindCert(NodeList childNodes) {
991 try {
992 for (int x = 0; x < childNodes.getLength(); x++) {
993 if (childNodes.item(x).getLocalName().equalsIgnoreCase("X509SubjectName")) {
994
995 String dn = childNodes.item(x).getTextContent().trim();
996 return FindCertByDN(new X500Principal(dn));
997
998 }
999 if (childNodes.item(x).getLocalName().equalsIgnoreCase("X509IssuerSerial")) {
1000 String X509IssuerName = null;
1001 String X509SerialNumber = null;
1002 for (int k = 0; k < childNodes.item(x).getChildNodes().getLength(); k++) {
1003 if (childNodes.item(x).getChildNodes().item(x).getLocalName().equalsIgnoreCase("X509IssuerName")) {
1004 X509IssuerName = childNodes.item(x).getTextContent().trim();
1005 }
1006 if (childNodes.item(x).getChildNodes().item(x).getLocalName().equalsIgnoreCase("X509SerialNumber")) {
1007 X509SerialNumber = childNodes.item(x).getTextContent().trim();
1008 }
1009
1010 }
1011 if (X509IssuerName != null && X509SerialNumber != null) {
1012 return FindCertByIssuer(X509IssuerName, X509SerialNumber);
1013 }
1014
1015 }
1016 }
1017 } catch (Exception ex) {
1018 logger.warn("error caught searching for a certificate", ex);
1019 }
1020 return null;
1021 }
1022
1023 private X509Certificate FindCertByDN(X500Principal name) throws Exception {
1024 KeyStore ks = GetTrustStore();
1025 if (ks == null) {
1026 return null;
1027 }
1028 Enumeration<String> aliases = ks.aliases();
1029 while (aliases.hasMoreElements()) {
1030 String nextElement = aliases.nextElement();
1031 Certificate certificate = ks.getCertificate(nextElement);
1032 X509Certificate x = (X509Certificate) certificate;
1033 if (x.getSubjectX500Principal().equals(name)) {
1034 return x;
1035 }
1036 }
1037 return null;
1038 }
1039
1040
1041
1042
1043
1044 private X509CRL downloadCRLFromWeb(String crlURL)
1045 throws MalformedURLException, IOException, CertificateException,
1046 CRLException {
1047 URL url = new URL(crlURL);
1048 InputStream crlStream = url.openStream();
1049 try {
1050
1051 X509CRL crl = (X509CRL) cf.generateCRL(crlStream);
1052 return crl;
1053 } finally {
1054 crlStream.close();
1055 }
1056 }
1057
1058 private X509Certificate FindCertByIssuer(String X509IssuerName, String X509SerialNumber) throws Exception {
1059 KeyStore ks = GetTrustStore();
1060 if (ks == null) {
1061 return null;
1062 }
1063 Enumeration<String> aliases = ks.aliases();
1064 while (aliases.hasMoreElements()) {
1065 String nextElement = aliases.nextElement();
1066 Certificate certificate = ks.getCertificate(nextElement);
1067 X509Certificate x = (X509Certificate) certificate;
1068 if (x.getIssuerDN().getName().equals(X509IssuerName)
1069 && x.getSerialNumber().toString().equalsIgnoreCase(X509SerialNumber)) {
1070 return x;
1071 }
1072 }
1073 return null;
1074 }
1075 }