1 module hunt.security.x509.X509CertInfo;
2 
3 import hunt.security.x509.CertAttrSet;
4 import hunt.security.x509.CertificateAlgorithmId;
5 import hunt.security.x509.CertificateExtensions;
6 import hunt.security.x509.CertificateSerialNumber;
7 import hunt.security.x509.CertificateValidity;
8 import hunt.security.x509.CertificateVersion;
9 import hunt.security.x509.CertificateX509Key;
10 
11 import hunt.security.util.DerOutputStream;
12 
13 import hunt.collection.Enumeration;
14 import hunt.stream.Common;
15 import hunt.Exceptions;
16 
17 // import hunt.security.x509.CertAttrSet;
18 // import hunt.security.x509.CertAttrSet;
19 
20 /**
21  * The X509CertInfo class represents X.509 certificate information.
22  *
23  * <P>X.509 certificates have several base data elements, including:<UL>
24  *
25  * <LI>The <em>Subject Name</em>, an X.500 Distinguished Name for
26  *      the entity (subject) for which the certificate was issued.
27  *
28  * <LI>The <em>Subject Public Key</em>, the key of the subject.
29  *      This is one of the most important parts of the certificate.
30  *
31  * <LI>The <em>Validity Period</em>, a time period (e.g. six months)
32  *      within which the certificate is valid (unless revoked).
33  *
34  * <LI>The <em>Issuer Name</em>, an X.500 Distinguished Name for the
35  *      Certificate Authority (CA) which issued the certificate.
36  *
37  * <LI>A <em>Serial Number</em> assigned by the CA, for use in
38  *      certificate revocation and other applications.
39  *
40  * @author Amit Kapoor
41  * @author Hemma Prafullchandra
42  * @see CertAttrSet
43  * @see X509CertImpl
44  */
45 class X509CertInfo : CertAttrSet!(string, Object) {
46     /**
47      * Identifier for this attribute, to be used with the
48      * get, set, delete methods of Certificate, x509 type.
49      */
50     enum string IDENT = "x509.info";
51     // Certificate attribute names
52     enum string NAME = "info";
53     enum string DN_NAME = "dname";
54     enum string VERSION = CertificateVersion.NAME;
55     enum string SERIAL_NUMBER = CertificateSerialNumber.NAME;
56     enum string ALGORITHM_ID = CertificateAlgorithmId.NAME;
57     enum string ISSUER = "issuer";
58     enum string SUBJECT = "subject";
59     enum string VALIDITY = CertificateValidity.NAME;
60     enum string KEY = CertificateX509Key.NAME;
61     enum string ISSUER_ID = "issuerID";
62     enum string SUBJECT_ID = "subjectID";
63     enum string EXTENSIONS = CertificateExtensions.NAME;
64 
65     // X509.v1 data
66     // protected CertificateVersion _version = new CertificateVersion();
67     // protected CertificateSerialNumber   serialNum = null;
68     // protected CertificateAlgorithmId    algId = null;
69     // protected X500Name                  issuer = null;
70     // protected X500Name                  subject = null;
71     // protected CertificateValidity       interval = null;
72     // protected CertificateX509Key        pubKey = null;
73 
74     // X509.v2 & v3 extensions
75     // protected UniqueIdentity   issuerUniqueId = null;
76     // protected UniqueIdentity  subjectUniqueId = null;
77 
78     // X509.v3 extensions
79     // protected CertificateExtensions     extensions = null;
80 
81     // Attribute numbers for internal manipulation
82     private enum int ATTR_VERSION = 1;
83     private enum int ATTR_SERIAL = 2;
84     private enum int ATTR_ALGORITHM = 3;
85     private enum int ATTR_ISSUER = 4;
86     private enum int ATTR_VALIDITY = 5;
87     private enum int ATTR_SUBJECT = 6;
88     private enum int ATTR_KEY = 7;
89     private enum int ATTR_ISSUER_ID = 8;
90     private enum int ATTR_SUBJECT_ID = 9;
91     private enum int ATTR_EXTENSIONS = 10;
92 
93     // DER encoded CertificateInfo data
94     private byte[]      rawCertInfo = null;
95 
96     // The certificate attribute name to integer mapping stored here
97     // private static final Map<string,Integer> map = new HashMap<string,Integer>();
98     // static {
99     //     map.put(VERSION, Integer.valueOf(ATTR_VERSION));
100     //     map.put(SERIAL_NUMBER, Integer.valueOf(ATTR_SERIAL));
101     //     map.put(ALGORITHM_ID, Integer.valueOf(ATTR_ALGORITHM));
102     //     map.put(ISSUER, Integer.valueOf(ATTR_ISSUER));
103     //     map.put(VALIDITY, Integer.valueOf(ATTR_VALIDITY));
104     //     map.put(SUBJECT, Integer.valueOf(ATTR_SUBJECT));
105     //     map.put(KEY, Integer.valueOf(ATTR_KEY));
106     //     map.put(ISSUER_ID, Integer.valueOf(ATTR_ISSUER_ID));
107     //     map.put(SUBJECT_ID, Integer.valueOf(ATTR_SUBJECT_ID));
108     //     map.put(EXTENSIONS, Integer.valueOf(ATTR_EXTENSIONS));
109     // }
110 
111     // /**
112     //  * Construct an uninitialized X509CertInfo on which <a href="#decode">
113     //  * decode</a> must later be called (or which may be deserialized).
114     //  */
115     // X509CertInfo() { }
116 
117     // /**
118     //  * Unmarshals a certificate from its encoded form, parsing the
119     //  * encoded bytes.  This form of constructor is used by agents which
120     //  * need to examine and use certificate contents.  That is, this is
121     //  * one of the more commonly used constructors.  Note that the buffer
122     //  * must include only a certificate, and no "garbage" may be left at
123     //  * the end.  If you need to ignore data at the end of a certificate,
124     //  * use another constructor.
125     //  *
126     //  * @param cert the encoded bytes, with no trailing data.
127     //  * @exception CertificateParsingException on parsing errors.
128     //  */
129     // X509CertInfo(byte[] cert) throws CertificateParsingException {
130     //     try {
131     //         DerValue    in = new DerValue(cert);
132 
133     //         parse(in);
134     //     } catch (IOException e) {
135     //         throw new CertificateParsingException(e);
136     //     }
137     // }
138 
139     // /**
140     //  * Unmarshal a certificate from its encoded form, parsing a DER value.
141     //  * This form of constructor is used by agents which need to examine
142     //  * and use certificate contents.
143     //  *
144     //  * @param derVal the der value containing the encoded cert.
145     //  * @exception CertificateParsingException on parsing errors.
146     //  */
147     // X509CertInfo(DerValue derVal) throws CertificateParsingException {
148     //     try {
149     //         parse(derVal);
150     //     } catch (IOException e) {
151     //         throw new CertificateParsingException(e);
152     //     }
153     // }
154 
155     /**
156      * Appends the certificate to an output stream.
157      *
158      * @param stream an output stream to which the certificate is appended.
159      * @exception CertificateException on encoding errors.
160      * @exception IOException on other errors.
161      */
162     void encode(OutputStream stream)  {
163         if (rawCertInfo is null) {
164             DerOutputStream tmp = new DerOutputStream();
165             emit(tmp);
166             rawCertInfo = tmp.toByteArray();
167         }
168         stream.write(rawCertInfo.dup);
169     }
170 
171     /**
172      * Return an enumeration of names of attributes existing within this
173      * attribute.
174      */
175     Enumeration!string getElements() {
176         // AttributeNameEnumeration elements = new AttributeNameEnumeration();
177         // elements.addElement(VERSION);
178         // elements.addElement(SERIAL_NUMBER);
179         // elements.addElement(ALGORITHM_ID);
180         // elements.addElement(ISSUER);
181         // elements.addElement(VALIDITY);
182         // elements.addElement(SUBJECT);
183         // elements.addElement(KEY);
184         // elements.addElement(ISSUER_ID);
185         // elements.addElement(SUBJECT_ID);
186         // elements.addElement(EXTENSIONS);
187 
188         // return elements.elements();
189         implementationMissing();
190         return null;
191     }
192 
193     /**
194      * Return the name of this attribute.
195      */
196     string getName() {
197         return(NAME);
198     }
199 
200     /**
201      * Returns the encoded certificate info.
202      *
203      * @exception CertificateEncodingException on encoding information errors.
204      */
205     byte[] getEncodedInfo() {
206                 implementationMissing();
207         return null;
208 
209         // try {
210         //     if (rawCertInfo is null) {
211         //         DerOutputStream tmp = new DerOutputStream();
212         //         emit(tmp);
213         //         rawCertInfo = tmp.toByteArray();
214         //     }
215         //     return rawCertInfo.clone();
216         // } catch (IOException e) {
217         //     throw new CertificateEncodingException(e.toString());
218         // } catch (CertificateException e) {
219         //     throw new CertificateEncodingException(e.toString());
220         // }
221     }
222 
223     // /**
224     //  * Compares two X509CertInfo objects.  This is false if the
225     //  * certificates are not both X.509 certs, otherwise it
226     //  * compares them as binary data.
227     //  *
228     //  * @param other the object being compared with this one
229     //  * @return true iff the certificates are equivalent
230     //  */
231     // bool equals(Object other) {
232     //     if (other instanceof X509CertInfo) {
233     //         return equals((X509CertInfo) other);
234     //     } else {
235     //         return false;
236     //     }
237     // }
238 
239     // /**
240     //  * Compares two certificates, returning false if any data
241     //  * differs between the two.
242     //  *
243     //  * @param other the object being compared with this one
244     //  * @return true iff the certificates are equivalent
245     //  */
246     // bool equals(X509CertInfo other) {
247     //     if (this == other) {
248     //         return(true);
249     //     } else if (rawCertInfo is null || other.rawCertInfo is null) {
250     //         return(false);
251     //     } else if (rawCertInfo.length != other.rawCertInfo.length) {
252     //         return(false);
253     //     }
254     //     for (int i = 0; i < rawCertInfo.length; i++) {
255     //         if (rawCertInfo[i] != other.rawCertInfo[i]) {
256     //             return(false);
257     //         }
258     //     }
259     //     return(true);
260     // }
261 
262     // /**
263     //  * Calculates a hash code value for the object.  Objects
264     //  * which are equal will also have the same hashcode.
265     //  */
266     // int hashCode() {
267     //     int     retval = 0;
268 
269     //     for (int i = 1; i < rawCertInfo.length; i++) {
270     //         retval += rawCertInfo[i] * i;
271     //     }
272     //     return(retval);
273     // }
274 
275     /**
276      * Returns a printable representation of the certificate.
277      */
278     override string toString() {
279     implementationMissing();
280         return "";
281 
282         // if (subject is null || pubKey is null || interval is null
283         //     || issuer is null || algId is null || serialNum is null) {
284         //         throw new NullPointerException("X.509 cert is incomplete");
285         // }
286         // StringBuilder sb = new StringBuilder();
287 
288         // sb.append("[\n");
289         // sb.append("  " ~ _version.toString() ~ "\n");
290         // sb.append("  Subject: " ~ subject.toString() ~ "\n");
291         // sb.append("  Signature Algorithm: " ~ algId.toString() ~ "\n");
292         // sb.append("  Key:  " ~ pubKey.toString() ~ "\n");
293         // sb.append("  " ~ interval.toString() ~ "\n");
294         // sb.append("  Issuer: " ~ issuer.toString() ~ "\n");
295         // sb.append("  " ~ serialNum.toString() ~ "\n");
296 
297         // // optional v2, v3 extras
298         // if (issuerUniqueId !is null) {
299         //     sb.append("  Issuer Id:\n" ~ issuerUniqueId.toString() ~ "\n");
300         // }
301         // if (subjectUniqueId !is null) {
302         //     sb.append("  Subject Id:\n" ~ subjectUniqueId.toString() ~ "\n");
303         // }
304         // if (extensions !is null) {
305         //     Collection<Extension> allExts = extensions.getAllExtensions();
306         //     Extension[] exts = allExts.toArray(new Extension[0]);
307         //     sb.append("\nCertificate Extensions: " ~ exts.length);
308         //     for (int i = 0; i < exts.length; i++) {
309         //         sb.append("\n[" ~ (i+1) ~ "]: ");
310         //         Extension ext = exts[i];
311         //         try {
312         //             if (OIDMap.getClass(ext.getExtensionId()) is null) {
313         //                 sb.append(ext.toString());
314         //                 byte[] extValue = ext.getExtensionValue();
315         //                 if (extValue !is null) {
316         //                     DerOutputStream stream = new DerOutputStream();
317         //                     stream.putOctetString(extValue);
318         //                     extValue = stream.toByteArray();
319         //                     HexDumpEncoder enc = new HexDumpEncoder();
320         //                     sb.append("Extension unknown: "
321         //                               ~ "DER encoded OCTET string =\n"
322         //                               + enc.encodeBuffer(extValue) ~ "\n");
323         //                 }
324         //             } else
325         //                 sb.append(ext.toString()); //sub-class exists
326         //         } catch (Exception e) {
327         //             sb.append(", Error parsing this extension");
328         //         }
329         //     }
330         //     Map<string,Extension> invalid = extensions.getUnparseableExtensions();
331         //     if (invalid.isEmpty() == false) {
332         //         sb.append("\nUnparseable certificate extensions: " ~ invalid.size());
333         //         int i = 1;
334         //         for (Extension ext : invalid.values()) {
335         //             sb.append("\n[" ~ (i++) ~ "]: ");
336         //             sb.append(ext);
337         //         }
338         //     }
339         // }
340         // sb.append("\n]");
341         // return sb.toString();
342     }
343 
344     /**
345      * Set the certificate attribute.
346      *
347      * @params name the name of the Certificate attribute.
348      * @params val the value of the Certificate attribute.
349      * @exception CertificateException on invalid attributes.
350      * @exception IOException on other errors.
351      */
352     void set(string name, Object val) {
353         implementationMissing();
354         // X509AttributeName attrName = new X509AttributeName(name);
355 
356         // int attr = attributeMap(attrName.getPrefix());
357         // if (attr == 0) {
358         //     throw new CertificateException("Attribute name not recognized: "
359         //                                    + name);
360         // }
361         // // set rawCertInfo to null, so that we are forced to re-encode
362         // rawCertInfo = null;
363         // string suffix = attrName.getSuffix();
364 
365         // switch (attr) {
366         // case ATTR_VERSION:
367         //     if (suffix is null) {
368         //         setVersion(val);
369         //     } else {
370         //         _version.set(suffix, val);
371         //     }
372         //     break;
373 
374         // case ATTR_SERIAL:
375         //     if (suffix is null) {
376         //         setSerialNumber(val);
377         //     } else {
378         //         serialNum.set(suffix, val);
379         //     }
380         //     break;
381 
382         // case ATTR_ALGORITHM:
383         //     if (suffix is null) {
384         //         setAlgorithmId(val);
385         //     } else {
386         //         algId.set(suffix, val);
387         //     }
388         //     break;
389 
390         // case ATTR_ISSUER:
391         //     setIssuer(val);
392         //     break;
393 
394         // case ATTR_VALIDITY:
395         //     if (suffix is null) {
396         //         setValidity(val);
397         //     } else {
398         //         interval.set(suffix, val);
399         //     }
400         //     break;
401 
402         // case ATTR_SUBJECT:
403         //     setSubject(val);
404         //     break;
405 
406         // case ATTR_KEY:
407         //     if (suffix is null) {
408         //         setKey(val);
409         //     } else {
410         //         pubKey.set(suffix, val);
411         //     }
412         //     break;
413 
414         // case ATTR_ISSUER_ID:
415         //     setIssuerUniqueId(val);
416         //     break;
417 
418         // case ATTR_SUBJECT_ID:
419         //     setSubjectUniqueId(val);
420         //     break;
421 
422         // case ATTR_EXTENSIONS:
423         //     if (suffix is null) {
424         //         setExtensions(val);
425         //     } else {
426         //         if (extensions is null)
427         //             extensions = new CertificateExtensions();
428         //         extensions.set(suffix, val);
429         //     }
430         //     break;
431         // }
432     }
433 
434     /**
435      * Delete the certificate attribute.
436      *
437      * @params name the name of the Certificate attribute.
438      * @exception CertificateException on invalid attributes.
439      * @exception IOException on other errors.
440      */
441     void remove(string name) {
442         implementationMissing();
443         // X509AttributeName attrName = new X509AttributeName(name);
444 
445         // int attr = attributeMap(attrName.getPrefix());
446         // if (attr == 0) {
447         //     throw new CertificateException("Attribute name not recognized: "
448         //                                    + name);
449         // }
450         // // set rawCertInfo to null, so that we are forced to re-encode
451         // rawCertInfo = null;
452         // string suffix = attrName.getSuffix();
453 
454         // switch (attr) {
455         // case ATTR_VERSION:
456         //     if (suffix is null) {
457         //         _version = null;
458         //     } else {
459         //         _version.remove(suffix);
460         //     }
461         //     break;
462         // case (ATTR_SERIAL):
463         //     if (suffix is null) {
464         //         serialNum = null;
465         //     } else {
466         //         serialNum.remove(suffix);
467         //     }
468         //     break;
469         // case (ATTR_ALGORITHM):
470         //     if (suffix is null) {
471         //         algId = null;
472         //     } else {
473         //         algId.remove(suffix);
474         //     }
475         //     break;
476         // case (ATTR_ISSUER):
477         //     issuer = null;
478         //     break;
479         // case (ATTR_VALIDITY):
480         //     if (suffix is null) {
481         //         interval = null;
482         //     } else {
483         //         interval.remove(suffix);
484         //     }
485         //     break;
486         // case (ATTR_SUBJECT):
487         //     subject = null;
488         //     break;
489         // case (ATTR_KEY):
490         //     if (suffix is null) {
491         //         pubKey = null;
492         //     } else {
493         //         pubKey.remove(suffix);
494         //     }
495         //     break;
496         // case (ATTR_ISSUER_ID):
497         //     issuerUniqueId = null;
498         //     break;
499         // case (ATTR_SUBJECT_ID):
500         //     subjectUniqueId = null;
501         //     break;
502         // case (ATTR_EXTENSIONS):
503         //     if (suffix is null) {
504         //         extensions = null;
505         //     } else {
506         //         if (extensions !is null)
507         //            extensions.remove(suffix);
508         //     }
509         //     break;
510         // }
511     }
512 
513     /**
514      * Get the certificate attribute.
515      *
516      * @params name the name of the Certificate attribute.
517      *
518      * @exception CertificateException on invalid attributes.
519      * @exception IOException on other errors.
520      */
521     Object get(string name) {
522         // X509AttributeName attrName = new X509AttributeName(name);
523 
524         // int attr = attributeMap(attrName.getPrefix());
525         // if (attr == 0) {
526         //     throw new CertificateParsingException(
527         //                   "Attribute name not recognized: " ~ name);
528         // }
529         // string suffix = attrName.getSuffix();
530 
531         // switch (attr) { // frequently used attributes first
532         // case (ATTR_EXTENSIONS):
533         //     if (suffix is null) {
534         //         return(extensions);
535         //     } else {
536         //         if (extensions is null) {
537         //             return null;
538         //         } else {
539         //             return(extensions.get(suffix));
540         //         }
541         //     }
542         // case (ATTR_SUBJECT):
543         //     if (suffix is null) {
544         //         return(subject);
545         //     } else {
546         //         return(getX500Name(suffix, false));
547         //     }
548         // case (ATTR_ISSUER):
549         //     if (suffix is null) {
550         //         return(issuer);
551         //     } else {
552         //         return(getX500Name(suffix, true));
553         //     }
554         // case (ATTR_KEY):
555         //     if (suffix is null) {
556         //         return(pubKey);
557         //     } else {
558         //         return(pubKey.get(suffix));
559         //     }
560         // case (ATTR_ALGORITHM):
561         //     if (suffix is null) {
562         //         return(algId);
563         //     } else {
564         //         return(algId.get(suffix));
565         //     }
566         // case (ATTR_VALIDITY):
567         //     if (suffix is null) {
568         //         return(interval);
569         //     } else {
570         //         return(interval.get(suffix));
571         //     }
572         // case (ATTR_VERSION):
573         //     if (suffix is null) {
574         //         return(_version);
575         //     } else {
576         //         return(_version.get(suffix));
577         //     }
578         // case (ATTR_SERIAL):
579         //     if (suffix is null) {
580         //         return(serialNum);
581         //     } else {
582         //         return(serialNum.get(suffix));
583         //     }
584         // case (ATTR_ISSUER_ID):
585         //     return(issuerUniqueId);
586         // case (ATTR_SUBJECT_ID):
587         //     return(subjectUniqueId);
588         // }
589         return null;
590     }
591 
592     // /*
593     //  * Get the Issuer or Subject name
594     //  */
595     // private Object getX500Name(string name, bool getIssuer)
596     //     {
597     //     if (name.equalsIgnoreCase(X509CertInfo.DN_NAME)) {
598     //         return getIssuer ? issuer : subject;
599     //     } else if (name.equalsIgnoreCase("x500principal")) {
600     //         return getIssuer ? issuer.asX500Principal()
601     //                          : subject.asX500Principal();
602     //     } else {
603     //         throw new IOException("Attribute name not recognized.");
604     //     }
605     // }
606 
607     // /*
608     //  * This routine unmarshals the certificate information.
609     //  */
610     // private void parse(DerValue val)
611     // throws CertificateParsingException, IOException {
612     //     DerInputStream  in;
613     //     DerValue        tmp;
614 
615     //     if (val.tag != DerValue.tag_Sequence) {
616     //         throw new CertificateParsingException("signed fields invalid");
617     //     }
618     //     rawCertInfo = val.toByteArray();
619 
620     //     in = val.data;
621 
622     //     // Version
623     //     tmp = in.getDerValue();
624     //     if (tmp.isContextSpecific((byte)0)) {
625     //         _version = new CertificateVersion(tmp);
626     //         tmp = in.getDerValue();
627     //     }
628 
629     //     // Serial number ... an integer
630     //     serialNum = new CertificateSerialNumber(tmp);
631 
632     //     // Algorithm Identifier
633     //     algId = new CertificateAlgorithmId(in);
634 
635     //     // Issuer name
636     //     issuer = new X500Name(in);
637     //     if (issuer.isEmpty()) {
638     //         throw new CertificateParsingException(
639     //             "Empty issuer DN not allowed in X509Certificates");
640     //     }
641 
642     //     // validity:  SEQUENCE { start date, end date }
643     //     interval = new CertificateValidity(in);
644 
645     //     // subject name
646     //     subject = new X500Name(in);
647     //     if ((_version.compare(CertificateVersion.V1) == 0) &&
648     //             subject.isEmpty()) {
649     //         throw new CertificateParsingException(
650     //                   "Empty subject DN not allowed in v1 certificate");
651     //     }
652 
653     //     // key
654     //     pubKey = new CertificateX509Key(in);
655 
656     //     // If more data available, make sure version is not v1.
657     //     if (in.available() != 0) {
658     //         if (_version.compare(CertificateVersion.V1) == 0) {
659     //             throw new CertificateParsingException(
660     //                       "no more data allowed for version 1 certificate");
661     //         }
662     //     } else {
663     //         return;
664     //     }
665 
666     //     // Get the issuerUniqueId if present
667     //     tmp = in.getDerValue();
668     //     if (tmp.isContextSpecific((byte)1)) {
669     //         issuerUniqueId = new UniqueIdentity(tmp);
670     //         if (in.available() == 0)
671     //             return;
672     //         tmp = in.getDerValue();
673     //     }
674 
675     //     // Get the subjectUniqueId if present.
676     //     if (tmp.isContextSpecific((byte)2)) {
677     //         subjectUniqueId = new UniqueIdentity(tmp);
678     //         if (in.available() == 0)
679     //             return;
680     //         tmp = in.getDerValue();
681     //     }
682 
683     //     // Get the extensions.
684     //     if (_version.compare(CertificateVersion.V3) != 0) {
685     //         throw new CertificateParsingException(
686     //                   "Extensions not allowed in v2 certificate");
687     //     }
688     //     if (tmp.isConstructed() && tmp.isContextSpecific((byte)3)) {
689     //         extensions = new CertificateExtensions(tmp.data);
690     //     }
691 
692     //     // verify X.509 V3 Certificate
693     //     verifyCert(subject, extensions);
694 
695     // }
696 
697     // /*
698     //  * Verify if X.509 V3 Certificate is compliant with RFC 3280.
699     //  */
700     // private void verifyCert(X500Name subject,
701     //     CertificateExtensions extensions)
702     //     throws CertificateParsingException, IOException {
703 
704     //     // if SubjectName is empty, check for SubjectAlternativeNameExtension
705     //     if (subject.isEmpty()) {
706     //         if (extensions is null) {
707     //             throw new CertificateParsingException("X.509 Certificate is " ~
708     //                     "incomplete: subject field is empty, and certificate " ~
709     //                     "has no extensions");
710     //         }
711     //         SubjectAlternativeNameExtension subjectAltNameExt = null;
712     //         SubjectAlternativeNameExtension extValue = null;
713     //         GeneralNames names = null;
714     //         try {
715     //             subjectAltNameExt = (SubjectAlternativeNameExtension)
716     //                     extensions.get(SubjectAlternativeNameExtension.NAME);
717     //             names = subjectAltNameExt.get(
718     //                     SubjectAlternativeNameExtension.SUBJECT_NAME);
719     //         } catch (IOException e) {
720     //             throw new CertificateParsingException("X.509 Certificate is " ~
721     //                     "incomplete: subject field is empty, and " ~
722     //                     "SubjectAlternativeName extension is absent");
723     //         }
724 
725     //         // SubjectAlternativeName extension is empty or not marked critical
726     //         if (names is null || names.isEmpty()) {
727     //             throw new CertificateParsingException("X.509 Certificate is " ~
728     //                     "incomplete: subject field is empty, and " ~
729     //                     "SubjectAlternativeName extension is empty");
730     //         } else if (subjectAltNameExt.isCritical() == false) {
731     //             throw new CertificateParsingException("X.509 Certificate is " ~
732     //                     "incomplete: SubjectAlternativeName extension MUST " ~
733     //                     "be marked critical when subject field is empty");
734     //         }
735     //     }
736     // }
737 
738     /*
739      * Marshal the contents of a "raw" certificate into a DER sequence.
740      */
741     private void emit(DerOutputStream stream) {
742         DerOutputStream tmp = new DerOutputStream();
743 
744         // // version number, iff not V1
745         // _version.encode(tmp);
746 
747         // // Encode serial number, issuer signing algorithm, issuer name
748         // // and validity
749         // serialNum.encode(tmp);
750         // algId.encode(tmp);
751 
752         // if ((_version.compare(CertificateVersion.V1) == 0) &&
753         //     (issuer.toString() is null))
754         //     throw new CertificateParsingException(
755         //               "Null issuer DN not allowed in v1 certificate");
756 
757         // issuer.encode(tmp);
758         // interval.encode(tmp);
759 
760         // // Encode subject (principal) and associated key
761         // if ((_version.compare(CertificateVersion.V1) == 0) &&
762         //     (subject.toString() is null))
763         //     throw new CertificateParsingException(
764         //               "Null subject DN not allowed in v1 certificate");
765         // subject.encode(tmp);
766         // pubKey.encode(tmp);
767 
768         // // Encode issuerUniqueId & subjectUniqueId.
769         // if (issuerUniqueId !is null) {
770         //     issuerUniqueId.encode(tmp, DerValue.createTag(DerValue.TAG_CONTEXT,
771         //                                                   false,(byte)1));
772         // }
773         // if (subjectUniqueId !is null) {
774         //     subjectUniqueId.encode(tmp, DerValue.createTag(DerValue.TAG_CONTEXT,
775         //                                                    false,(byte)2));
776         // }
777 
778         // // Write all the extensions.
779         // if (extensions !is null) {
780         //     extensions.encode(tmp);
781         // }
782 
783         // // Wrap the data; encoding of the "raw" cert is now complete.
784         // stream.write(DerValue.tag_Sequence, tmp);
785 
786                 implementationMissing();
787 
788     }
789 
790     // /**
791     //  * Returns the integer attribute number for the passed attribute name.
792     //  */
793     // private int attributeMap(string name) {
794     //     Integer num = map.get(name);
795     //     if (num is null) {
796     //         return 0;
797     //     }
798     //     return num.intValue();
799     // }
800 
801     // /**
802     //  * Set the version number of the certificate.
803     //  *
804     //  * @params val the Object class value for the Extensions
805     //  * @exception CertificateException on invalid data.
806     //  */
807     // private void setVersion(Object val) throws CertificateException {
808     //     if (!(val instanceof CertificateVersion)) {
809     //         throw new CertificateException("Version class type invalid.");
810     //     }
811     //     _version = (CertificateVersion)val;
812     // }
813 
814     // /**
815     //  * Set the serial number of the certificate.
816     //  *
817     //  * @params val the Object class value for the CertificateSerialNumber
818     //  * @exception CertificateException on invalid data.
819     //  */
820     // private void setSerialNumber(Object val) throws CertificateException {
821     //     if (!(val instanceof CertificateSerialNumber)) {
822     //         throw new CertificateException("SerialNumber class type invalid.");
823     //     }
824     //     serialNum = (CertificateSerialNumber)val;
825     // }
826 
827     // /**
828     //  * Set the algorithm id of the certificate.
829     //  *
830     //  * @params val the Object class value for the AlgorithmId
831     //  * @exception CertificateException on invalid data.
832     //  */
833     // private void setAlgorithmId(Object val) throws CertificateException {
834     //     if (!(val instanceof CertificateAlgorithmId)) {
835     //         throw new CertificateException(
836     //                          "AlgorithmId class type invalid.");
837     //     }
838     //     algId = (CertificateAlgorithmId)val;
839     // }
840 
841     // /**
842     //  * Set the issuer name of the certificate.
843     //  *
844     //  * @params val the Object class value for the issuer
845     //  * @exception CertificateException on invalid data.
846     //  */
847     // private void setIssuer(Object val) throws CertificateException {
848     //     if (!(val instanceof X500Name)) {
849     //         throw new CertificateException(
850     //                          "Issuer class type invalid.");
851     //     }
852     //     issuer = (X500Name)val;
853     // }
854 
855     // /**
856     //  * Set the validity interval of the certificate.
857     //  *
858     //  * @params val the Object class value for the CertificateValidity
859     //  * @exception CertificateException on invalid data.
860     //  */
861     // private void setValidity(Object val) throws CertificateException {
862     //     if (!(val instanceof CertificateValidity)) {
863     //         throw new CertificateException(
864     //                          "CertificateValidity class type invalid.");
865     //     }
866     //     interval = (CertificateValidity)val;
867     // }
868 
869     // /**
870     //  * Set the subject name of the certificate.
871     //  *
872     //  * @params val the Object class value for the Subject
873     //  * @exception CertificateException on invalid data.
874     //  */
875     // private void setSubject(Object val) throws CertificateException {
876     //     if (!(val instanceof X500Name)) {
877     //         throw new CertificateException(
878     //                          "Subject class type invalid.");
879     //     }
880     //     subject = (X500Name)val;
881     // }
882 
883     // /**
884     //  * Set the key in the certificate.
885     //  *
886     //  * @params val the Object class value for the PublicKey
887     //  * @exception CertificateException on invalid data.
888     //  */
889     // private void setKey(Object val) throws CertificateException {
890     //     if (!(val instanceof CertificateX509Key)) {
891     //         throw new CertificateException(
892     //                          "Key class type invalid.");
893     //     }
894     //     pubKey = (CertificateX509Key)val;
895     // }
896 
897     // /**
898     //  * Set the Issuer Unique Identity in the certificate.
899     //  *
900     //  * @params val the Object class value for the IssuerUniqueId
901     //  * @exception CertificateException
902     //  */
903     // private void setIssuerUniqueId(Object val) throws CertificateException {
904     //     if (_version.compare(CertificateVersion.V2) < 0) {
905     //         throw new CertificateException("Invalid version");
906     //     }
907     //     if (!(val instanceof UniqueIdentity)) {
908     //         throw new CertificateException(
909     //                          "IssuerUniqueId class type invalid.");
910     //     }
911     //     issuerUniqueId = (UniqueIdentity)val;
912     // }
913 
914     // /**
915     //  * Set the Subject Unique Identity in the certificate.
916     //  *
917     //  * @params val the Object class value for the SubjectUniqueId
918     //  * @exception CertificateException
919     //  */
920     // private void setSubjectUniqueId(Object val) throws CertificateException {
921     //     if (_version.compare(CertificateVersion.V2) < 0) {
922     //         throw new CertificateException("Invalid version");
923     //     }
924     //     if (!(val instanceof UniqueIdentity)) {
925     //         throw new CertificateException(
926     //                          "SubjectUniqueId class type invalid.");
927     //     }
928     //     subjectUniqueId = (UniqueIdentity)val;
929     // }
930 
931     // /**
932     //  * Set the extensions in the certificate.
933     //  *
934     //  * @params val the Object class value for the Extensions
935     //  * @exception CertificateException
936     //  */
937     // private void setExtensions(Object val) throws CertificateException {
938     //     if (_version.compare(CertificateVersion.V3) < 0) {
939     //         throw new CertificateException("Invalid version");
940     //     }
941     //     if (!(val instanceof CertificateExtensions)) {
942     //       throw new CertificateException(
943     //                          "Extensions class type invalid.");
944     //     }
945     //     extensions = (CertificateExtensions)val;
946     // }
947 }