1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43:
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55:
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76: import ;
77: import ;
78: import ;
79: import ;
80: import ;
81: import ;
82: import ;
83: import ;
84: import ;
85: import ;
86: import ;
87: import ;
88: import ;
89: import ;
90: import ;
91:
92: import ;
93: import ;
94:
95: import ;
96:
97:
102: public class X509Certificate extends java.security.cert.X509Certificate
103: implements Serializable, GnuPKIExtension
104: {
105:
106:
107:
108:
109: private static final Logger logger = SystemLogger.SYSTEM;
110:
111: protected static final OID ID_DSA = new OID ("1.2.840.10040.4.1");
112: protected static final OID ID_DSA_WITH_SHA1 = new OID ("1.2.840.10040.4.3");
113: protected static final OID ID_RSA = new OID ("1.2.840.113549.1.1.1");
114: protected static final OID ID_RSA_WITH_MD2 = new OID ("1.2.840.113549.1.1.2");
115: protected static final OID ID_RSA_WITH_MD5 = new OID ("1.2.840.113549.1.1.4");
116: protected static final OID ID_RSA_WITH_SHA1 = new OID ("1.2.840.113549.1.1.5");
117: protected static final OID ID_ECDSA_WITH_SHA1 = new OID ("1.2.840.10045.4.1");
118:
119:
120:
121:
122:
123:
124: protected transient byte[] encoded;
125:
126:
127: protected transient byte[] tbsCertBytes;
128: protected transient int version;
129: protected transient BigInteger serialNo;
130: protected transient OID algId;
131: protected transient byte[] algVal;
132: protected transient X500DistinguishedName issuer;
133: protected transient Date notBefore;
134: protected transient Date notAfter;
135: protected transient X500DistinguishedName subject;
136: protected transient PublicKey subjectKey;
137: protected transient BitString issuerUniqueId;
138: protected transient BitString subjectUniqueId;
139: protected transient Map extensions;
140:
141:
142: protected transient OID sigAlgId;
143: protected transient byte[] sigAlgVal;
144: protected transient byte[] signature;
145:
146:
147:
148:
149:
159: public X509Certificate(InputStream encoded)
160: throws CertificateException, IOException
161: {
162: super();
163: extensions = new HashMap();
164: try
165: {
166: parse(encoded);
167: }
168: catch (IOException ioe)
169: {
170: logger.log (Component.X509, "", ioe);
171: throw ioe;
172: }
173: catch (Exception e)
174: {
175: logger.log (Component.X509, "", e);
176: CertificateException ce = new CertificateException(e.getMessage());
177: ce.initCause (e);
178: throw ce;
179: }
180: }
181:
182: protected X509Certificate()
183: {
184: extensions = new HashMap();
185: }
186:
187:
188:
189:
190: public void checkValidity()
191: throws CertificateExpiredException, CertificateNotYetValidException
192: {
193: checkValidity(new Date());
194: }
195:
196: public void checkValidity(Date date)
197: throws CertificateExpiredException, CertificateNotYetValidException
198: {
199: if (date.compareTo(notBefore) < 0)
200: {
201: throw new CertificateNotYetValidException();
202: }
203: if (date.compareTo(notAfter) > 0)
204: {
205: throw new CertificateExpiredException();
206: }
207: }
208:
209: public int getVersion()
210: {
211: return version;
212: }
213:
214: public BigInteger getSerialNumber()
215: {
216: return serialNo;
217: }
218:
219: public Principal getIssuerDN()
220: {
221: return issuer;
222: }
223:
224: public X500Principal getIssuerX500Principal()
225: {
226: return new X500Principal(issuer.getDer());
227: }
228:
229: public Principal getSubjectDN()
230: {
231: return subject;
232: }
233:
234: public X500Principal getSubjectX500Principal()
235: {
236: return new X500Principal(subject.getDer());
237: }
238:
239: public Date getNotBefore()
240: {
241: return (Date) notBefore.clone();
242: }
243:
244: public Date getNotAfter()
245: {
246: return (Date) notAfter.clone();
247: }
248:
249: public byte[] getTBSCertificate() throws CertificateEncodingException
250: {
251: return (byte[]) tbsCertBytes.clone();
252: }
253:
254: public byte[] getSignature()
255: {
256: return (byte[]) signature.clone();
257: }
258:
259: public String getSigAlgName()
260: {
261: if (sigAlgId.equals(ID_DSA_WITH_SHA1))
262: {
263: return "SHA1withDSA";
264: }
265: if (sigAlgId.equals(ID_RSA_WITH_MD2))
266: {
267: return "MD2withRSA";
268: }
269: if (sigAlgId.equals(ID_RSA_WITH_MD5))
270: {
271: return "MD5withRSA";
272: }
273: if (sigAlgId.equals(ID_RSA_WITH_SHA1))
274: {
275: return "SHA1withRSA";
276: }
277: return "unknown";
278: }
279:
280: public String getSigAlgOID()
281: {
282: return sigAlgId.toString();
283: }
284:
285: public byte[] getSigAlgParams()
286: {
287: return (byte[]) sigAlgVal.clone();
288: }
289:
290: public boolean[] getIssuerUniqueID()
291: {
292: if (issuerUniqueId != null)
293: {
294: return issuerUniqueId.toBooleanArray();
295: }
296: return null;
297: }
298:
299: public boolean[] getSubjectUniqueID()
300: {
301: if (subjectUniqueId != null)
302: {
303: return subjectUniqueId.toBooleanArray();
304: }
305: return null;
306: }
307:
308: public boolean[] getKeyUsage()
309: {
310: Extension e = getExtension(KeyUsage.ID);
311: if (e != null)
312: {
313: KeyUsage ku = (KeyUsage) e.getValue();
314: boolean[] result = new boolean[9];
315: boolean[] b = ku.getKeyUsage().toBooleanArray();
316: System.arraycopy(b, 0, result, 0, b.length);
317: return result;
318: }
319: return null;
320: }
321:
322: public List getExtendedKeyUsage() throws CertificateParsingException
323: {
324: Extension e = getExtension(ExtendedKeyUsage.ID);
325: if (e != null)
326: {
327: List a = ((ExtendedKeyUsage) e.getValue()).getPurposeIds();
328: List b = new ArrayList(a.size());
329: for (Iterator it = a.iterator(); it.hasNext(); )
330: {
331: b.add(it.next().toString());
332: }
333: return Collections.unmodifiableList(b);
334: }
335: return null;
336: }
337:
338: public int getBasicConstraints()
339: {
340: Extension e = getExtension(BasicConstraints.ID);
341: if (e != null)
342: {
343: return ((BasicConstraints) e.getValue()).getPathLengthConstraint();
344: }
345: return -1;
346: }
347:
348: public Collection getSubjectAlternativeNames()
349: throws CertificateParsingException
350: {
351: Extension e = getExtension(SubjectAlternativeNames.ID);
352: if (e != null)
353: {
354: return ((SubjectAlternativeNames) e.getValue()).getNames();
355: }
356: return null;
357: }
358:
359: public Collection getIssuerAlternativeNames()
360: throws CertificateParsingException
361: {
362: Extension e = getExtension(IssuerAlternativeNames.ID);
363: if (e != null)
364: {
365: return ((IssuerAlternativeNames) e.getValue()).getNames();
366: }
367: return null;
368: }
369:
370:
371:
372:
373: public boolean hasUnsupportedCriticalExtension()
374: {
375: for (Iterator it = extensions.values().iterator(); it.hasNext(); )
376: {
377: Extension e = (Extension) it.next();
378: if (e.isCritical() && !e.isSupported())
379: return true;
380: }
381: return false;
382: }
383:
384: public Set getCriticalExtensionOIDs()
385: {
386: HashSet s = new HashSet();
387: for (Iterator it = extensions.values().iterator(); it.hasNext(); )
388: {
389: Extension e = (Extension) it.next();
390: if (e.isCritical())
391: s.add(e.getOid().toString());
392: }
393: return Collections.unmodifiableSet(s);
394: }
395:
396: public Set getNonCriticalExtensionOIDs()
397: {
398: HashSet s = new HashSet();
399: for (Iterator it = extensions.values().iterator(); it.hasNext(); )
400: {
401: Extension e = (Extension) it.next();
402: if (!e.isCritical())
403: s.add(e.getOid().toString());
404: }
405: return Collections.unmodifiableSet(s);
406: }
407:
408: public byte[] getExtensionValue(String oid)
409: {
410: Extension e = getExtension(new OID(oid));
411: if (e != null)
412: {
413: return e.getValue().getEncoded();
414: }
415: return null;
416: }
417:
418:
419:
420:
421: public Extension getExtension(OID oid)
422: {
423: return (Extension) extensions.get(oid);
424: }
425:
426: public Collection getExtensions()
427: {
428: return extensions.values();
429: }
430:
431:
432:
433:
434: public byte[] getEncoded() throws CertificateEncodingException
435: {
436: return (byte[]) encoded.clone();
437: }
438:
439: public void verify(PublicKey key)
440: throws CertificateException, NoSuchAlgorithmException,
441: InvalidKeyException, NoSuchProviderException, SignatureException
442: {
443: Signature sig = Signature.getInstance(sigAlgId.toString());
444: doVerify(sig, key);
445: }
446:
447: public void verify(PublicKey key, String provider)
448: throws CertificateException, NoSuchAlgorithmException,
449: InvalidKeyException, NoSuchProviderException, SignatureException
450: {
451: Signature sig = Signature.getInstance(sigAlgId.toString(), provider);
452: doVerify(sig, key);
453: }
454:
455: public String toString()
456: {
457: StringWriter str = new StringWriter();
458: PrintWriter out = new PrintWriter(str);
459: out.println(X509Certificate.class.getName() + " {");
460: out.println(" TBSCertificate {");
461: out.println(" version = " + version + ";");
462: out.println(" serialNo = " + serialNo + ";");
463: out.println(" signature = {");
464: out.println(" algorithm = " + getSigAlgName() + ";");
465: out.print(" parameters =");
466: if (sigAlgVal != null)
467: {
468: out.println();
469: out.print(Util.hexDump(sigAlgVal, " "));
470: }
471: else
472: {
473: out.println(" null;");
474: }
475: out.println(" }");
476: out.println(" issuer = " + issuer.getName() + ";");
477: out.println(" validity = {");
478: out.println(" notBefore = " + notBefore + ";");
479: out.println(" notAfter = " + notAfter + ";");
480: out.println(" }");
481: out.println(" subject = " + subject.getName() + ";");
482: out.println(" subjectPublicKeyInfo = {");
483: out.println(" algorithm = " + subjectKey.getAlgorithm());
484: out.println(" key =");
485: out.print(Util.hexDump(subjectKey.getEncoded(), " "));
486: out.println(" };");
487: out.println(" issuerUniqueId = " + issuerUniqueId + ";");
488: out.println(" subjectUniqueId = " + subjectUniqueId + ";");
489: out.println(" extensions = {");
490: for (Iterator it = extensions.values().iterator(); it.hasNext(); )
491: {
492: out.println(" " + it.next());
493: }
494: out.println(" }");
495: out.println(" }");
496: out.println(" signatureAlgorithm = " + getSigAlgName() + ";");
497: out.println(" signatureValue =");
498: out.print(Util.hexDump(signature, " "));
499: out.println("}");
500: return str.toString();
501: }
502:
503: public PublicKey getPublicKey()
504: {
505: return subjectKey;
506: }
507:
508: public boolean equals(Object other)
509: {
510: if (!(other instanceof X509Certificate))
511: return false;
512: try
513: {
514: if (other instanceof X509Certificate)
515: return Arrays.equals(encoded, ((X509Certificate) other).encoded);
516: byte[] enc = ((X509Certificate) other).getEncoded();
517: if (enc == null)
518: return false;
519: return Arrays.equals(encoded, enc);
520: }
521: catch (CertificateEncodingException cee)
522: {
523: return false;
524: }
525: }
526:
527:
528:
529:
530:
533: private void doVerify(Signature sig, PublicKey key)
534: throws CertificateException, InvalidKeyException, SignatureException
535: {
536: logger.log (Component.X509, "verifying sig={0} key={1}",
537: new Object[] { sig, key });
538: sig.initVerify(key);
539: sig.update(tbsCertBytes);
540: if (!sig.verify(signature))
541: {
542: throw new CertificateException("signature not validated");
543: }
544: }
545:
546:
551: private void parse(InputStream encoded) throws Exception
552: {
553: DERReader der = new DERReader(encoded);
554:
555:
556: DERValue cert = der.read();
557: logger.log (Component.X509, "start Certificate len == {0}",
558: new Integer (cert.getLength()));
559:
560: this.encoded = cert.getEncoded();
561: if (!cert.isConstructed())
562: {
563: throw new IOException("malformed Certificate");
564: }
565:
566:
567: DERValue tbsCert = der.read();
568: if (tbsCert.getValue() != DER.CONSTRUCTED_VALUE)
569: {
570: throw new IOException("malformed TBSCertificate");
571: }
572: tbsCertBytes = tbsCert.getEncoded();
573: logger.log (Component.X509, "start TBSCertificate len == {0}",
574: new Integer (tbsCert.getLength()));
575:
576:
577: DERValue val = der.read();
578: if (val.getTagClass() == DER.CONTEXT && val.getTag() == 0)
579: {
580: version = ((BigInteger) der.read().getValue()).intValue() + 1;
581: val = der.read();
582: }
583: else
584: {
585: version = 1;
586: }
587: logger.log (Component.X509, "read version == {0}",
588: new Integer (version));
589:
590:
591: serialNo = (BigInteger) val.getValue();
592: logger.log (Component.X509, "read serial number == {0}", serialNo);
593:
594:
595: val = der.read();
596: if (!val.isConstructed())
597: {
598: throw new IOException("malformed AlgorithmIdentifier");
599: }
600: int certAlgLen = val.getLength();
601: logger.log (Component.X509, "start AlgorithmIdentifier len == {0}",
602: new Integer (certAlgLen));
603: val = der.read();
604:
605:
606: algId = (OID) val.getValue();
607: logger.log (Component.X509, "read algorithm ID == {0}", algId);
608:
609:
610: if (certAlgLen > val.getEncodedLength())
611: {
612: val = der.read();
613: if (val == null)
614: {
615: algVal = null;
616: }
617: else
618: {
619: algVal = val.getEncoded();
620:
621: if (val.isConstructed())
622: encoded.skip(val.getLength());
623: }
624: logger.log (Component.X509, "read algorithm parameters == {0}", algVal);
625: }
626:
627:
628: val = der.read();
629: issuer = new X500DistinguishedName(val.getEncoded());
630: der.skip(val.getLength());
631: logger.log (Component.X509, "read issuer == {0}", issuer);
632:
633:
634:
635:
636: if (!der.read().isConstructed())
637: {
638: throw new IOException("malformed Validity");
639: }
640: notBefore = (Date) der.read().getValue();
641: logger.log (Component.X509, "read notBefore == {0}", notBefore);
642: notAfter = (Date) der.read().getValue();
643: logger.log (Component.X509, "read notAfter == {0}", notAfter);
644:
645:
646: val = der.read();
647: subject = new X500DistinguishedName(val.getEncoded());
648: der.skip(val.getLength());
649: logger.log (Component.X509, "read subject == {0}", subject);
650:
651:
652:
653:
654: DERValue spki = der.read();
655: if (!spki.isConstructed())
656: {
657: throw new IOException("malformed SubjectPublicKeyInfo");
658: }
659: KeyFactory spkFac = KeyFactory.getInstance("X.509");
660: subjectKey = spkFac.generatePublic(new X509EncodedKeySpec(spki.getEncoded()));
661: der.skip(spki.getLength());
662: logger.log (Component.X509, "read subjectPublicKey == {0}", subjectKey);
663:
664: val = der.read();
665: if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 1)
666: {
667: byte[] b = (byte[]) val.getValue();
668: issuerUniqueId = new BitString(b, 1, b.length-1, b[0] & 0xFF);
669: logger.log (Component.X509, "read issuerUniqueId == {0}", issuerUniqueId);
670: val = der.read();
671: }
672: if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 2)
673: {
674: byte[] b = (byte[]) val.getValue();
675: subjectUniqueId = new BitString(b, 1, b.length-1, b[0] & 0xFF);
676: logger.log (Component.X509, "read subjectUniqueId == {0}", subjectUniqueId);
677: val = der.read();
678: }
679: if (version >= 3 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 3)
680: {
681: val = der.read();
682: logger.log (Component.X509, "start Extensions len == {0}",
683: new Integer (val.getLength()));
684: int len = 0;
685: while (len < val.getLength())
686: {
687: DERValue ext = der.read();
688: logger.log (Component.X509, "start extension len == {0}",
689: new Integer (ext.getLength()));
690: Extension e = new Extension(ext.getEncoded());
691: extensions.put(e.getOid(), e);
692: der.skip(ext.getLength());
693: len += ext.getEncodedLength();
694: logger.log (Component.X509, "read extension {0} == {1}",
695: new Object[] { e.getOid (), e });
696: logger.log (Component.X509, "count == {0}", new Integer (len));
697: }
698:
699: val = der.read ();
700: }
701:
702: logger.log (Component.X509, "read value {0}", val);
703: if (!val.isConstructed())
704: {
705: throw new CertificateException ("malformed AlgorithmIdentifier");
706: }
707: int sigAlgLen = val.getLength();
708: logger.log (Component.X509, "start AlgorithmIdentifier len == {0}",
709: new Integer (sigAlgLen));
710: val = der.read();
711: sigAlgId = (OID) val.getValue();
712: logger.log (Component.X509, "read algorithm id == {0}", sigAlgId);
713: if (sigAlgLen > val.getEncodedLength())
714: {
715: val = der.read();
716: if (val.getValue() == null)
717: {
718: if (subjectKey instanceof DSAPublicKey)
719: {
720: AlgorithmParameters params =
721: AlgorithmParameters.getInstance("DSA");
722: DSAParams dsap = ((DSAPublicKey) subjectKey).getParams();
723: DSAParameterSpec spec =
724: new DSAParameterSpec(dsap.getP(), dsap.getQ(), dsap.getG());
725: params.init(spec);
726: sigAlgVal = params.getEncoded();
727: }
728: }
729: else
730: {
731: sigAlgVal = (byte[]) val.getEncoded();
732: }
733: if (val.isConstructed())
734: {
735: encoded.skip(val.getLength());
736: }
737: logger.log (Component.X509, "read parameters == {0}", sigAlgVal);
738: }
739: signature = ((BitString) der.read().getValue()).toByteArray();
740: logger.log (Component.X509, "read signature ==\n{0}", Util.hexDump(signature, ">>>> "));
741: }
742: }