Dead
[official-gcc.git] / gomp-20050608-branch / libjava / classpath / gnu / java / security / x509 / X509Certificate.java
blob14ac43a25e61340e92b366d4e48b0c8a67192846
1 /* X509Certificate.java -- X.509 certificate.
2 Copyright (C) 2003, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.java.security.x509;
41 import gnu.classpath.debug.Component;
42 import gnu.classpath.debug.SystemLogger;
44 import gnu.java.security.OID;
45 import gnu.java.security.der.BitString;
46 import gnu.java.security.der.DER;
47 import gnu.java.security.der.DERReader;
48 import gnu.java.security.der.DERValue;
49 import gnu.java.security.x509.ext.BasicConstraints;
50 import gnu.java.security.x509.ext.ExtendedKeyUsage;
51 import gnu.java.security.x509.ext.Extension;
52 import gnu.java.security.x509.ext.IssuerAlternativeNames;
53 import gnu.java.security.x509.ext.KeyUsage;
54 import gnu.java.security.x509.ext.SubjectAlternativeNames;
56 import java.io.IOException;
57 import java.io.InputStream;
58 import java.io.PrintWriter;
59 import java.io.Serializable;
60 import java.io.StringWriter;
61 import java.math.BigInteger;
62 import java.security.AlgorithmParameters;
63 import java.security.InvalidKeyException;
64 import java.security.KeyFactory;
65 import java.security.NoSuchAlgorithmException;
66 import java.security.NoSuchProviderException;
67 import java.security.Principal;
68 import java.security.PublicKey;
69 import java.security.Signature;
70 import java.security.SignatureException;
71 import java.security.cert.CertificateEncodingException;
72 import java.security.cert.CertificateException;
73 import java.security.cert.CertificateExpiredException;
74 import java.security.cert.CertificateNotYetValidException;
75 import java.security.cert.CertificateParsingException;
76 import java.security.interfaces.DSAParams;
77 import java.security.interfaces.DSAPublicKey;
78 import java.security.spec.DSAParameterSpec;
79 import java.security.spec.X509EncodedKeySpec;
80 import java.util.ArrayList;
81 import java.util.Arrays;
82 import java.util.Collection;
83 import java.util.Collections;
84 import java.util.Date;
85 import java.util.HashMap;
86 import java.util.HashSet;
87 import java.util.Iterator;
88 import java.util.List;
89 import java.util.Map;
90 import java.util.Set;
92 import java.util.logging.Level;
93 import java.util.logging.Logger;
95 import javax.security.auth.x500.X500Principal;
97 /**
98 * An implementation of X.509 certificates.
100 * @author Casey Marshall (rsdio@metastatic.org)
102 public class X509Certificate extends java.security.cert.X509Certificate
103 implements Serializable, GnuPKIExtension
106 // Constants and fields.
107 // ------------------------------------------------------------------------
109 private static final Logger logger = SystemLogger.SYSTEM;
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");
119 // This object SHOULD be serialized with an instance of
120 // java.security.cert.Certificate.CertificateRep, thus all fields are
121 // transient.
123 // The encoded certificate.
124 protected transient byte[] encoded;
126 // TBSCertificate part.
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;
141 // Signature.
142 protected transient OID sigAlgId;
143 protected transient byte[] sigAlgVal;
144 protected transient byte[] signature;
146 // Constructors.
147 // ------------------------------------------------------------------------
150 * Create a new X.509 certificate from the encoded data. The input
151 * data are expected to be the ASN.1 DER encoding of the certificate.
153 * @param encoded The encoded certificate data.
154 * @throws IOException If the certificate cannot be read, possibly
155 * from a formatting error.
156 * @throws CertificateException If the data read is not an X.509
157 * certificate.
159 public X509Certificate(InputStream encoded)
160 throws CertificateException, IOException
162 super();
163 extensions = new HashMap();
166 parse(encoded);
168 catch (IOException ioe)
170 logger.log (Component.X509, "", ioe);
171 throw ioe;
173 catch (Exception e)
175 logger.log (Component.X509, "", e);
176 CertificateException ce = new CertificateException(e.getMessage());
177 ce.initCause (e);
178 throw ce;
182 protected X509Certificate()
184 extensions = new HashMap();
187 // X509Certificate methods.
188 // ------------------------------------------------------------------------
190 public void checkValidity()
191 throws CertificateExpiredException, CertificateNotYetValidException
193 checkValidity(new Date());
196 public void checkValidity(Date date)
197 throws CertificateExpiredException, CertificateNotYetValidException
199 if (date.compareTo(notBefore) < 0)
201 throw new CertificateNotYetValidException();
203 if (date.compareTo(notAfter) > 0)
205 throw new CertificateExpiredException();
209 public int getVersion()
211 return version;
214 public BigInteger getSerialNumber()
216 return serialNo;
219 public Principal getIssuerDN()
221 return issuer;
224 public X500Principal getIssuerX500Principal()
226 return new X500Principal(issuer.getDer());
229 public Principal getSubjectDN()
231 return subject;
234 public X500Principal getSubjectX500Principal()
236 return new X500Principal(subject.getDer());
239 public Date getNotBefore()
241 return (Date) notBefore.clone();
244 public Date getNotAfter()
246 return (Date) notAfter.clone();
249 public byte[] getTBSCertificate() throws CertificateEncodingException
251 return (byte[]) tbsCertBytes.clone();
254 public byte[] getSignature()
256 return (byte[]) signature.clone();
259 public String getSigAlgName()
261 if (sigAlgId.equals(ID_DSA_WITH_SHA1))
263 return "SHA1withDSA";
265 if (sigAlgId.equals(ID_RSA_WITH_MD2))
267 return "MD2withRSA";
269 if (sigAlgId.equals(ID_RSA_WITH_MD5))
271 return "MD5withRSA";
273 if (sigAlgId.equals(ID_RSA_WITH_SHA1))
275 return "SHA1withRSA";
277 return "unknown";
280 public String getSigAlgOID()
282 return sigAlgId.toString();
285 public byte[] getSigAlgParams()
287 return (byte[]) sigAlgVal.clone();
290 public boolean[] getIssuerUniqueID()
292 if (issuerUniqueId != null)
294 return issuerUniqueId.toBooleanArray();
296 return null;
299 public boolean[] getSubjectUniqueID()
301 if (subjectUniqueId != null)
303 return subjectUniqueId.toBooleanArray();
305 return null;
308 public boolean[] getKeyUsage()
310 Extension e = getExtension(KeyUsage.ID);
311 if (e != null)
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;
319 return null;
322 public List getExtendedKeyUsage() throws CertificateParsingException
324 Extension e = getExtension(ExtendedKeyUsage.ID);
325 if (e != null)
327 List a = ((ExtendedKeyUsage) e.getValue()).getPurposeIds();
328 List b = new ArrayList(a.size());
329 for (Iterator it = a.iterator(); it.hasNext(); )
331 b.add(it.next().toString());
333 return Collections.unmodifiableList(b);
335 return null;
338 public int getBasicConstraints()
340 Extension e = getExtension(BasicConstraints.ID);
341 if (e != null)
343 return ((BasicConstraints) e.getValue()).getPathLengthConstraint();
345 return -1;
348 public Collection getSubjectAlternativeNames()
349 throws CertificateParsingException
351 Extension e = getExtension(SubjectAlternativeNames.ID);
352 if (e != null)
354 return ((SubjectAlternativeNames) e.getValue()).getNames();
356 return null;
359 public Collection getIssuerAlternativeNames()
360 throws CertificateParsingException
362 Extension e = getExtension(IssuerAlternativeNames.ID);
363 if (e != null)
365 return ((IssuerAlternativeNames) e.getValue()).getNames();
367 return null;
370 \f// X509Extension methods.
371 // ------------------------------------------------------------------------
373 public boolean hasUnsupportedCriticalExtension()
375 for (Iterator it = extensions.values().iterator(); it.hasNext(); )
377 Extension e = (Extension) it.next();
378 if (e.isCritical() && !e.isSupported())
379 return true;
381 return false;
384 public Set getCriticalExtensionOIDs()
386 HashSet s = new HashSet();
387 for (Iterator it = extensions.values().iterator(); it.hasNext(); )
389 Extension e = (Extension) it.next();
390 if (e.isCritical())
391 s.add(e.getOid().toString());
393 return Collections.unmodifiableSet(s);
396 public Set getNonCriticalExtensionOIDs()
398 HashSet s = new HashSet();
399 for (Iterator it = extensions.values().iterator(); it.hasNext(); )
401 Extension e = (Extension) it.next();
402 if (!e.isCritical())
403 s.add(e.getOid().toString());
405 return Collections.unmodifiableSet(s);
408 public byte[] getExtensionValue(String oid)
410 Extension e = getExtension(new OID(oid));
411 if (e != null)
413 return e.getValue().getEncoded();
415 return null;
418 // GnuPKIExtension method.
419 // -------------------------------------------------------------------------
421 public Extension getExtension(OID oid)
423 return (Extension) extensions.get(oid);
426 public Collection getExtensions()
428 return extensions.values();
431 // Certificate methods.
432 // -------------------------------------------------------------------------
434 public byte[] getEncoded() throws CertificateEncodingException
436 return (byte[]) encoded.clone();
439 public void verify(PublicKey key)
440 throws CertificateException, NoSuchAlgorithmException,
441 InvalidKeyException, NoSuchProviderException, SignatureException
443 Signature sig = Signature.getInstance(sigAlgId.toString());
444 doVerify(sig, key);
447 public void verify(PublicKey key, String provider)
448 throws CertificateException, NoSuchAlgorithmException,
449 InvalidKeyException, NoSuchProviderException, SignatureException
451 Signature sig = Signature.getInstance(sigAlgId.toString(), provider);
452 doVerify(sig, key);
455 public String toString()
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)
468 out.println();
469 out.print(Util.hexDump(sigAlgVal, " "));
471 else
473 out.println(" null;");
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(); )
492 out.println(" " + it.next());
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();
503 public PublicKey getPublicKey()
505 return subjectKey;
508 public boolean equals(Object other)
510 if (!(other instanceof X509Certificate))
511 return false;
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);
521 catch (CertificateEncodingException cee)
523 return false;
527 // Own methods.
528 // ------------------------------------------------------------------------
531 * Verify this certificate's signature.
533 private void doVerify(Signature sig, PublicKey key)
534 throws CertificateException, InvalidKeyException, SignatureException
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))
542 throw new CertificateException("signature not validated");
547 * Parse a DER stream into an X.509 certificate.
549 * @param encoded The encoded bytes.
551 private void parse(InputStream encoded) throws Exception
553 DERReader der = new DERReader(encoded);
555 // Certificate ::= SEQUENCE {
556 DERValue cert = der.read();
557 logger.log (Component.X509, "start Certificate len == {0}",
558 new Integer (cert.getLength()));
560 this.encoded = cert.getEncoded();
561 if (!cert.isConstructed())
563 throw new IOException("malformed Certificate");
566 // TBSCertificate ::= SEQUENCE {
567 DERValue tbsCert = der.read();
568 if (tbsCert.getValue() != DER.CONSTRUCTED_VALUE)
570 throw new IOException("malformed TBSCertificate");
572 tbsCertBytes = tbsCert.getEncoded();
573 logger.log (Component.X509, "start TBSCertificate len == {0}",
574 new Integer (tbsCert.getLength()));
576 // Version ::= INTEGER [0] { v1(0), v2(1), v3(2) }
577 DERValue val = der.read();
578 if (val.getTagClass() == DER.CONTEXT && val.getTag() == 0)
580 version = ((BigInteger) der.read().getValue()).intValue() + 1;
581 val = der.read();
583 else
585 version = 1;
587 logger.log (Component.X509, "read version == {0}",
588 new Integer (version));
590 // SerialNumber ::= INTEGER
591 serialNo = (BigInteger) val.getValue();
592 logger.log (Component.X509, "read serial number == {0}", serialNo);
594 // AlgorithmIdentifier ::= SEQUENCE {
595 val = der.read();
596 if (!val.isConstructed())
598 throw new IOException("malformed AlgorithmIdentifier");
600 int certAlgLen = val.getLength();
601 logger.log (Component.X509, "start AlgorithmIdentifier len == {0}",
602 new Integer (certAlgLen));
603 val = der.read();
605 // algorithm OBJECT IDENTIFIER,
606 algId = (OID) val.getValue();
607 logger.log (Component.X509, "read algorithm ID == {0}", algId);
609 // parameters ANY DEFINED BY algorithm OPTIONAL }
610 if (certAlgLen > val.getEncodedLength())
612 val = der.read();
613 if (val == null)
615 algVal = null;
617 else
619 algVal = val.getEncoded();
621 if (val.isConstructed())
622 encoded.skip(val.getLength());
624 logger.log (Component.X509, "read algorithm parameters == {0}", algVal);
627 // issuer Name,
628 val = der.read();
629 issuer = new X500DistinguishedName(val.getEncoded());
630 der.skip(val.getLength());
631 logger.log (Component.X509, "read issuer == {0}", issuer);
633 // Validity ::= SEQUENCE {
634 // notBefore Time,
635 // notAfter Time }
636 if (!der.read().isConstructed())
638 throw new IOException("malformed Validity");
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);
645 // subject Name,
646 val = der.read();
647 subject = new X500DistinguishedName(val.getEncoded());
648 der.skip(val.getLength());
649 logger.log (Component.X509, "read subject == {0}", subject);
651 // SubjectPublicKeyInfo ::= SEQUENCE {
652 // algorithm AlgorithmIdentifier,
653 // subjectPublicKey BIT STRING }
654 DERValue spki = der.read();
655 if (!spki.isConstructed())
657 throw new IOException("malformed SubjectPublicKeyInfo");
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);
664 if (version > 1)
666 val = der.read();
668 if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 1)
670 byte[] b = (byte[]) val.getValue();
671 issuerUniqueId = new BitString(b, 1, b.length-1, b[0] & 0xFF);
672 logger.log (Component.X509, "read issuerUniqueId == {0}", issuerUniqueId);
673 val = der.read();
675 if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 2)
677 byte[] b = (byte[]) val.getValue();
678 subjectUniqueId = new BitString(b, 1, b.length-1, b[0] & 0xFF);
679 logger.log (Component.X509, "read subjectUniqueId == {0}", subjectUniqueId);
680 val = der.read();
682 if (version >= 3 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 3)
684 val = der.read();
685 logger.log (Component.X509, "start Extensions len == {0}",
686 new Integer (val.getLength()));
687 int len = 0;
688 while (len < val.getLength())
690 DERValue ext = der.read();
691 logger.log (Component.X509, "start extension len == {0}",
692 new Integer (ext.getLength()));
693 Extension e = new Extension(ext.getEncoded());
694 extensions.put(e.getOid(), e);
695 der.skip(ext.getLength());
696 len += ext.getEncodedLength();
697 logger.log (Component.X509, "read extension {0} == {1}",
698 new Object[] { e.getOid (), e });
699 logger.log (Component.X509, "count == {0}", new Integer (len));
702 val = der.read ();
705 logger.log (Component.X509, "read value {0}", val);
706 if (!val.isConstructed())
708 throw new CertificateException ("malformed AlgorithmIdentifier");
710 int sigAlgLen = val.getLength();
711 logger.log (Component.X509, "start AlgorithmIdentifier len == {0}",
712 new Integer (sigAlgLen));
713 val = der.read();
714 sigAlgId = (OID) val.getValue();
715 logger.log (Component.X509, "read algorithm id == {0}", sigAlgId);
716 if (sigAlgLen > val.getEncodedLength())
718 val = der.read();
719 if (val.getValue() == null)
721 if (subjectKey instanceof DSAPublicKey)
723 AlgorithmParameters params =
724 AlgorithmParameters.getInstance("DSA");
725 DSAParams dsap = ((DSAPublicKey) subjectKey).getParams();
726 DSAParameterSpec spec =
727 new DSAParameterSpec(dsap.getP(), dsap.getQ(), dsap.getG());
728 params.init(spec);
729 sigAlgVal = params.getEncoded();
732 else
734 sigAlgVal = (byte[]) val.getEncoded();
736 if (val.isConstructed())
738 encoded.skip(val.getLength());
740 logger.log (Component.X509, "read parameters == {0}", sigAlgVal);
742 signature = ((BitString) der.read().getValue()).toByteArray();
743 logger.log (Component.X509, "read signature ==\n{0}", Util.hexDump(signature, ">>>> "));