blob: 6777d4b4a2ff08ef906b6a28a0360f1c519c94ad [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.security.x509;
27
28import java.io.IOException;
29import java.io.InputStream;
30import java.io.OutputStream;
31import java.io.ObjectInputStream;
32import java.io.ObjectOutputStream;
33import java.io.Serializable;
34import java.math.BigInteger;
35import java.security.*;
36import java.util.Date;
37import java.util.Enumeration;
38
39import sun.security.util.*; // DER
40
41/**
42 * @author David Brownell
43 *
44 * @see CertAndKeyGen
45 * @deprecated Use the new X509Certificate class.
46 * This class is only restored for backwards compatibility.
47 */
48@Deprecated
49public class X509Cert implements Certificate, Serializable {
50
51 static final long serialVersionUID = -52595524744692374L;
52
53 /*
54 * NOTE: All fields are marked transient, because we do not want them to
55 * be included in the class description when we serialize an object of
56 * this class. We override "writeObject" and "readObject" to use the
57 * ASN.1 encoding of a certificate as the serialized form, instead of
58 * calling the default routines which would operate on the field values.
59 *
60 * MAKE SURE TO MARK ANY FIELDS THAT ARE ADDED IN THE FUTURE AS TRANSIENT.
61 */
62
63 /* The algorithm id */
64 transient protected AlgorithmId algid;
65
66 /*
67 * Certificate data, and its envelope
68 */
69 transient private byte rawCert [];
70 transient private byte signature [];
71 transient private byte signedCert [];
72
73 /*
74 * X509.v1 data (parsed)
75 */
76 transient private X500Name subject; // from subject
77 transient private PublicKey pubkey;
78
79 transient private Date notafter; // from CA (constructor)
80 transient private Date notbefore;
81
82 transient private int version; // from CA (signAndEncode)
83 transient private BigInteger serialnum;
84 transient private X500Name issuer;
85 transient private AlgorithmId issuerSigAlg;
86
87 /*
88 * flag to indicate whether or not this certificate has already been parsed
89 * (through a call to one of the constructors or the "decode" or
90 * "readObject" methods). This is to ensure that certificates are
91 * immutable.
92 */
93 transient private boolean parsed=false;
94
95 /*
96 * X509.v2 extensions
97 */
98
99 /*
100 * X509.v3 extensions
101 */
102
103 /*
104 * Other extensions ... Netscape, Verisign, SET, etc
105 */
106
107
108 /**
109 * Construct a uninitialized X509 Cert on which <a href="#decode">
110 * decode</a> must later be called (or which may be deserialized).
111 */
112 // XXX deprecated, delete this
113 public X509Cert() { }
114
115
116 /**
117 * Unmarshals a certificate from its encoded form, parsing the
118 * encoded bytes. This form of constructor is used by agents which
119 * need to examine and use certificate contents. That is, this is
120 * one of the more commonly used constructors. Note that the buffer
121 * must include only a certificate, and no "garbage" may be left at
122 * the end. If you need to ignore data at the end of a certificate,
123 * use another constructor.
124 *
125 * @param cert the encoded bytes, with no terminatu (CONSUMED)
126 * @exception IOException when the certificate is improperly encoded.
127 */
128 public X509Cert(byte cert []) throws IOException
129 {
130 DerValue in = new DerValue (cert);
131 parse (in);
132 if (in.data.available () != 0)
133 throw new CertParseError ("garbage at end");
134 signedCert = cert;
135 }
136
137
138 /**
139 * Unmarshals a certificate from its encoded form, parsing the
140 * encoded bytes. This form of constructor is used by agents which
141 * need to examine and use certificate contents. That is, this is
142 * one of the most commonly used constructors.
143 *
144 * @param buf the buffer holding the encoded bytes
145 * @param offset the offset in the buffer where the bytes begin
146 * @param len how many bytes of certificate exist
147 *
148 * @exception IOException when the certificate is improperly encoded.
149 */
150 public X509Cert(byte buf [], int offset, int len) throws IOException
151 {
152 DerValue in = new DerValue (buf, offset, len);
153
154 parse (in);
155 if (in.data.available () != 0)
156 throw new CertParseError ("garbage at end");
157 signedCert = new byte [len];
158 System.arraycopy (buf, offset, signedCert, 0, len);
159 }
160
161
162 /**
163 * Unmarshal a certificate from its encoded form, parsing a DER value.
164 * This form of constructor is used by agents which need to examine
165 * and use certificate contents.
166 *
167 * @param derVal the der value containing the encoded cert.
168 * @exception IOException when the certificate is improperly encoded.
169 */
170 public X509Cert(DerValue derVal) throws IOException
171 {
172 parse (derVal);
173 if (derVal.data.available () != 0)
174 throw new CertParseError ("garbage at end");
175 signedCert = derVal.toByteArray ();
176 }
177
178
179 /**
180 * Partially constructs a certificate from descriptive parameters.
181 * This constructor may be used by Certificate Authority (CA) code,
182 * which later <a href="#signAndEncode">signs and encodes</a> the
183 * certificate. Also, self-signed certificates serve as CA certificates,
184 * and are sometimes used as certificate requests.
185 *
186 * <P>Until the certificate has been signed and encoded, some of
187 * the mandatory fields in the certificate will not be available
188 * via accessor functions: the serial number, issuer name and signing
189 * algorithm, and of course the signed certificate. The fields passed
190 * to this constructor are available, and must be non-null.
191 *
192 * <P>Note that the public key being signed is generally independent of
193 * the signature algorithm being used. So for example Diffie-Hellman
194 * keys (which do not support signatures) can be placed in X.509
195 * certificates when some other signature algorithm (e.g. DSS/DSA,
196 * or one of the RSA based algorithms) is used.
197 *
198 * @see CertAndKeyGen
199 *
200 * @param subjectName the X.500 distinguished name being certified
201 * @param subjectPublicKey the public key being certified. This
202 * must be an "X509Key" implementing the "PublicKey" interface.
203 * @param notBefore the first time the certificate is valid
204 * @param notAfter the last time the certificate is valid
205 *
206 * @exception CertException if the public key is inappropriate
207 */
208 public X509Cert(X500Name subjectName, X509Key subjectPublicKey,
209 Date notBefore, Date notAfter) throws CertException
210 {
211 subject = subjectName;
212
213 if (!(subjectPublicKey instanceof PublicKey))
214 throw new CertException (CertException.err_INVALID_PUBLIC_KEY,
215 "Doesn't implement PublicKey interface");
216
217 // The X509 cert API requires X509 keys, else things break.
218 pubkey = subjectPublicKey;
219 notbefore = notBefore;
220 notafter = notAfter;
221 version = 0;
222 }
223
224
225 /**
226 * Decode an X.509 certificate from an input stream.
227 *
228 * @param in an input stream holding at least one certificate
229 * @exception IOException when the certificate is improperly encoded, or
230 * if it has already been parsed.
231 */
232 public void decode(InputStream in) throws IOException
233 {
234 DerValue val = new DerValue(in);
235 parse(val);
236 signedCert = val.toByteArray();
237 }
238
239
240 /**
241 * Appends the certificate to an output stream.
242 *
243 * @param out an input stream to which the certificate is appended.
244 * @exception IOException when appending fails.
245 */
246 public void encode (OutputStream out) throws IOException
247 { out.write (getSignedCert ()); }
248
249
250 /**
251 * Compares two certificates. This is false if the
252 * certificates are not both X.509 certs, otherwise it
253 * compares them as binary data.
254 *
255 * @param other the object being compared with this one
256 * @return true iff the certificates are equivalent
257 */
258 public boolean equals (Object other)
259 {
260 if (other instanceof X509Cert)
261 return equals ((X509Cert) other);
262 else
263 return false;
264 }
265
266
267 /**
268 * Compares two certificates, returning false if any data
269 * differs between the two.
270 *
271 * @param other the object being compared with this one
272 * @return true iff the certificates are equivalent
273 */
274 public boolean equals (X509Cert src)
275 {
276 if (this == src)
277 return true;
278 if (signedCert == null || src.signedCert == null)
279 return false;
280 if (signedCert.length != src.signedCert.length)
281 return false;
282 for (int i = 0; i < signedCert.length; i++)
283 if (signedCert [i] != src.signedCert [i])
284 return false;
285 return true;
286 }
287
288
289 /** Returns the "X.509" format identifier. */
290 public String getFormat () // for Certificate
291 { return "X.509"; }
292
293
294 /** Returns <a href="#getIssuerName">getIssuerName</a> */
295 public Principal getGuarantor () // for Certificate
296 { return getIssuerName (); }
297
298
299 /** Returns <a href="#getSubjectName">getSubjectName</a> */
300 public Principal getPrincipal ()
301 { return getSubjectName (); }
302
303
304 /**
305 * Throws an exception if the certificate is invalid because it is
306 * now outside of the certificate's validity period, or because it
307 * was not signed using the verification key provided. Successfully
308 * verifying a certificate does <em>not</em> indicate that one should
309 * trust the entity which it represents.
310 *
311 * <P><em>Note that since this class represents only a single X.509
312 * certificate, it cannot know anything about the certificate chain
313 * which is used to provide the verification key and to establish trust.
314 * Other code must manage and use those cert chains.
315 *
316 * <P>For now, you must walk the cert chain being used to verify any
317 * given cert. Start at the root, which is a self-signed certificate;
318 * verify it using the key inside the certificate. Then use that to
319 * verify the next certificate in the chain, issued by that CA. In
320 * this manner, verify each certificate until you reach the particular
321 * certificate you wish to verify. You should not use a certificate
322 * if any of the verification operations for its certificate chain
323 * were unsuccessful.
324 * </em>
325 *
326 * @param issuerPublicKey the public key of the issuing CA
327 * @exception CertException when the certificate is not valid.
328 */
329 public void verify (PublicKey issuerPublicKey)
330 throws CertException
331 {
332 Date now = new Date ();
333
334 if (now.before (notbefore))
335 throw new CertException (CertException.verf_INVALID_NOTBEFORE);
336 if (now.after (notafter))
337 throw new CertException (CertException.verf_INVALID_EXPIRED);
338 if (signedCert == null)
339 throw new CertException (CertException.verf_INVALID_SIG,
340 "?? certificate is not signed yet ??");
341
342 //
343 // Verify the signature ...
344 //
345 String algName = null;
346
347 try {
348 Signature sigVerf = null;
349
350 algName = issuerSigAlg.getName();
351 sigVerf = Signature.getInstance(algName);
352 sigVerf.initVerify (issuerPublicKey);
353 sigVerf.update (rawCert, 0, rawCert.length);
354
355 if (!sigVerf.verify (signature)) {
356 throw new CertException (CertException.verf_INVALID_SIG,
357 "Signature ... by <" + issuer + "> for <" + subject + ">");
358 }
359
360 // Gag -- too many catch clauses, let most through.
361
362 } catch (NoSuchAlgorithmException e) {
363 throw new CertException (CertException.verf_INVALID_SIG,
364 "Unsupported signature algorithm (" + algName + ")");
365
366 } catch (InvalidKeyException e) {
367 // e.printStackTrace();
368 throw new CertException (CertException.err_INVALID_PUBLIC_KEY,
369 "Algorithm (" + algName + ") rejected public key");
370
371 } catch (SignatureException e) {
372 throw new CertException (CertException.verf_INVALID_SIG,
373 "Signature by <" + issuer + "> for <" + subject + ">");
374 }
375 }
376
377
378 /**
379 * Creates an X.509 certificate, and signs it using the issuer
380 * passed (associating a signature algorithm and an X.500 name).
381 * This operation is used to implement the certificate generation
382 * functionality of a certificate authority.
383 *
384 * @see #getSignedCert
385 * @see #getSigner
386 * @see CertAndKeyGen
387 *
388 * @param serial the serial number of the certificate (non-null)
389 * @param issuer the certificate issuer (CA) (non-null)
390 * @return the signed certificate, as returned by getSignedCert
391 *
392 * @exception IOException if any of the data could not be encoded,
393 * or when any mandatory data was omitted
394 * @exception SignatureException on signing failures
395 */
396 public byte []
397 encodeAndSign (
398 BigInteger serial,
399 X500Signer issuer
400 ) throws IOException, SignatureException
401 {
402 rawCert = null;
403
404 /*
405 * Get the remaining cert parameters, and make sure we have enough.
406 *
407 * We deduce version based on what attribute data are available
408 * For now, we have no attributes, so we always deduce X.509v1 !
409 */
410 version = 0;
411 serialnum = serial;
412 this.issuer = issuer.getSigner ();
413 issuerSigAlg = issuer.getAlgorithmId ();
414
415 if (subject == null || pubkey == null
416 || notbefore == null || notafter == null)
417 throw new IOException ("not enough cert parameters");
418
419 /*
420 * Encode the raw cert, create its signature and put it
421 * into the envelope.
422 */
423 rawCert = DERencode ();
424 signedCert = sign (issuer, rawCert);
425 return signedCert;
426 }
427
428
429 /**
430 * Returns an X500Signer that may be used to create signatures. Those
431 * signature may in turn be verified using this certificate (or a
432 * copy of it).
433 *
434 * <P><em><b>NOTE:</b> If the private key is by itself capable of
435 * creating signatures, this fact may not be recognized at this time.
436 * Specifically, the case of DSS/DSA keys which get their algorithm
437 * parameters from higher in the certificate chain is not supportable
438 * without using an X509CertChain API, and there is no current support
439 * for other sources of algorithm parameters.</em>
440 *
441 * @param algorithm the signature algorithm to be used. Note that a
442 * given public/private key pair may support several such algorithms.
443 * @param privateKey the private key used to create the signature,
444 * which must correspond to the public key in this certificate
445 * @return the Signer object
446 *
447 * @exception NoSuchAlgorithmException if the signature
448 * algorithm is not supported
449 * @exception InvalidKeyException if either the key in the certificate,
450 * or the private key parameter, does not support the requested
451 * signature algorithm
452 */
453 public X500Signer getSigner (AlgorithmId algorithmId,
454 PrivateKey privateKey)
455 throws NoSuchAlgorithmException, InvalidKeyException
456 {
457 String algorithm;
458 Signature sig;
459
460 if (privateKey instanceof Key) {
461 Key key = (Key)privateKey;
462 algorithm = key.getAlgorithm();
463 } else {
464 throw new InvalidKeyException("private key not a key!");
465 }
466
467 sig = Signature.getInstance(algorithmId.getName());
468
469 if (!pubkey.getAlgorithm ().equals (algorithm)) {
470
471 throw new InvalidKeyException( "Private key algorithm " +
472 algorithm +
473 " incompatible with certificate " +
474 pubkey.getAlgorithm());
475 }
476 sig.initSign (privateKey);
477 return new X500Signer (sig, subject);
478 }
479
480
481 /**
482 * Returns a signature object that may be used to verify signatures
483 * created using a specified signature algorithm and the public key
484 * contained in this certificate.
485 *
486 * <P><em><b>NOTE:</b> If the public key in this certificate is not by
487 * itself capable of verifying signatures, this may not be recognized
488 * at this time. Specifically, the case of DSS/DSA keys which get
489 * their algorithm parameters from higher in the certificate chain
490 * is not supportable without using an X509CertChain API, and there
491 * is no current support for other sources of algorithm parameters.</em>
492 *
493 * @param algorithm the algorithm of the signature to be verified
494 * @return the Signature object
495 * @exception NoSuchAlgorithmException if the signature
496 * algorithm is not supported
497 * @exception InvalidKeyException if the key in the certificate
498 * does not support the requested signature algorithm
499 */
500 public Signature getVerifier(String algorithm)
501 throws NoSuchAlgorithmException, InvalidKeyException
502 {
503 String algName;
504 Signature sig;
505
506 sig = Signature.getInstance(algorithm);
507 sig.initVerify (pubkey);
508 return sig;
509 }
510
511
512
513 /**
514 * Return the signed X.509 certificate as a byte array.
515 * The bytes are in standard DER marshaled form.
516 * Null is returned in the case of a partially constructed cert.
517 */
518 public byte [] getSignedCert ()
519 { return (byte[])signedCert.clone(); }
520
521
522 /**
523 * Returns the certificate's serial number.
524 * Null is returned in the case of a partially constructed cert.
525 */
526 public BigInteger getSerialNumber ()
527 { return serialnum; }
528
529
530 /**
531 * Returns the subject's X.500 distinguished name.
532 */
533 public X500Name getSubjectName ()
534 { return subject; }
535
536
537 /**
538 * Returns the certificate issuer's X.500 distinguished name.
539 * Null is returned in the case of a partially constructed cert.
540 */
541 public X500Name getIssuerName ()
542 { return issuer; }
543
544
545 /**
546 * Returns the algorithm used by the issuer to sign the certificate.
547 * Null is returned in the case of a partially constructed cert.
548 */
549 public AlgorithmId getIssuerAlgorithmId ()
550 { return issuerSigAlg; }
551
552
553 /**
554 * Returns the first time the certificate is valid.
555 */
556 public Date getNotBefore ()
557 { return new Date(notbefore.getTime()); }
558
559
560 /**
561 * Returns the last time the certificate is valid.
562 */
563 public Date getNotAfter ()
564 { return new Date(notafter.getTime()); }
565
566
567 /**
568 * Returns the subject's public key. Note that some public key
569 * algorithms support an optional certificate generation policy
570 * where the keys in the certificates are not in themselves sufficient
571 * to perform a public key operation. Those keys need to be augmented
572 * by algorithm parameters, which the certificate generation policy
573 * chose not to place in the certificate.
574 *
575 * <P>Two such public key algorithms are: DSS/DSA, where algorithm
576 * parameters could be acquired from a CA certificate in the chain
577 * of issuers; and Diffie-Hellman, with a similar solution although
578 * the CA then needs both a Diffie-Hellman certificate and a signature
579 * capable certificate.
580 */
581 public PublicKey getPublicKey ()
582 { return pubkey; }
583
584
585 /**
586 * Returns the X.509 version number of this certificate, zero based.
587 * That is, "2" indicates an X.509 version 3 (1993) certificate,
588 * and "0" indicates X.509v1 (1988).
589 * Zero is returned in the case of a partially constructed cert.
590 */
591 public int getVersion ()
592 { return version; }
593
594
595 /**
596 * Calculates a hash code value for the object. Objects
597 * which are equal will also have the same hashcode.
598 */
599 public int hashCode ()
600 {
601 int retval = 0;
602
603 for (int i = 0; i < signedCert.length; i++)
604 retval += signedCert [i] * i;
605 return retval;
606 }
607
608
609 /**
610 * Returns a printable representation of the certificate. This does not
611 * contain all the information available to distinguish this from any
612 * other certificate. The certificate must be fully constructed
613 * before this function may be called; in particular, if you are
614 * creating certificates you must call encodeAndSign() before calling
615 * this function.
616 */
617 public String toString ()
618 {
619 String s;
620
621 if (subject == null || pubkey == null
622 || notbefore == null || notafter == null
623 || issuer == null || issuerSigAlg == null
624 || serialnum == null)
625 throw new NullPointerException ("X.509 cert is incomplete");
626
627 s = " X.509v" + (version + 1) + " certificate,\n";
628 s += " Subject is " + subject + "\n";
629 s += " Key: " + pubkey;
630 s += " Validity <" + notbefore + "> until <" + notafter + ">\n";
631 s += " Issuer is " + issuer + "\n";
632 s += " Issuer signature used " + issuerSigAlg.toString () + "\n";
633 s += " Serial number = " + Debug.toHexString(serialnum) + "\n";
634
635 // optional v2, v3 extras
636
637 return "[\n" + s + "]";
638 }
639
640
641 /**
642 * Returns a printable representation of the certificate.
643 *
644 * @param detailed true iff lots of detail is requested
645 */
646 public String toString (boolean detailed)
647 { return toString (); }
648
649
650 /************************************************************/
651
652 /*
653 * Cert is a SIGNED ASN.1 macro, a three elment sequence:
654 *
655 * - Data to be signed (ToBeSigned) -- the "raw" cert
656 * - Signature algorithm (SigAlgId)
657 * - The signature bits
658 *
659 * This routine unmarshals the certificate, saving the signature
660 * parts away for later verification.
661 */
662 private void parse (DerValue val) throws IOException
663 {
664 if (parsed == true) {
665 throw new IOException("Certificate already parsed");
666 }
667
668 DerValue seq [] = new DerValue [3];
669
670 seq [0] = val.data.getDerValue ();
671 seq [1] = val.data.getDerValue ();
672 seq [2] = val.data.getDerValue ();
673
674 if (val.data.available () != 0)
675 throw new CertParseError ("signed overrun, bytes = "
676 + val.data.available ());
677 if (seq [0].tag != DerValue.tag_Sequence)
678 throw new CertParseError ("signed fields invalid");
679
680 rawCert = seq [0].toByteArray (); // XXX slow; fixme!
681
682
683 issuerSigAlg = AlgorithmId.parse (seq [1]);
684 signature = seq [2].getBitString ();
685
686 if (seq [1].data.available () != 0) {
687 // XXX why was this error check commented out?
688 // It was originally part of the next check.
689 throw new CertParseError ("algid field overrun");
690 }
691
692 if (seq [2].data.available () != 0)
693 throw new CertParseError ("signed fields overrun");
694
695 /*
696 * Let's have fun parsing the cert itself.
697 */
698 DerInputStream in;
699 DerValue tmp;
700
701 in = seq [0].data;
702
703 /*
704 * Version -- this is optional (default zero). If it's there it's
705 * the first field and is specially tagged.
706 *
707 * Both branches leave "tmp" holding a value for the serial
708 * number that comes next.
709 */
710 version = 0;
711 tmp = in.getDerValue ();
712 if (tmp.isConstructed () && tmp.isContextSpecific ()) {
713 version = tmp.data.getInteger();
714 if (tmp.data.available () != 0)
715 throw new IOException ("X.509 version, bad format");
716 tmp = in.getDerValue ();
717 }
718
719 /*
720 * serial number ... an integer
721 */
722 serialnum = tmp.getBigInteger ();
723
724 /*
725 * algorithm type for CA's signature ... needs to match the
726 * one on the envelope, and that's about it! different IDs
727 * may represent a signature attack. In general we want to
728 * inherit parameters.
729 */
730 tmp = in.getDerValue ();
731 {
732 AlgorithmId algid;
733
734
735 algid = AlgorithmId.parse(tmp);
736
737 if (!algid.equals (issuerSigAlg))
738 throw new CertParseError ("CA Algorithm mismatch!");
739
740 this.algid = algid;
741 }
742
743 /*
744 * issuer name
745 */
746 issuer = new X500Name (in);
747
748 /*
749 * validity: SEQUENCE { start date, end date }
750 */
751 tmp = in.getDerValue ();
752 if (tmp.tag != DerValue.tag_Sequence)
753 throw new CertParseError ("corrupt validity field");
754
755 notbefore = tmp.data.getUTCTime ();
756 notafter = tmp.data.getUTCTime ();
757 if (tmp.data.available () != 0)
758 throw new CertParseError ("excess validity data");
759
760 /*
761 * subject name and public key
762 */
763 subject = new X500Name (in);
764
765 tmp = in.getDerValue ();
766 pubkey = X509Key.parse (tmp);
767
768 /*
769 * XXX for v2 and later, a bunch of tagged options follow
770 */
771
772 if (in.available () != 0) {
773 /*
774 * Until we parse V2/V3 data ... ignore it.
775 *
776 // throw new CertParseError ("excess cert data");
777 System.out.println (
778 "@end'o'cert, optional V2/V3 data unparsed: "
779 + in.available ()
780 + " bytes"
781 );
782 */
783 }
784
785 parsed = true;
786 }
787
788
789 /*
790 * Encode only the parts that will later be signed.
791 */
792 private byte [] DERencode () throws IOException
793 {
794 DerOutputStream raw = new DerOutputStream ();
795
796 encode (raw);
797 return raw.toByteArray ();
798 }
799
800
801 /*
802 * Marshal the contents of a "raw" certificate into a DER sequence.
803 */
804 private void encode (DerOutputStream out) throws IOException
805 {
806 DerOutputStream tmp = new DerOutputStream ();
807
808 /*
809 * encode serial number, issuer signing algorithm,
810 * and issuer name into the data we'll return
811 */
812 tmp.putInteger (serialnum);
813 issuerSigAlg.encode (tmp);
814 issuer.encode (tmp);
815
816 /*
817 * Validity is a two element sequence ... encode the
818 * elements, then wrap them into the data we'll return
819 */
820 {
821 DerOutputStream seq = new DerOutputStream ();
822
823 seq.putUTCTime (notbefore);
824 seq.putUTCTime (notafter);
825 tmp.write (DerValue.tag_Sequence, seq);
826 }
827
828 /*
829 * Encode subject (principal) and associated key
830 */
831 subject.encode (tmp);
832 tmp.write(pubkey.getEncoded());
833
834 /*
835 * Wrap the data; encoding of the "raw" cert is now complete.
836 */
837 out.write (DerValue.tag_Sequence, tmp);
838 }
839
840
841 /*
842 * Calculate the signature of the "raw" certificate,
843 * and marshal the cert with the signature and a
844 * description of the signing algorithm.
845 */
846 private byte [] sign (X500Signer issuer, byte data [])
847 throws IOException, SignatureException
848 {
849 /*
850 * Encode the to-be-signed data, then the algorithm used
851 * to create the signature.
852 */
853 DerOutputStream out = new DerOutputStream ();
854 DerOutputStream tmp = new DerOutputStream ();
855
856 tmp.write (data);
857 issuer.getAlgorithmId ().encode(tmp);
858
859
860 /*
861 * Create and encode the signature itself.
862 */
863 issuer.update (data, 0, data.length);
864 signature = issuer.sign ();
865 tmp.putBitString (signature);
866
867 /*
868 * Wrap the signed data in a SEQUENCE { data, algorithm, sig }
869 */
870 out.write (DerValue.tag_Sequence, tmp);
871 return out.toByteArray ();
872 }
873
874
875 /**
876 * Serialization write ... X.509 certificates serialize as
877 * themselves, and they're parsed when they get read back.
878 * (Actually they serialize as some type data from the
879 * serialization subsystem, then the cert data.)
880 */
881 private void writeObject (java.io.ObjectOutputStream stream)
882 throws IOException
883 { encode(stream); }
884
885 /**
886 * Serialization read ... X.509 certificates serialize as
887 * themselves, and they're parsed when they get read back.
888 */
889 private void readObject (ObjectInputStream stream)
890 throws IOException
891 { decode(stream); }
892}