KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > maverick > crypto > asn1 > x509 > X509Certificate


1 /*
2  * SSL-Explorer
3  *
4  * Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */

19             
20 package com.maverick.crypto.asn1.x509;
21
22 import java.io.ByteArrayInputStream JavaDoc;
23 import java.io.ByteArrayOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.math.BigInteger JavaDoc;
26
27 import java.util.Date JavaDoc;
28 import java.util.Enumeration JavaDoc;
29 import java.util.Hashtable JavaDoc;
30 import java.util.Vector JavaDoc;
31
32 import com.maverick.crypto.asn1.ASN1Sequence;
33 import com.maverick.crypto.asn1.DERBitString;
34 import com.maverick.crypto.asn1.DERBoolean;
35 import com.maverick.crypto.asn1.DEREncodable;
36 import com.maverick.crypto.asn1.DERIA5String;
37 import com.maverick.crypto.asn1.DERInputStream;
38 import com.maverick.crypto.asn1.DERInteger;
39 import com.maverick.crypto.asn1.DERObjectIdentifier;
40 import com.maverick.crypto.asn1.DEROutputStream;
41 import com.maverick.crypto.asn1.misc.MiscObjectIdentifiers;
42 import com.maverick.crypto.asn1.misc.NetscapeCertType;
43 import com.maverick.crypto.asn1.misc.NetscapeRevocationURL;
44 import com.maverick.crypto.asn1.misc.VerisignCzagExtension;
45 import com.maverick.crypto.asn1.ASN1Dump;
46 import com.maverick.crypto.asn1.pkcs.PKCSObjectIdentifiers;
47 import com.maverick.crypto.asn1.x509.BasicConstraints;
48 import com.maverick.crypto.asn1.x509.KeyUsage;
49 import com.maverick.crypto.asn1.x509.X509CertificateStructure;
50 import com.maverick.crypto.asn1.x509.X509Extension;
51 import com.maverick.crypto.asn1.x509.X509Extensions;
52 import com.maverick.crypto.encoders.Hex;
53 import com.maverick.crypto.publickey.*;
54
55 public class X509Certificate
56 {
57     private X509CertificateStructure c;
58     private Hashtable JavaDoc pkcs12Attributes = new Hashtable JavaDoc();
59     private Vector JavaDoc pkcs12Ordering = new Vector JavaDoc();
60
61     public X509Certificate(
62         X509CertificateStructure c)
63     {
64         this.c = c;
65     }
66
67     public void checkValidity()
68         throws CertificateException
69     {
70         this.checkValidity(new Date JavaDoc());
71     }
72
73     public void checkValidity(
74         Date JavaDoc date)
75         throws CertificateException
76     {
77         if (date.after(this.getNotAfter()))
78         {
79             throw new CertificateException(
80           CertificateException.CERTIFICATE_EXPIRED,
81           "Certificate expired on " + c.getEndDate().getTime());
82         }
83
84         if (date.before(this.getNotBefore()))
85         {
86             throw new CertificateException(
87           CertificateException.CERTIFICATE_NOT_YET_VALID,
88           "certificate not valid till " + c.getStartDate().getTime());
89         }
90     }
91
92     public int getVersion()
93     {
94         return c.getVersion();
95     }
96
97     public BigInteger JavaDoc getSerialNumber()
98     {
99         return c.getSerialNumber().getValue();
100     }
101
102     public X509Name getIssuerDN()
103     {
104         return c.getIssuer();
105     }
106
107     public X509Name getSubjectDN()
108     {
109         return c.getSubject();
110     }
111
112     public Date JavaDoc getNotBefore()
113     {
114         return c.getStartDate().getDate();
115     }
116
117     public Date JavaDoc getNotAfter()
118     {
119         return c.getEndDate().getDate();
120     }
121
122     public byte[] getTBSCertificate()
123         throws CertificateException
124     {
125         ByteArrayOutputStream JavaDoc bOut = new ByteArrayOutputStream JavaDoc();
126         DEROutputStream dOut = new DEROutputStream(bOut);
127
128         try
129         {
130             dOut.writeObject(c.getTBSCertificate());
131
132             return bOut.toByteArray();
133         }
134         catch (IOException JavaDoc e)
135         {
136             throw new CertificateException(CertificateException.CERTIFICATE_ENCODING_ERROR,
137                                            e.toString());
138         }
139     }
140
141     public byte[] getSignature()
142     {
143         return c.getSignature().getBytes();
144     }
145
146     /**
147      * return a more "meaningful" representation for the signature algorithm used in
148      * the certficate.
149      */

150     /*public String getSigAlgName()
151     {
152         Provider prov = Security.getProvider("BC");
153         String algName = prov.getProperty("Alg.Alias.Signature." + this.getSigAlgOID());
154
155         if (algName != null)
156         {
157             return algName;
158         }
159
160         Provider[] provs = Security.getProviders();
161
162         //
163         // search every provider looking for a real algorithm
164         //
165         for (int i = 0; i != provs.length; i++)
166         {
167             algName = provs[i].getProperty("Alg.Alias.Signature." + this.getSigAlgOID());
168             if (algName != null)
169             {
170                 return algName;
171             }
172         }
173
174         return this.getSigAlgOID();
175     }*/

176
177     /**
178      * return the object identifier for the signature.
179      */

180     public String JavaDoc getSigAlgOID()
181     {
182         return c.getSignatureAlgorithm().getObjectId().getId();
183     }
184
185
186     public String JavaDoc getSigAlgName() throws CertificateException {
187       if(getSigAlgOID().equals("1.2.840.113549.1.1.4")) {
188         return "MD5WithRSAEncryption";
189       } else if(getSigAlgOID().equals("1.2.840.113549.1.1.5")) {
190         return "SHA1WithRSAEncryption";
191       } else
192         throw new CertificateException(CertificateException.CERTIFICATE_UNSUPPORTED_ALGORITHM,
193                                        "Unsupported signature algorithm id "
194                                        + getSigAlgOID());
195     }
196
197     /**
198      * return the signature parameters, or null if there aren't any.
199      */

200     public byte[] getSigAlgParams()
201     {
202         ByteArrayOutputStream JavaDoc bOut = new ByteArrayOutputStream JavaDoc();
203
204         if (c.getSignatureAlgorithm().getParameters() != null)
205         {
206             try
207             {
208                 DEROutputStream dOut = new DEROutputStream(bOut);
209
210                 dOut.writeObject(c.getSignatureAlgorithm().getParameters());
211             }
212             catch (Exception JavaDoc e)
213             {
214                 throw new RuntimeException JavaDoc("exception getting sig parameters " + e);
215             }
216
217             return bOut.toByteArray();
218         }
219         else
220         {
221             return null;
222         }
223     }
224
225     public boolean[] getIssuerUniqueID()
226     {
227         DERBitString id = c.getTBSCertificate().getIssuerUniqueId();
228
229         if (id != null)
230         {
231             byte[] bytes = id.getBytes();
232             boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()];
233
234             for (int i = 0; i != boolId.length; i++)
235             {
236                 boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
237             }
238
239             return boolId;
240         }
241
242         return null;
243     }
244
245     public boolean[] getSubjectUniqueID()
246     {
247         DERBitString id = c.getTBSCertificate().getSubjectUniqueId();
248
249         if (id != null)
250         {
251             byte[] bytes = id.getBytes();
252             boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()];
253
254             for (int i = 0; i != boolId.length; i++)
255             {
256                 boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
257             }
258
259             return boolId;
260         }
261
262         return null;
263     }
264
265     public boolean[] getKeyUsage()
266     {
267         byte[] bytes = this.getExtensionBytes("2.5.29.15");
268         int length = 0;
269
270         if (bytes != null)
271         {
272             try
273             {
274                 DERInputStream dIn = new DERInputStream(new ByteArrayInputStream JavaDoc(bytes));
275                 DERBitString bits = (DERBitString)dIn.readObject();
276
277                 bytes = bits.getBytes();
278                 length = (bytes.length * 8) - bits.getPadBits();
279             }
280             catch (Exception JavaDoc e)
281             {
282                 throw new RuntimeException JavaDoc("error processing key usage extension");
283             }
284
285             boolean[] keyUsage = new boolean[(length < 9) ? 9 : length];
286
287             for (int i = 0; i != length; i++)
288             {
289                 keyUsage[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
290             }
291
292             return keyUsage;
293         }
294
295         return null;
296     }
297
298     public int getBasicConstraints()
299     {
300         byte[] bytes = this.getExtensionBytes("2.5.29.19");
301
302         if (bytes != null)
303         {
304             try
305             {
306                 DERInputStream dIn = new DERInputStream(new ByteArrayInputStream JavaDoc(bytes));
307                 ASN1Sequence seq = (ASN1Sequence)dIn.readObject();
308
309                 if (seq.size() == 2)
310                 {
311                     if (((DERBoolean)seq.getObjectAt(0)).isTrue())
312                     {
313                         return ((DERInteger)seq.getObjectAt(1)).getValue().intValue();
314                     }
315                     else
316                     {
317                         return -1;
318                     }
319                 }
320                 else if (seq.size() == 1)
321                 {
322                     if (seq.getObjectAt(0) instanceof DERBoolean)
323                     {
324                         if (((DERBoolean)seq.getObjectAt(0)).isTrue())
325                         {
326                             return Integer.MAX_VALUE;
327                         }
328                         else
329                         {
330                             return -1;
331                         }
332                     }
333                     else
334                     {
335                         return -1;
336                     }
337                 }
338             }
339             catch (Exception JavaDoc e)
340             {
341                 throw new RuntimeException JavaDoc("error processing key usage extension");
342             }
343         }
344
345         return -1;
346     }
347
348     public X509Extension[] getCriticalExtensionOIDs()
349     {
350         if (this.getVersion() == 3)
351         {
352             Vector JavaDoc set = new Vector JavaDoc();
353             X509Extensions extensions = c.getTBSCertificate().getExtensions();
354
355             if (extensions != null)
356             {
357                 Enumeration JavaDoc e = extensions.oids();
358
359                 while (e.hasMoreElements())
360                 {
361                     DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
362                     X509Extension ext = extensions.getExtension(oid);
363
364                     if (ext.isCritical())
365                     {
366                         set.addElement(oid.getId());
367                     }
368                 }
369
370                 X509Extension[] ext = new X509Extension[set.size()];
371                 set.copyInto(ext);
372                 return ext;
373             }
374         }
375
376         return null;
377     }
378
379     private byte[] getExtensionBytes(String JavaDoc oid)
380     {
381         X509Extensions exts = c.getTBSCertificate().getExtensions();
382
383         if (exts != null)
384         {
385             X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid));
386             if (ext != null)
387             {
388                 return ext.getValue().getOctets();
389             }
390         }
391
392         return null;
393     }
394
395     public byte[] getExtensionValue(String JavaDoc oid)
396     {
397         X509Extensions exts = c.getTBSCertificate().getExtensions();
398
399         if (exts != null)
400         {
401             X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid));
402
403             if (ext != null)
404             {
405                 ByteArrayOutputStream JavaDoc bOut = new ByteArrayOutputStream JavaDoc();
406                 DEROutputStream dOut = new DEROutputStream(bOut);
407
408                 try
409                 {
410                     dOut.writeObject(ext.getValue());
411
412                     return bOut.toByteArray();
413                 }
414                 catch (Exception JavaDoc e)
415                 {
416                     throw new RuntimeException JavaDoc("error encoding " + e.toString());
417                 }
418             }
419         }
420
421         return null;
422     }
423
424     public X509Extension[] getNonCriticalExtensionOIDs()
425     {
426         if (this.getVersion() == 3)
427         {
428             Vector JavaDoc set = new Vector JavaDoc();
429             X509Extensions extensions = c.getTBSCertificate().getExtensions();
430
431             if (extensions != null)
432             {
433                 Enumeration JavaDoc e = extensions.oids();
434
435                 while (e.hasMoreElements())
436                 {
437                     DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
438                     X509Extension ext = extensions.getExtension(oid);
439
440                     if (!ext.isCritical())
441                     {
442                         set.addElement(oid.getId());
443                     }
444                 }
445
446                 X509Extension[] ext = new X509Extension[set.size()];
447                 set.copyInto(ext);
448                 return ext;
449             }
450         }
451
452         return null;
453     }
454
455     public boolean hasUnsupportedCriticalExtension()
456     {
457         if (this.getVersion() == 3)
458         {
459             X509Extensions extensions = c.getTBSCertificate().getExtensions();
460
461             if (extensions != null)
462             {
463                 Enumeration JavaDoc e = extensions.oids();
464
465                 while (e.hasMoreElements())
466                 {
467                     DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
468                     if (oid.getId().equals("2.5.29.15")
469                        || oid.getId().equals("2.5.29.19"))
470                     {
471                         continue;
472                     }
473
474                     X509Extension ext = extensions.getExtension(oid);
475
476                     if (ext.isCritical())
477                     {
478                         return true;
479                     }
480                 }
481             }
482         }
483
484         return false;
485     }
486
487     public PublicKey getPublicKey() throws CertificateException
488     {
489       try {
490         AlgorithmIdentifier algId = c.getSubjectPublicKeyInfo().getAlgorithmId();
491         if (algId.getObjectId().equals(PKCSObjectIdentifiers.rsaEncryption)
492             || algId.getObjectId().equals(X509ObjectIdentifiers.id_ea_rsa)) {
493           RSAPublicKeyStructure rsa = RSAPublicKeyStructure.getInstance(
494             c.getSubjectPublicKeyInfo().
495             getPublicKey());
496           return new RsaPublicKey(rsa.getModulus(),
497                                   rsa.getPublicExponent());
498         } else
499           throw new CertificateException(CertificateException.CERTIFICATE_UNSUPPORTED_ALGORITHM,
500                                          "Public key algorithm id "
501                                          + algId.getObjectId().getId()
502                                          + " is not supported");
503
504       }
505       catch (IOException JavaDoc ex) {
506         throw new CertificateException(CertificateException.CERTIFICATE_GENERAL_ERROR,
507                                        ex.getMessage());
508       }
509     }
510
511     public byte[] getEncoded()
512         throws CertificateException
513     {
514         ByteArrayOutputStream JavaDoc bOut = new ByteArrayOutputStream JavaDoc();
515         DEROutputStream dOut = new DEROutputStream(bOut);
516
517         try
518         {
519             dOut.writeObject(c);
520
521             return bOut.toByteArray();
522         }
523         catch (IOException JavaDoc e)
524         {
525             throw new CertificateException(
526           CertificateException.CERTIFICATE_ENCODING_ERROR,
527           e.toString());
528         }
529     }
530
531     public void setBagAttribute(
532         DERObjectIdentifier oid,
533         DEREncodable attribute)
534     {
535         pkcs12Attributes.put(oid, attribute);
536         pkcs12Ordering.addElement(oid);
537     }
538
539     public DEREncodable getBagAttribute(
540         DERObjectIdentifier oid)
541     {
542         return (DEREncodable)pkcs12Attributes.get(oid);
543     }
544
545     public Enumeration JavaDoc getBagAttributeKeys()
546     {
547         return pkcs12Ordering.elements();
548     }
549
550     public String JavaDoc toString()
551     {
552         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
553         String JavaDoc nl = System.getProperty("line.separator");
554
555
556           buf.append(" [0] Version: " + this.getVersion() + nl);
557           buf.append(" SerialNumber: " + this.getSerialNumber() + nl);
558           buf.append(" IssuerDN: " + this.getIssuerDN() + nl);
559           buf.append(" Start Date: " + this.getNotBefore() + nl);
560           buf.append(" Final Date: " + this.getNotAfter() + nl);
561           buf.append(" SubjectDN: " + this.getSubjectDN() + nl);
562         try {
563           buf.append(" Public Key: " + this.getPublicKey() + nl);
564
565         }
566         catch (CertificateException ex1) {
567           buf.append(" Public Key: " + ex1.getMessage());
568         }
569
570         try {
571           buf.append(" Signature Algorithm: " + this.getSigAlgName() + nl);
572         } catch(CertificateException ex1) {
573           buf.append(" Signature Algorithm: " + ex1.getMessage());
574         }
575
576         byte[] sig = this.getSignature();
577
578         buf.append(" Signature: " + new String JavaDoc(Hex.encode(sig, 0, 20)) + nl);
579         for (int i = 20; i < sig.length; i += 20)
580         {
581             if (i < sig.length - 20)
582             {
583                 buf.append(" " + new String JavaDoc(Hex.encode(sig, i, 20)) + nl);
584             }
585             else
586             {
587                 buf.append(" " + new String JavaDoc(Hex.encode(sig, i, sig.length - i)) + nl);
588             }
589         }
590
591         X509Extensions extensions = c.getTBSCertificate().getExtensions();
592
593         if (extensions != null)
594         {
595             Enumeration JavaDoc e = extensions.oids();
596
597             if (e.hasMoreElements())
598             {
599                 buf.append(" Extensions: \n");
600             }
601
602             while (e.hasMoreElements())
603             {
604                 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
605                 X509Extension ext = extensions.getExtension(oid);
606
607                 if (ext.getValue() != null)
608                 {
609                     byte[] octs = ext.getValue().getOctets();
610                     ByteArrayInputStream JavaDoc bIn = new ByteArrayInputStream JavaDoc(octs);
611                     DERInputStream dIn = new DERInputStream(bIn);
612                     buf.append(" critical(" + ext.isCritical() + ") ");
613                     try
614                     {
615                         if (oid.equals(X509Extensions.BasicConstraints))
616                         {
617                             buf.append(new BasicConstraints((ASN1Sequence)dIn.readObject()) + nl);
618                         }
619                         else if (oid.equals(X509Extensions.KeyUsage))
620                         {
621                             buf.append(new KeyUsage((DERBitString)dIn.readObject()) + nl);
622                         }
623                         else if (oid.equals(MiscObjectIdentifiers.netscapeCertType))
624                         {
625                             buf.append(new NetscapeCertType((DERBitString)dIn.readObject()) + nl);
626                         }
627                         else if (oid.equals(MiscObjectIdentifiers.netscapeRevocationURL))
628                         {
629                             buf.append(new NetscapeRevocationURL((DERIA5String)dIn.readObject()) + nl);
630                         }
631                         else if (oid.equals(MiscObjectIdentifiers.verisignCzagExtension))
632                         {
633                             buf.append(new VerisignCzagExtension((DERIA5String)dIn.readObject()) + nl);
634                         }
635                         else
636                         {
637                             buf.append(oid.getId());
638                             buf.append(" value = " + ASN1Dump.dumpAsString(dIn.readObject()) + nl);
639                             //buf.append(" value = " + "*****" + nl);
640
}
641                     }
642                     catch (Exception JavaDoc ex)
643                     {
644                         buf.append(oid.getId());
645                    // buf.append(" value = " + new String(Hex.encode(ext.getValue().getOctets())) + nl);
646
buf.append(" value = " + "*****" + nl);
647                     }
648                 }
649                 else
650                 {
651                     buf.append(nl);
652                 }
653             }
654         }
655
656         return buf.toString();
657     }
658
659     public final void verify(
660         PublicKey key)
661         throws CertificateException
662     {
663
664
665
666     }
667
668
669 }
670
Popular Tags