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