1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.xml.security.keyinfo;
18
19 import java.math.BigInteger;
20 import java.security.KeyException;
21 import java.security.KeyFactory;
22 import java.security.NoSuchAlgorithmException;
23 import java.security.PublicKey;
24 import java.security.cert.CRLException;
25 import java.security.cert.CertificateEncodingException;
26 import java.security.cert.CertificateException;
27 import java.security.cert.CertificateFactory;
28 import java.security.cert.X509CRL;
29 import java.security.cert.X509Certificate;
30 import java.security.interfaces.DSAParams;
31 import java.security.interfaces.DSAPublicKey;
32 import java.security.interfaces.RSAPublicKey;
33 import java.security.spec.DSAParameterSpec;
34 import java.security.spec.DSAPublicKeySpec;
35 import java.security.spec.InvalidKeySpecException;
36 import java.security.spec.KeySpec;
37 import java.security.spec.RSAPublicKeySpec;
38 import java.util.Collection;
39 import java.util.LinkedList;
40 import java.util.List;
41
42 import org.opensaml.xml.Configuration;
43 import org.opensaml.xml.XMLObjectBuilderFactory;
44 import org.opensaml.xml.security.x509.X509Util;
45 import org.opensaml.xml.signature.DSAKeyValue;
46 import org.opensaml.xml.signature.Exponent;
47 import org.opensaml.xml.signature.G;
48 import org.opensaml.xml.signature.KeyInfo;
49 import org.opensaml.xml.signature.KeyName;
50 import org.opensaml.xml.signature.KeyValue;
51 import org.opensaml.xml.signature.Modulus;
52 import org.opensaml.xml.signature.P;
53 import org.opensaml.xml.signature.Q;
54 import org.opensaml.xml.signature.RSAKeyValue;
55 import org.opensaml.xml.signature.X509Data;
56 import org.opensaml.xml.signature.X509IssuerName;
57 import org.opensaml.xml.signature.X509IssuerSerial;
58 import org.opensaml.xml.signature.X509SKI;
59 import org.opensaml.xml.signature.X509SerialNumber;
60 import org.opensaml.xml.signature.X509SubjectName;
61 import org.opensaml.xml.signature.Y;
62 import org.opensaml.xml.util.Base64;
63 import org.opensaml.xml.util.DatatypeHelper;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66
67
68
69
70
71
72
73 public class KeyInfoHelper {
74
75
76
77 private static CertificateFactory x509CertFactory;
78
79
80 protected KeyInfoHelper(){
81
82 }
83
84
85
86
87
88
89
90
91 public static List<String> getKeyNames(KeyInfo keyInfo) {
92 List<String> keynameList = new LinkedList<String>();
93
94 if (keyInfo == null) {
95 return keynameList;
96 }
97
98 List<KeyName> keyNames = keyInfo.getKeyNames();
99 for (KeyName keyName : keyNames) {
100 if (keyName.getValue() != null) {
101 keynameList.add(keyName.getValue());
102 }
103 }
104
105 return keynameList;
106 }
107
108
109
110
111
112
113
114 public static void addKeyName(KeyInfo keyInfo, String keyNameValue) {
115 KeyName keyName = (KeyName) Configuration.getBuilderFactory()
116 .getBuilder(KeyName.DEFAULT_ELEMENT_NAME)
117 .buildObject(KeyName.DEFAULT_ELEMENT_NAME);
118 keyName.setValue(keyNameValue);
119 keyInfo.getKeyNames().add(keyName);
120 }
121
122
123
124
125
126
127
128
129
130
131
132 public static List<X509Certificate> getCertificates(KeyInfo keyInfo) throws CertificateException {
133 List<X509Certificate> certList = new LinkedList<X509Certificate>();
134
135 if (keyInfo == null) {
136 return certList;
137 }
138
139 List<X509Data> x509Datas = keyInfo.getX509Datas();
140 for (X509Data x509Data : x509Datas) {
141 if (x509Data != null) {
142 certList.addAll(getCertificates(x509Data));
143 }
144 }
145
146 return certList;
147 }
148
149
150
151
152
153
154
155
156
157
158
159 public static List<X509Certificate> getCertificates(X509Data x509Data) throws CertificateException {
160 List<X509Certificate> certList = new LinkedList<X509Certificate>();
161
162 if (x509Data == null) {
163 return certList;
164 }
165
166 for (org.opensaml.xml.signature.X509Certificate xmlCert : x509Data.getX509Certificates()) {
167 if (xmlCert != null && xmlCert.getValue() != null) {
168 X509Certificate newCert = getCertificate(xmlCert);
169 certList.add(newCert);
170 }
171 }
172
173 return certList;
174 }
175
176
177
178
179
180
181
182
183
184
185
186 public static X509Certificate getCertificate(org.opensaml.xml.signature.X509Certificate xmlCert)
187 throws CertificateException {
188
189 if (xmlCert == null || xmlCert.getValue() == null) {
190 return null;
191 }
192
193 Collection<X509Certificate> certs = X509Util.decodeCertificate(Base64.decode(xmlCert.getValue()));
194 if (certs != null && certs.iterator().hasNext()) {
195 return certs.iterator().next();
196 } else {
197 return null;
198 }
199 }
200
201
202
203
204
205
206
207
208
209
210
211 public static List<X509CRL> getCRLs(KeyInfo keyInfo) throws CRLException {
212 List<X509CRL> crlList = new LinkedList<X509CRL>();
213
214 if (keyInfo == null) {
215 return crlList;
216 }
217
218 List<X509Data> x509Datas = keyInfo.getX509Datas();
219 for (X509Data x509Data : x509Datas) {
220 if (x509Data != null) {
221 crlList.addAll(getCRLs(x509Data));
222 }
223 }
224
225 return crlList;
226 }
227
228
229
230
231
232
233
234
235
236
237
238 public static List<X509CRL> getCRLs(X509Data x509Data) throws CRLException {
239 List<X509CRL> crlList = new LinkedList<X509CRL>();
240
241 if (x509Data == null) {
242 return crlList;
243 }
244
245 for (org.opensaml.xml.signature.X509CRL xmlCRL : x509Data.getX509CRLs()) {
246 if (xmlCRL != null && xmlCRL.getValue() != null) {
247 X509CRL newCRL = getCRL(xmlCRL);
248 crlList.add(newCRL);
249 }
250 }
251
252 return crlList;
253 }
254
255
256
257
258
259
260
261
262
263
264
265 public static X509CRL getCRL(org.opensaml.xml.signature.X509CRL xmlCRL) throws CRLException {
266
267 if (xmlCRL == null || xmlCRL.getValue() == null) {
268 return null;
269 }
270
271 Collection<X509CRL> crls = X509Util.decodeCRLs(Base64.decode(xmlCRL.getValue()));
272 return crls.iterator().next();
273 }
274
275
276
277
278
279
280
281
282
283
284
285 public static void addCertificate(KeyInfo keyInfo, X509Certificate cert) throws CertificateEncodingException {
286 X509Data x509Data;
287 if (keyInfo.getX509Datas().size() == 0) {
288 x509Data = (X509Data) Configuration.getBuilderFactory()
289 .getBuilder(X509Data.DEFAULT_ELEMENT_NAME)
290 .buildObject(X509Data.DEFAULT_ELEMENT_NAME);
291 keyInfo.getX509Datas().add(x509Data);
292 } else {
293 x509Data = keyInfo.getX509Datas().get(0);
294 }
295 x509Data.getX509Certificates().add(buildX509Certificate(cert));
296 }
297
298
299
300
301
302
303
304
305
306
307
308 public static void addCRL(KeyInfo keyInfo, X509CRL crl) throws CRLException {
309 X509Data x509Data;
310 if (keyInfo.getX509Datas().size() == 0) {
311 x509Data = (X509Data) Configuration.getBuilderFactory()
312 .getBuilder(X509Data.DEFAULT_ELEMENT_NAME)
313 .buildObject(X509Data.DEFAULT_ELEMENT_NAME);
314 keyInfo.getX509Datas().add(x509Data);
315 } else {
316 x509Data = keyInfo.getX509Datas().get(0);
317 }
318 x509Data.getX509CRLs().add(buildX509CRL(crl));
319 }
320
321
322
323
324
325
326
327
328
329
330 public static org.opensaml.xml.signature.X509Certificate
331 buildX509Certificate(X509Certificate cert) throws CertificateEncodingException {
332 org.opensaml.xml.signature.X509Certificate xmlCert =
333 (org.opensaml.xml.signature.X509Certificate) Configuration.getBuilderFactory()
334 .getBuilder(org.opensaml.xml.signature.X509Certificate.DEFAULT_ELEMENT_NAME)
335 .buildObject(org.opensaml.xml.signature.X509Certificate.DEFAULT_ELEMENT_NAME);
336
337 xmlCert.setValue(Base64.encodeBytes(cert.getEncoded()));
338
339 return xmlCert;
340 }
341
342
343
344
345
346
347
348
349
350
351 public static org.opensaml.xml.signature.X509CRL buildX509CRL(X509CRL crl) throws CRLException {
352 org.opensaml.xml.signature.X509CRL xmlCRL =
353 (org.opensaml.xml.signature.X509CRL) Configuration.getBuilderFactory()
354 .getBuilder(org.opensaml.xml.signature.X509CRL.DEFAULT_ELEMENT_NAME)
355 .buildObject(org.opensaml.xml.signature.X509CRL.DEFAULT_ELEMENT_NAME);
356
357 xmlCRL.setValue(Base64.encodeBytes(crl.getEncoded()));
358
359 return xmlCRL;
360 }
361
362
363
364
365
366
367
368 public static X509SubjectName buildX509SubjectName(String subjectName) {
369 X509SubjectName xmlSubjectName = (X509SubjectName) Configuration.getBuilderFactory()
370 .getBuilder(X509SubjectName.DEFAULT_ELEMENT_NAME)
371 .buildObject(X509SubjectName.DEFAULT_ELEMENT_NAME);
372 xmlSubjectName.setValue(subjectName);
373 return xmlSubjectName;
374 }
375
376
377
378
379
380
381
382
383 public static X509IssuerSerial buildX509IssuerSerial(String issuerName, BigInteger serialNumber) {
384 X509IssuerName xmlIssuerName = (X509IssuerName) Configuration.getBuilderFactory()
385 .getBuilder(X509IssuerName.DEFAULT_ELEMENT_NAME)
386 .buildObject(X509IssuerName.DEFAULT_ELEMENT_NAME);
387 xmlIssuerName.setValue(issuerName);
388
389 X509SerialNumber xmlSerialNumber = (X509SerialNumber) Configuration.getBuilderFactory()
390 .getBuilder(X509SerialNumber.DEFAULT_ELEMENT_NAME)
391 .buildObject(X509SerialNumber.DEFAULT_ELEMENT_NAME);
392 xmlSerialNumber.setValue(serialNumber);
393
394 X509IssuerSerial xmlIssuerSerial = (X509IssuerSerial) Configuration.getBuilderFactory()
395 .getBuilder(X509IssuerSerial.DEFAULT_ELEMENT_NAME)
396 .buildObject(X509IssuerSerial.DEFAULT_ELEMENT_NAME);
397 xmlIssuerSerial.setX509IssuerName(xmlIssuerName);
398 xmlIssuerSerial.setX509SerialNumber(xmlSerialNumber);
399
400 return xmlIssuerSerial;
401 }
402
403
404
405
406
407
408
409
410 public static X509SKI buildX509SKI(X509Certificate javaCert) {
411 byte[] skiPlainValue = X509Util.getSubjectKeyIdentifier(javaCert);
412 if (skiPlainValue == null || skiPlainValue.length == 0) {
413 return null;
414 }
415
416 X509SKI xmlSKI = (X509SKI) Configuration.getBuilderFactory()
417 .getBuilder(X509SKI.DEFAULT_ELEMENT_NAME)
418 .buildObject(X509SKI.DEFAULT_ELEMENT_NAME);
419 xmlSKI.setValue(Base64.encodeBytes(skiPlainValue));
420
421 return xmlSKI;
422 }
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437 public static void addPublicKey(KeyInfo keyInfo, PublicKey pk) throws IllegalArgumentException {
438 KeyValue keyValue = (KeyValue) Configuration.getBuilderFactory()
439 .getBuilder(KeyValue.DEFAULT_ELEMENT_NAME)
440 .buildObject(KeyValue.DEFAULT_ELEMENT_NAME);
441
442 if (pk instanceof RSAPublicKey) {
443 keyValue.setRSAKeyValue(buildRSAKeyValue((RSAPublicKey) pk));
444 } else if (pk instanceof DSAPublicKey) {
445 keyValue.setDSAKeyValue(buildDSAKeyValue((DSAPublicKey) pk));
446 } else {
447 throw new IllegalArgumentException("Only RSAPublicKey and DSAPublicKey are supported");
448 }
449
450 keyInfo.getKeyValues().add(keyValue);
451 }
452
453
454
455
456
457
458
459 public static RSAKeyValue buildRSAKeyValue(RSAPublicKey rsaPubKey) {
460 XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
461 RSAKeyValue rsaKeyValue = (RSAKeyValue) builderFactory
462 .getBuilder(RSAKeyValue.DEFAULT_ELEMENT_NAME)
463 .buildObject(RSAKeyValue.DEFAULT_ELEMENT_NAME);
464 Modulus modulus = (Modulus) builderFactory
465 .getBuilder(Modulus.DEFAULT_ELEMENT_NAME)
466 .buildObject(Modulus.DEFAULT_ELEMENT_NAME);
467 Exponent exponent = (Exponent) builderFactory
468 .getBuilder(Exponent.DEFAULT_ELEMENT_NAME)
469 .buildObject(Exponent.DEFAULT_ELEMENT_NAME);
470
471 modulus.setValueBigInt(rsaPubKey.getModulus());
472 rsaKeyValue.setModulus(modulus);
473
474 exponent.setValueBigInt(rsaPubKey.getPublicExponent());
475 rsaKeyValue.setExponent(exponent);
476
477 return rsaKeyValue;
478 }
479
480
481
482
483
484
485
486 public static DSAKeyValue buildDSAKeyValue(DSAPublicKey dsaPubKey) {
487 XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
488 DSAKeyValue dsaKeyValue = (DSAKeyValue) builderFactory
489 .getBuilder(DSAKeyValue.DEFAULT_ELEMENT_NAME)
490 .buildObject(DSAKeyValue.DEFAULT_ELEMENT_NAME);
491 Y y = (Y) builderFactory.getBuilder(Y.DEFAULT_ELEMENT_NAME).buildObject(Y.DEFAULT_ELEMENT_NAME);
492 G g = (G) builderFactory.getBuilder(G.DEFAULT_ELEMENT_NAME).buildObject(G.DEFAULT_ELEMENT_NAME);
493 P p = (P) builderFactory.getBuilder(P.DEFAULT_ELEMENT_NAME).buildObject(P.DEFAULT_ELEMENT_NAME);
494 Q q = (Q) builderFactory.getBuilder(Q.DEFAULT_ELEMENT_NAME).buildObject(Q.DEFAULT_ELEMENT_NAME);
495
496 y.setValueBigInt(dsaPubKey.getY());
497 dsaKeyValue.setY(y);
498
499 g.setValueBigInt(dsaPubKey.getParams().getG());
500 dsaKeyValue.setG(g);
501
502 p.setValueBigInt(dsaPubKey.getParams().getP());
503 dsaKeyValue.setP(p);
504
505 q.setValueBigInt(dsaPubKey.getParams().getQ());
506 dsaKeyValue.setQ(q);
507
508 return dsaKeyValue;
509 }
510
511
512
513
514
515
516
517
518
519
520
521
522 public static List<PublicKey> getPublicKeys(KeyInfo keyInfo) throws KeyException{
523 List<PublicKey> keys = new LinkedList<PublicKey>();
524
525 if (keyInfo == null || keyInfo.getKeyValues() == null) {
526 return keys;
527 }
528
529 for(KeyValue keyDescriptor : keyInfo.getKeyValues()){
530 keys.add(getKey(keyDescriptor));
531 }
532
533 return keys;
534 }
535
536
537
538
539
540
541
542
543
544
545 public static PublicKey getKey(KeyValue keyValue) throws KeyException{
546 if(keyValue.getDSAKeyValue() != null){
547 return getDSAKey(keyValue.getDSAKeyValue());
548 }else if(keyValue.getRSAKeyValue() != null){
549 return getRSAKey(keyValue.getRSAKeyValue());
550 }else{
551 return null;
552 }
553 }
554
555
556
557
558
559
560
561
562
563
564
565
566
567 public static PublicKey getDSAKey(DSAKeyValue keyDescriptor) throws KeyException {
568 if (! hasCompleteDSAParams(keyDescriptor)) {
569 throw new KeyException("DSAKeyValue element did not contain at least one of DSA parameters P, Q or G");
570 }
571
572 BigInteger gComponent = keyDescriptor.getG().getValueBigInt();
573 BigInteger pComponent = keyDescriptor.getP().getValueBigInt();
574 BigInteger qComponent = keyDescriptor.getQ().getValueBigInt();
575
576 DSAParams dsaParams = new DSAParameterSpec(pComponent, qComponent, gComponent);
577 return getDSAKey(keyDescriptor, dsaParams);
578 }
579
580
581
582
583
584
585
586
587
588
589
590
591
592 public static PublicKey getDSAKey(DSAKeyValue keyDescriptor, DSAParams dsaParams) throws KeyException {
593 BigInteger yComponent = keyDescriptor.getY().getValueBigInt();
594
595 DSAPublicKeySpec keySpec =
596 new DSAPublicKeySpec(yComponent, dsaParams.getP(), dsaParams.getQ(), dsaParams.getG());
597 return buildKey(keySpec, "DSA");
598 }
599
600
601
602
603
604
605
606
607
608 public static boolean hasCompleteDSAParams(DSAKeyValue keyDescriptor) {
609 if ( keyDescriptor.getG() == null || DatatypeHelper.isEmpty(keyDescriptor.getG().getValue())
610 || keyDescriptor.getP() == null || DatatypeHelper.isEmpty(keyDescriptor.getP().getValue())
611 || keyDescriptor.getQ() == null || DatatypeHelper.isEmpty(keyDescriptor.getQ().getValue())
612 ) {
613 return false;
614 }
615 return true;
616 }
617
618
619
620
621
622
623
624
625
626
627
628 public static PublicKey getRSAKey(RSAKeyValue keyDescriptor) throws KeyException {
629 BigInteger modulus = keyDescriptor.getModulus().getValueBigInt();
630 BigInteger exponent = keyDescriptor.getExponent().getValueBigInt();
631
632 RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, exponent);
633 return buildKey(keySpec, "RSA");
634 }
635
636
637
638
639
640
641
642 public static final BigInteger decodeBigIntegerFromCryptoBinary(String base64Value) {
643 return new BigInteger(1, Base64.decode(base64Value));
644 }
645
646
647
648
649
650
651
652 public static final String encodeCryptoBinaryFromBigInteger(BigInteger bigInt) {
653
654 byte[] bigIntBytes = org.apache.xml.security.utils.Base64.encode(bigInt, bigInt.bitLength());
655 return Base64.encodeBytes(bigIntBytes);
656 }
657
658
659
660
661
662
663
664
665
666
667
668
669 protected static PublicKey buildKey(KeySpec keySpec, String keyAlgorithm) throws KeyException {
670 Logger log = getLogger();
671 try {
672 KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);
673 return keyFactory.generatePublic(keySpec);
674 } catch (NoSuchAlgorithmException e) {
675 log.error(keyAlgorithm + " algorithm is not supported by this VM", e);
676 throw new KeyException(keyAlgorithm + "algorithm is not supported by the JCE", e);
677 } catch (InvalidKeySpecException e) {
678 log.error("Invalid key information", e);
679 throw new KeyException("Invalid key information", e);
680 }
681 }
682
683
684
685
686
687
688
689
690 protected static CertificateFactory getX509CertFactory() throws CertificateException {
691
692 if (x509CertFactory == null) {
693 x509CertFactory = CertificateFactory.getInstance("X.509");
694 }
695
696 return x509CertFactory;
697 }
698
699
700
701
702
703
704 private static Logger getLogger() {
705 return LoggerFactory.getLogger(KeyInfoHelper.class);
706 }
707 }