import
[org.ibex.wildebeest.git] / src / org / xwt / shoehorn3 / Crypto.java
1 // This is just a cut-and-paste of a bunch of files from Bouncycastle
2 package org.xwt.shoehorn3;
3
4 import java.io.*;
5 import java.math.BigInteger;
6 import java.util.*;
7 import java.text.*;
8
9 abstract class ASN1OctetString
10     extends DERObject
11 {
12     byte[]  string;
13
14     /**
15      * return an Octet String from a tagged object.
16      *
17      * @param obj the tagged object holding the object we want.
18      * @param explicit true if the object is meant to be explicitly
19      *              tagged false otherwise.
20      * @exception IllegalArgumentException if the tagged object cannot
21      *              be converted.
22      */
23     public static ASN1OctetString getInstance(
24         ASN1TaggedObject    obj,
25         boolean             explicit)
26     {
27         return getInstance(obj.getObject());
28     }
29         
30     /**
31      * return an Octet String from the given object.
32      *
33      * @param obj the object we want converted.
34      * @exception IllegalArgumentException if the object cannot be converted.
35      */
36     public static ASN1OctetString getInstance(
37         Object  obj)
38     {
39         if (obj == null || obj instanceof ASN1OctetString)
40         {
41             return (ASN1OctetString)obj;
42         }
43
44         if (obj instanceof ASN1TaggedObject)
45         {
46             return getInstance(((ASN1TaggedObject)obj).getObject());
47         }
48
49         if (obj instanceof ASN1Sequence)
50         {
51             Vector      v = new Vector();
52             Enumeration e = ((ASN1Sequence)obj).getObjects();
53
54             while (e.hasMoreElements())
55             {
56                 v.addElement(e.nextElement());
57             }
58
59             return new BERConstructedOctetString(v);
60         }
61
62         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
63     }
64
65     /**
66      * @param string the octets making up the octet string.
67      */
68     public ASN1OctetString(
69         byte[]  string)
70     {
71         this.string = string;
72     }
73
74     public ASN1OctetString(
75         DEREncodable obj)
76     {
77         try
78         {
79             ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
80             DEROutputStream         dOut = new DEROutputStream(bOut);
81
82             dOut.writeObject(obj);
83             dOut.close();
84
85             this.string = bOut.toByteArray();
86         }
87         catch (IOException e)
88         {
89             throw new IllegalArgumentException("Error processing object : " + e.toString());
90         }
91     }
92
93     public byte[] getOctets()
94     {
95         return string;
96     }
97
98     public int hashCode()
99     {
100         byte[]  b = this.getOctets();
101         int     value = 0;
102
103         for (int i = 0; i != b.length; i++)
104         {
105             value ^= (b[i] & 0xff) << (i % 4);
106         }
107
108         return value;
109     }
110
111     public boolean equals(
112         Object  o)
113     {
114         if (o == null || !(o instanceof DEROctetString))
115         {
116             return false;
117         }
118
119         DEROctetString  other = (DEROctetString)o;
120
121         byte[] b1 = other.getOctets();
122         byte[] b2 = this.getOctets();
123
124         if (b1.length != b2.length)
125         {
126             return false;
127         }
128
129         for (int i = 0; i != b1.length; i++)
130         {
131             if (b1[i] != b2[i])
132             {
133                 return false;
134             }
135         }
136
137         return true;
138     }
139
140     abstract void encode(DEROutputStream out)
141         throws IOException;
142 }
143
144
145 class ASN1OutputStream
146     extends DEROutputStream
147 {
148     public ASN1OutputStream(
149         OutputStream    os)
150     {
151         super(os);
152     }
153
154     public void writeObject(
155         Object    obj)
156         throws IOException
157     {
158         if (obj == null)
159         {
160             writeNull();
161         }
162         else if (obj instanceof DERObject)
163         {
164             ((DERObject)obj).encode(this);
165         }
166         else if (obj instanceof DEREncodable)
167         {
168             ((DEREncodable)obj).getDERObject().encode(this);
169         }
170         else
171         {
172             throw new IOException("object not ASN1Encodable");
173         }
174     }
175 }
176
177
178 abstract class ASN1Sequence
179     extends DERObject
180 {
181     private Vector seq = new Vector();
182
183     /**
184      * return an ASN1Sequence from the given object.
185      *
186      * @param obj the object we want converted.
187      * @exception IllegalArgumentException if the object cannot be converted.
188      */
189     public static ASN1Sequence getInstance(
190         Object  obj)
191     {
192         if (obj == null || obj instanceof ASN1Sequence)
193         {
194             return (ASN1Sequence)obj;
195         }
196
197         throw new IllegalArgumentException("unknown object in getInstance");
198     }
199
200     /**
201      * Return an ASN1 sequence from a tagged object. There is a special
202      * case here, if an object appears to have been explicitly tagged on 
203      * reading but we were expecting it to be implictly tagged in the 
204      * normal course of events it indicates that we lost the surrounding
205      * sequence - so we need to add it back (this will happen if the tagged
206      * object is a sequence that contains other sequences). If you are
207      * dealing with implicitly tagged sequences you really <b>should</b>
208      * be using this method.
209      *
210      * @param obj the tagged object.
211      * @param explicit true if the object is meant to be explicitly tagged,
212      *          false otherwise.
213      * @exception IllegalArgumentException if the tagged object cannot
214      *          be converted.
215      */
216     public static ASN1Sequence getInstance(
217         ASN1TaggedObject    obj,
218         boolean             explicit)
219     {
220         if (explicit)
221         {
222             if (!obj.isExplicit())
223             {
224                 throw new IllegalArgumentException("object implicit - explicit expected.");
225             }
226
227             return (ASN1Sequence)obj.getObject();
228         }
229         else
230         {
231             //
232             // constructed object which appears to be explicitly tagged
233             // when it should be implicit means we have to add the
234             // surrounding sequence.
235             //
236             if (obj.isExplicit())
237             {
238                 ASN1Sequence    seq;
239
240                 if (obj instanceof BERTaggedObject)
241                 {
242                     seq = new BERConstructedSequence();
243                 }
244                 else
245                 {
246                     seq = new DERConstructedSequence();
247                 }
248
249                 seq.addObject(obj.getObject());
250
251                 return seq;
252             }
253             else
254             {
255                 ASN1Sequence    seq;
256
257                 if (obj.getObject() instanceof ASN1Sequence)
258                 {
259                     return (ASN1Sequence)obj.getObject();
260                 }
261             }
262         }
263
264         throw new IllegalArgumentException(
265                 "unknown object in getInstanceFromTagged");
266     }
267
268     public Enumeration getObjects()
269     {
270         return seq.elements();
271     }
272
273     /**
274      * return the object at the sequence postion indicated by index.
275      *
276      * @param the sequence number (starting at zero) of the object
277      * @return the object at the sequence postion indicated by index.
278      */
279     public DEREncodable getObjectAt(
280         int index)
281     {
282         return (DEREncodable)seq.elementAt(index);
283     }
284
285     /**
286      * return the number of objects in this sequence.
287      *
288      * @return the number of objects in this sequence.
289      */
290     public int size()
291     {
292         return seq.size();
293     }
294
295     public int hashCode()
296     {
297         Enumeration             e = this.getObjects();
298         int                     hashCode = 0;
299
300         while (e.hasMoreElements())
301         {
302             hashCode ^= e.nextElement().hashCode();
303         }
304
305         return hashCode;
306     }
307
308     public boolean equals(
309         Object  o)
310     {
311         if (o == null || !(o instanceof ASN1Sequence))
312         {
313             return false;
314         }
315
316         ASN1Sequence   other = (ASN1Sequence)o;
317
318         if (this.size() != other.size())
319         {
320             return false;
321         }
322
323         Enumeration s1 = this.getObjects();
324         Enumeration s2 = other.getObjects();
325
326         while (s1.hasMoreElements())
327         {
328             if (!s1.nextElement().equals(s2.nextElement()))
329             {
330                 return false;
331             }
332         }
333
334         return true;
335     }
336
337     protected void addObject(
338         DEREncodable obj)
339     {
340         seq.addElement(obj);
341     }
342
343     abstract void encode(DEROutputStream out)
344         throws IOException;
345 }
346
347
348 abstract class ASN1Set
349     extends DERObject
350 {
351     protected Vector set = new Vector();
352
353     /**
354      * return an ASN1Set from the given object.
355      *
356      * @param obj the object we want converted.
357      * @exception IllegalArgumentException if the object cannot be converted.
358      */
359     public static ASN1Set getInstance(
360         Object  obj)
361     {
362         if (obj == null || obj instanceof ASN1Set)
363         {
364             return (ASN1Set)obj;
365         }
366
367         throw new IllegalArgumentException("unknown object in getInstance");
368     }
369
370     /**
371      * Return an ASN1 set from a tagged object. There is a special
372      * case here, if an object appears to have been explicitly tagged on 
373      * reading but we were expecting it to be implictly tagged in the 
374      * normal course of events it indicates that we lost the surrounding
375      * set - so we need to add it back (this will happen if the tagged
376      * object is a sequence that contains other sequences). If you are
377      * dealing with implicitly tagged sets you really <b>should</b>
378      * be using this method.
379      *
380      * @param obj the tagged object.
381      * @param explicit true if the object is meant to be explicitly tagged
382      *          false otherwise.
383      * @exception IllegalArgumentException if the tagged object cannot
384      *          be converted.
385      */
386     public static ASN1Set getInstance(
387         ASN1TaggedObject    obj,
388         boolean             explicit)
389     {
390         if (explicit)
391         {
392             if (!obj.isExplicit())
393             {
394                 throw new IllegalArgumentException("object implicit - explicit expected.");
395             }
396
397             return (ASN1Set)obj.getObject();
398         }
399         else
400         {
401             //
402             // constructed object which appears to be explicitly tagged
403             // and it's really implicit means we have to add the
404             // surrounding sequence.
405             //
406             if (obj.isExplicit())
407             {
408                 ASN1Set    set = new DERSet(obj.getObject());
409
410                 return set;
411             }
412             else
413             {
414                 //
415                 // in this case the parser returns a sequence, convert it
416                 // into a set.
417                 //
418                 DEREncodableVector  v = new DEREncodableVector();
419
420                 if (obj.getObject() instanceof ASN1Sequence)
421                 {
422                     ASN1Sequence s = (ASN1Sequence)obj.getObject();
423                     Enumeration e = s.getObjects();
424
425                     while (e.hasMoreElements())
426                     {
427                         v.add((DEREncodable)e.nextElement());
428                     }
429
430                     return new DERSet(v);
431                 }
432             }
433         }
434
435         throw new IllegalArgumentException(
436                     "unknown object in getInstanceFromTagged");
437     }
438
439     public ASN1Set()
440     {
441     }
442
443     public Enumeration getObjects()
444     {
445         return set.elements();
446     }
447
448     /**
449      * return the object at the set postion indicated by index.
450      *
451      * @param the set number (starting at zero) of the object
452      * @return the object at the set postion indicated by index.
453      */
454     public DEREncodable getObjectAt(
455         int index)
456     {
457         return (DEREncodable)set.elementAt(index);
458     }
459
460     /**
461      * return the number of objects in this set.
462      *
463      * @return the number of objects in this set.
464      */
465     public int size()
466     {
467         return set.size();
468     }
469
470     public int hashCode()
471     {
472         Enumeration             e = this.getObjects();
473         int                     hashCode = 0;
474
475         while (e.hasMoreElements())
476         {
477             hashCode ^= e.nextElement().hashCode();
478         }
479
480         return hashCode;
481     }
482
483     public boolean equals(
484         Object  o)
485     {
486         if (o == null || !(o instanceof ASN1Set))
487         {
488             return false;
489         }
490
491         ASN1Set   other = (ASN1Set)o;
492
493         if (this.size() != other.size())
494         {
495             return false;
496         }
497
498         Enumeration s1 = this.getObjects();
499         Enumeration s2 = other.getObjects();
500
501         while (s1.hasMoreElements())
502         {
503             if (!s1.nextElement().equals(s2.nextElement()))
504             {
505                 return false;
506             }
507         }
508
509         return true;
510     }
511
512     protected void addObject(
513         DEREncodable obj)
514     {
515         set.addElement(obj);
516     }
517
518     abstract void encode(DEROutputStream out)
519             throws IOException;
520 }
521
522
523 /**
524  * ASN.1 TaggedObject - in ASN.1 nottation this is any object proceeded by
525  * a [n] where n is some number - these are assume to follow the construction
526  * rules (as with sequences).
527  */
528 abstract class ASN1TaggedObject
529     extends DERObject
530 {
531     int             tagNo;
532     boolean         empty = false;
533     boolean         explicit = true;
534     DEREncodable    obj = null;
535
536     /**
537      * @param tagNo the tag number for this object.
538      * @param obj the tagged object.
539      */
540     public ASN1TaggedObject(
541         int             tagNo,
542         DEREncodable    obj)
543     {
544         this.explicit = true;
545         this.tagNo = tagNo;
546         this.obj = obj;
547     }
548
549     /**
550      * @param explicit true if the object is explicitly tagged.
551      * @param tagNo the tag number for this object.
552      * @param obj the tagged object.
553      */
554     public ASN1TaggedObject(
555         boolean         explicit,
556         int             tagNo,
557         DEREncodable    obj)
558     {
559         this.explicit = explicit;
560         this.tagNo = tagNo;
561         this.obj = obj;
562     }
563         
564         public boolean equals(
565                 Object o)
566         {
567         if (o == null || !(o instanceof ASN1TaggedObject))
568         {
569             return false;
570         }
571         
572         ASN1TaggedObject other = (ASN1TaggedObject)o;
573         
574         if(tagNo != other.tagNo || empty != other.empty || explicit != other.explicit)
575         {
576                         return false;
577                 }
578                 
579                 if(obj == null)
580                 {
581                         if(other.obj != null)
582                         {
583                                 return false;
584                         }
585                 }
586                 else
587                 {
588                         if(!(obj.equals(other.obj)))
589                         {
590                                 return false;
591                         }
592                 }
593                 
594                 return true;
595         }
596         
597     public int getTagNo()
598     {
599         return tagNo;
600     }
601
602     /**
603      * return whether or not the object may be explicitly tagged. 
604      * <p>
605      * Note: if the object has been read from an input stream, the only
606      * time you can be sure if isExplicit is returning the true state of
607      * affairs is if it returns false. An implicitly tagged object may appear
608      * to be explicitly tagged, so you need to understand the context under
609      * which the reading was done as well, see getObject below.
610      */
611     public boolean isExplicit()
612     {
613         return explicit;
614     }
615
616     public boolean isEmpty()
617     {
618         return empty;
619     }
620
621     /**
622      * return whatever was following the tag.
623      * <p>
624      * Note: tagged objects are generally context dependent if you're
625      * trying to extract a tagged object you should be going via the
626      * appropriate getInstance method.
627      */
628     public DERObject getObject()
629     {
630         if (obj != null)
631         {
632             return obj.getDERObject();
633         }
634
635         return null;
636     }
637
638     abstract void encode(DEROutputStream  out)
639         throws IOException;
640 }
641
642
643 class BERConstructedOctetString
644     extends DEROctetString
645 {
646     /**
647      * convert a vector of octet strings into a single byte string
648      */
649     static private byte[] toBytes(
650         Vector  octs)
651     {
652         ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
653
654         for (int i = 0; i != octs.size(); i++)
655         {
656             DEROctetString  o = (DEROctetString)octs.elementAt(i);
657
658             try
659             {
660                 bOut.write(o.getOctets());
661             }
662             catch (IOException e)
663             {
664                 throw new RuntimeException("exception converting octets " + e.toString());
665             }
666         }
667
668         return bOut.toByteArray();
669     }
670
671     private Vector  octs;
672
673     /**
674      * @param string the octets making up the octet string.
675      */
676     public BERConstructedOctetString(
677         byte[]  string)
678     {
679                 super(string);
680     }
681
682     public BERConstructedOctetString(
683         Vector  octs)
684     {
685                 super(toBytes(octs));
686
687         this.octs = octs;
688     }
689
690     public BERConstructedOctetString(
691         DERObject  obj)
692     {
693                 super(obj);
694     }
695
696     public BERConstructedOctetString(
697         DEREncodable  obj)
698     {
699         super(obj.getDERObject());
700     }
701
702     public byte[] getOctets()
703     {
704         return string;
705     }
706
707     /**
708      * return the DER octets that make up this string.
709      */
710     public Enumeration getObjects()
711     {
712         if (octs == null)
713         {
714             octs = generateOcts();
715         }
716
717         return octs.elements();
718     }
719
720     private Vector generateOcts()
721     {
722         int     start = 0;
723         int     end = 0;
724         Vector  vec = new Vector();
725
726         while ((end + 1) < string.length)
727         {
728             if (string[end] == 0 && string[end + 1] == 0)
729             {
730                 byte[]  nStr = new byte[end - start + 1];
731
732                 for (int i = 0; i != nStr.length; i++)
733                 {
734                     nStr[i] = string[start + i];
735                 }
736
737                 vec.addElement(new DEROctetString(nStr));
738                 start = end + 1;
739             }
740             end++;
741         }
742
743         byte[]  nStr = new byte[string.length - start];
744         for (int i = 0; i != nStr.length; i++)
745         {
746             nStr[i] = string[start + i];
747         }
748
749         vec.addElement(new DEROctetString(nStr));
750
751         return vec;
752     }
753
754     public void encode(
755         DEROutputStream out)
756         throws IOException
757     {
758         if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
759         {
760             out.write(CONSTRUCTED | OCTET_STRING);
761
762             out.write(0x80);
763
764             if (octs == null)
765             {
766                 octs = generateOcts();
767             }
768
769             for (int i = 0; i != octs.size(); i++)
770             {
771                 out.writeObject(octs.elementAt(i));
772             }
773
774             out.write(0x00);
775             out.write(0x00);
776         }
777         else
778         {
779             super.encode(out);
780         }
781     }
782 }
783
784
785 class BERConstructedSequence
786     extends DERConstructedSequence
787 {
788     /*
789      */
790     void encode(
791         DEROutputStream out)
792         throws IOException
793     {
794         if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
795         {
796             out.write(SEQUENCE | CONSTRUCTED);
797             out.write(0x80);
798             
799             Enumeration e = getObjects();
800             while (e.hasMoreElements())
801             {
802                 out.writeObject(e.nextElement());
803             }
804         
805             out.write(0x00);
806             out.write(0x00);
807         }
808         else
809         {
810             super.encode(out);
811         }
812     }
813 }
814
815
816 class BERInputStream
817     extends DERInputStream
818 {
819         private DERObject END_OF_STREAM = new DERObject() {
820                                                                                 void encode(
821                                                                                         DEROutputStream out)
822                                                                                 throws IOException
823                                                                                 {
824                                                                                         throw new IOException("Eeek!");
825                                                                                 }
826
827                                                                         };
828     public BERInputStream(
829         InputStream is)
830     {
831         super(is);
832     }
833
834     /**
835      * read a string of bytes representing an indefinite length object.
836      */
837     private byte[] readIndefiniteLengthFully()
838         throws IOException
839     {
840         ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
841         int                     b, b1;
842
843         b1 = read();
844
845         while ((b = read()) >= 0)
846         {
847                         if (b1 == 0 && b == 0)
848                         {
849                                 break;
850                         }
851
852             bOut.write(b1);
853             b1 = b;
854         }
855
856         return bOut.toByteArray();
857     }
858
859         private BERConstructedOctetString buildConstructedOctetString()
860                 throws IOException
861         {
862         Vector                  octs = new Vector();
863
864                 for (;;)
865                 {
866                         DERObject               o = readObject();
867
868                         if (o == END_OF_STREAM)
869                         {
870                                 break;
871                         }
872
873             octs.addElement(o);
874                 }
875
876                 return new BERConstructedOctetString(octs);
877         }
878
879     public DERObject readObject()
880         throws IOException
881     {
882         int tag = read();
883         if (tag == -1)
884         {
885             throw new EOFException();
886         }
887     
888         int     length = readLength();
889
890         if (length < 0)    // indefinite length method
891         {
892             switch (tag)
893             {
894             case NULL:
895                 return null;
896             case SEQUENCE | CONSTRUCTED:
897                 BERConstructedSequence  seq = new BERConstructedSequence();
898     
899                                 for (;;)
900                                 {
901                                         DERObject   obj = readObject();
902
903                                         if (obj == END_OF_STREAM)
904                                         {
905                                                 break;
906                                         }
907
908                                         seq.addObject(obj);
909                                 }
910                                 return seq;
911             case OCTET_STRING | CONSTRUCTED:
912                                 return buildConstructedOctetString();
913             case SET | CONSTRUCTED:
914                 DEREncodableVector  v = new DEREncodableVector();
915     
916                                 for (;;)
917                                 {
918                                         DERObject   obj = readObject();
919
920                                         if (obj == END_OF_STREAM)
921                                         {
922                                                 break;
923                                         }
924
925                                         v.add(obj);
926                                 }
927                                 return new BERSet(v);
928             default:
929                 //
930                 // with tagged object tag number is bottom 5 bits
931                 //
932                 if ((tag & TAGGED) != 0)  
933                 {
934                     if ((tag & 0x1f) == 0x1f)
935                     {
936                         throw new IOException("unsupported high tag encountered");
937                     }
938
939                     //
940                     // simple type - implicit... return an octet string
941                     //
942                     if ((tag & CONSTRUCTED) == 0)
943                     {
944                         byte[]  bytes = readIndefiniteLengthFully();
945
946                         return new BERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
947                     }
948
949                     //
950                     // either constructed or explicitly tagged
951                     //
952                                         DERObject               dObj = readObject();
953
954                                         if (dObj == END_OF_STREAM)     // empty tag!
955                     {
956                         return new DERTaggedObject(tag & 0x1f);
957                     }
958
959                     DERObject       next = readObject();
960
961                     //
962                     // explicitly tagged (probably!) - if it isn't we'd have to
963                     // tell from the context
964                     //
965                     if (next == END_OF_STREAM)
966                     {
967                         return new BERTaggedObject(tag & 0x1f, dObj);
968                     }
969
970                     //
971                     // another implicit object, we'll create a sequence...
972                     //
973                     seq = new BERConstructedSequence();
974
975                     seq.addObject(dObj);
976
977                     do
978                     {
979                         seq.addObject(next);
980                         next = readObject();
981                     }
982                     while (next != END_OF_STREAM);
983
984                     return new BERTaggedObject(false, tag & 0x1f, seq);
985                 }
986
987                 throw new IOException("unknown BER object encountered");
988             }
989         }
990         else
991         {
992             if (tag == 0 && length == 0)    // end of contents marker.
993             {
994                 return END_OF_STREAM;
995             }
996
997             byte[]  bytes = new byte[length];
998     
999             readFully(bytes);
1000     
1001                         return buildObject(tag, bytes);
1002         }
1003     }
1004 }
1005
1006
1007 class BEROutputStream
1008     extends DEROutputStream
1009 {
1010     public BEROutputStream(
1011         OutputStream    os)
1012     {
1013         super(os);
1014     }
1015
1016     public void writeObject(
1017         Object    obj)
1018         throws IOException
1019     {
1020         if (obj == null)
1021         {
1022             writeNull();
1023         }
1024         else if (obj instanceof DERObject)
1025         {
1026             ((DERObject)obj).encode(this);
1027         }
1028         else if (obj instanceof DEREncodable)
1029         {
1030             ((DEREncodable)obj).getDERObject().encode(this);
1031         }
1032         else
1033         {
1034             throw new IOException("object not BEREncodable");
1035         }
1036     }
1037 }
1038
1039
1040 class BERSet
1041     extends DERSet
1042 {
1043     /**
1044      * create an empty sequence
1045      */
1046     public BERSet()
1047     {
1048     }
1049
1050     /**
1051      * create a set containing one object
1052      */
1053     public BERSet(
1054         DEREncodable    obj)
1055     {
1056         super(obj);
1057     }
1058
1059     /**
1060      * create a set containing a vector of objects.
1061      */
1062     public BERSet(
1063         DEREncodableVector   v)
1064     {
1065         super(v);
1066     }
1067
1068     /*
1069      */
1070     void encode(
1071         DEROutputStream out)
1072         throws IOException
1073     {
1074         if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
1075         {
1076             out.write(SET | CONSTRUCTED);
1077             out.write(0x80);
1078             
1079             Enumeration e = getObjects();
1080             while (e.hasMoreElements())
1081             {
1082                 out.writeObject(e.nextElement());
1083             }
1084         
1085             out.write(0x00);
1086             out.write(0x00);
1087         }
1088         else
1089         {
1090             super.encode(out);
1091         }
1092     }
1093 }
1094
1095
1096 /**
1097  * BER TaggedObject - in ASN.1 nottation this is any object proceeded by
1098  * a [n] where n is some number - these are assume to follow the construction
1099  * rules (as with sequences).
1100  */
1101 class BERTaggedObject
1102     extends DERTaggedObject
1103 {
1104     /**
1105      * @param tagNo the tag number for this object.
1106      * @param obj the tagged object.
1107      */
1108     public BERTaggedObject(
1109         int             tagNo,
1110         DEREncodable    obj)
1111     {
1112                 super(tagNo, obj);
1113     }
1114
1115     /**
1116      * @param explicit true if an explicitly tagged object.
1117      * @param tagNo the tag number for this object.
1118      * @param obj the tagged object.
1119      */
1120     public BERTaggedObject(
1121         boolean         explicit,
1122         int             tagNo,
1123         DEREncodable    obj)
1124     {
1125                 super(explicit, tagNo, obj);
1126     }
1127
1128     /**
1129      * create an implicitly tagged object that contains a zero
1130      * length sequence.
1131      */
1132     public BERTaggedObject(
1133         int             tagNo)
1134     {
1135         super(false, tagNo, new BERConstructedSequence());
1136     }
1137
1138     void encode(
1139         DEROutputStream  out)
1140         throws IOException
1141     {
1142         if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
1143         {
1144             out.write(CONSTRUCTED | TAGGED | tagNo);
1145             out.write(0x80);
1146
1147             if (!empty)
1148             {
1149                 if (!explicit)
1150                 {
1151                     if (obj instanceof BERConstructedOctetString)
1152                     {
1153                         Enumeration  e = ((BERConstructedOctetString)obj).getObjects();
1154
1155                         while (e.hasMoreElements())
1156                         {
1157                             out.writeObject(e.nextElement());
1158                         }
1159                     }
1160                     else if (obj instanceof ASN1Sequence)
1161                     {
1162                         Enumeration  e = ((ASN1Sequence)obj).getObjects();
1163
1164                         while (e.hasMoreElements())
1165                         {
1166                             out.writeObject(e.nextElement());
1167                         }
1168                     }
1169                     else if (obj instanceof ASN1Set)
1170                     {
1171                         Enumeration  e = ((ASN1Set)obj).getObjects();
1172
1173                         while (e.hasMoreElements())
1174                         {
1175                             out.writeObject(e.nextElement());
1176                         }
1177                     }
1178                     else
1179                     {
1180                         throw new RuntimeException("not implemented: " + obj.getClass().getName());
1181                     }
1182                 }
1183                 else
1184                 {
1185                     out.writeObject(obj);
1186                 }
1187             }
1188
1189             out.write(0x00);
1190             out.write(0x00);
1191         }
1192         else
1193         {
1194             super.encode(out);
1195         }
1196     }
1197 }
1198
1199
1200 class Attribute
1201     implements DEREncodable
1202 {
1203         private DERObjectIdentifier attrType;
1204         private ASN1Set             attrValues;
1205
1206     /**
1207      * return an Attribute object from the given object.
1208      *
1209      * @param o the object we want converted.
1210      * @exception IllegalArgumentException if the object cannot be converted.
1211      */
1212         public static Attribute getInstance(
1213         Object o)
1214     {
1215                 if (o == null || o instanceof Attribute)
1216         {
1217                         return (Attribute)o;
1218                 }
1219                 
1220                 if (o instanceof ASN1Sequence)
1221         {
1222                         return new Attribute((ASN1Sequence)o);
1223                 }
1224
1225         throw new IllegalArgumentException("unknown object in factory");
1226         }
1227         
1228         public Attribute(
1229         ASN1Sequence seq)
1230     {
1231                 attrType = (DERObjectIdentifier)seq.getObjectAt(0);
1232                 attrValues = (ASN1Set)seq.getObjectAt(1);
1233         }
1234
1235         public Attribute(
1236             DERObjectIdentifier attrType,
1237             ASN1Set             attrValues)
1238     {
1239                 this.attrType = attrType;
1240                 this.attrValues = attrValues;
1241         }
1242
1243         public DERObjectIdentifier getAttrType()
1244     {
1245                 return attrType;
1246         }
1247         
1248         public ASN1Set getAttrValues()
1249     {
1250                 return attrValues;
1251         }
1252
1253     /** 
1254      * <pre>
1255      * Attribute ::= SEQUENCE {
1256      *  attrType OBJECT IDENTIFIER,
1257      *  attrValues SET OF AttributeValue
1258      * }
1259      * </pre>
1260      */
1261         public DERObject getDERObject()
1262     {
1263                 DEREncodableVector v = new DEREncodableVector();
1264
1265                 v.add(attrType);
1266                 v.add(attrValues);
1267
1268                 return new DERSequence(v);
1269         }
1270 }
1271 // Decompiled by Jad v1.5.7f. Copyright 2000 Pavel Kouznetsov.
1272 // Jad home page: http://www.geocities.com/SiliconValley/Bridge/8617/jad.html
1273 // Decompiler options: packimports(3) 
1274 // Source File Name:   SignedAttributes.java
1275
1276
1277
1278 // Referenced classes of package org.bouncycastle.asn1.cms:
1279 //            Attribute
1280
1281 class SignedAttributes
1282     implements DEREncodable
1283 {
1284
1285     public SignedAttributes(Vector vector)
1286     {
1287         setAttributes(vector);
1288     }
1289
1290     public SignedAttributes(DERConstructedSet derconstructedset)
1291     {
1292         attributes = derconstructedset;
1293     }
1294
1295     public SignedAttributes(SignedAttributes signedattributes)
1296     {
1297         attributes = signedattributes.attributes;
1298     }
1299
1300     public static SignedAttributes getInstance(Object obj)
1301     {
1302         if(obj == null)
1303             return null;
1304         if(obj instanceof SignedAttributes)
1305             return (SignedAttributes)obj;
1306         if(obj instanceof DERConstructedSet)
1307             return new SignedAttributes((DERConstructedSet)obj);
1308         if(obj instanceof DERTaggedObject)
1309             return getInstance(((DERTaggedObject)obj).getObject());
1310         else
1311             throw new IllegalArgumentException("Invalid SignedAttributes");
1312     }
1313
1314     public static SignedAttributes newInstance(Object obj)
1315     {
1316         if(obj == null)
1317             return null;
1318         if(obj instanceof SignedAttributes)
1319             return new SignedAttributes((SignedAttributes)obj);
1320         if(obj instanceof DERConstructedSet)
1321             return new SignedAttributes((DERConstructedSet)obj);
1322         if(obj instanceof DERTaggedObject)
1323             return getInstance(((DERTaggedObject)obj).getObject());
1324         else
1325             throw new IllegalArgumentException("Invalid SignedAttributes");
1326     }
1327
1328     public Vector getAttributes()
1329     {
1330         int i = attributes.getSize();
1331         Vector vector = new Vector();
1332         for(int j = 0; j < i; j++)
1333             vector.addElement(Attribute.getInstance(attributes.getObjectAt(j)));
1334
1335         return vector;
1336     }
1337
1338     private void setAttributes(Vector vector)
1339     {
1340         int i = vector.size();
1341         attributes = new DERConstructedSet();
1342         for(int j = 0; j < i; j++)
1343             attributes.addObject(Attribute.getInstance(vector.elementAt(j)));
1344
1345     }
1346
1347     public DERObject getDERObject()
1348     {
1349         return attributes;
1350     }
1351
1352     private DERConstructedSet attributes;
1353 }
1354
1355
1356 class DERBitString
1357     extends DERObject
1358 {
1359     protected byte[]      data;
1360     protected int         padBits;
1361
1362     /**
1363      * return the correct number of pad bits for a bit string defined in
1364      * a 16 bit constant
1365      */
1366     static protected int getPadBits(
1367         int bitString)
1368     {
1369         int val;
1370
1371         if (bitString == 0)
1372         {
1373             return 7;
1374         }
1375
1376         if (bitString > 255)
1377         {
1378             val = ((bitString >> 8) & 0xFF);
1379         }
1380         else
1381         {
1382             val = (bitString & 0xFF);
1383         }
1384
1385         int bits = 1;
1386
1387         while (((val <<= 1) & 0xFF) != 0)
1388         {
1389             bits++;
1390         }
1391
1392         return 8 - bits;
1393     }
1394
1395     /**
1396      * return the correct number of bytes for a bit string defined in
1397      * a 16 bit constant
1398      */
1399     static protected byte[] getBytes(
1400         int bitString)
1401     {
1402         if (bitString > 255)
1403         {
1404             byte[]  bytes = new byte[2];
1405
1406             bytes[0] = (byte)(bitString & 0xFF);
1407             bytes[1] = (byte)((bitString >> 8) & 0xFF);
1408
1409             return bytes;
1410         }
1411         else
1412         {
1413             byte[]  bytes = new byte[1];
1414
1415             bytes[0] = (byte)(bitString & 0xFF);
1416
1417             return bytes;
1418         }
1419     }
1420
1421     /**
1422      * return a Bit String from the passed in object
1423      *
1424      * @exception IllegalArgumentException if the object cannot be converted.
1425      */
1426     public static DERBitString getInstance(
1427         Object  obj)
1428     {
1429         if (obj == null || obj instanceof DERBitString)
1430         {
1431             return (DERBitString)obj;
1432         }
1433
1434         if (obj instanceof ASN1OctetString)
1435         {
1436             byte[]  bytes = ((ASN1OctetString)obj).getOctets();
1437             int     padBits = bytes[0];
1438             byte[]  data = new byte[bytes.length - 1];
1439
1440             System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
1441
1442             return new DERBitString(data, padBits);
1443         }
1444
1445         if (obj instanceof ASN1TaggedObject)
1446         {
1447             return getInstance(((ASN1TaggedObject)obj).getObject());
1448         }
1449
1450         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
1451     }
1452
1453     /**
1454      * return a Bit String from a tagged object.
1455      *
1456      * @param obj the tagged object holding the object we want
1457      * @param explicit true if the object is meant to be explicitly
1458      *              tagged false otherwise.
1459      * @exception IllegalArgumentException if the tagged object cannot
1460      *               be converted.
1461      */
1462     public static DERBitString getInstance(
1463         ASN1TaggedObject obj,
1464         boolean          explicit)
1465     {
1466         return getInstance(obj.getObject());
1467     }
1468     
1469     protected DERBitString(
1470         byte    data,
1471         int     padBits)
1472     {
1473         this.data = new byte[1];
1474         this.data[0] = data;
1475         this.padBits = padBits;
1476     }
1477
1478     /**
1479      * @param data the octets making up the bit string.
1480      * @param padBits the number of extra bits at the end of the string.
1481      */
1482     public DERBitString(
1483         byte[]  data,
1484         int     padBits)
1485     {
1486         this.data = data;
1487         this.padBits = padBits;
1488     }
1489
1490     public DERBitString(
1491         byte[]  data)
1492     {
1493         this(data, 0);
1494     }
1495
1496     public DERBitString(
1497         DEREncodable  obj)
1498     {
1499         try
1500         {
1501             ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
1502             DEROutputStream         dOut = new DEROutputStream(bOut);
1503
1504             dOut.writeObject(obj);
1505             dOut.close();
1506
1507             this.data = bOut.toByteArray();
1508             this.padBits = 0;
1509         }
1510         catch (IOException e)
1511         {
1512             throw new IllegalArgumentException("Error processing object : " + e.toString());
1513         }
1514     }
1515
1516     public byte[] getBytes()
1517     {
1518         return data;
1519     }
1520
1521     public int getPadBits()
1522     {
1523         return padBits;
1524     }
1525
1526     void encode(
1527         DEROutputStream  out)
1528         throws IOException
1529     {
1530         byte[]  bytes = new byte[getBytes().length + 1];
1531
1532         bytes[0] = (byte)getPadBits();
1533         System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1);
1534
1535         out.writeEncoded(BIT_STRING, bytes);
1536     }
1537     
1538     public boolean equals(
1539         Object  o)
1540     {
1541         if (o == null || !(o instanceof DERBitString))
1542         {
1543             return false;
1544         }
1545
1546         DERBitString  other = (DERBitString)o;
1547
1548         if (data.length != other.data.length)
1549         {
1550             return false;
1551         }
1552
1553         for (int i = 0; i != data.length; i++)
1554         {
1555             if (data[i] != other.data[i])
1556             {
1557                 return false;
1558             }
1559         }
1560
1561         return (padBits == other.padBits);
1562     }
1563 }
1564
1565
1566 /**
1567  * DER BMPString object.
1568  */
1569 class DERBMPString
1570     extends DERObject
1571     implements DERString
1572 {
1573     String  string;
1574
1575     /**
1576      * return a BMP String from the given object.
1577      *
1578      * @param obj the object we want converted.
1579      * @exception IllegalArgumentException if the object cannot be converted.
1580      */
1581     public static DERBMPString getInstance(
1582         Object  obj)
1583     {
1584         if (obj == null || obj instanceof DERBMPString)
1585         {
1586             return (DERBMPString)obj;
1587         }
1588
1589         if (obj instanceof ASN1OctetString)
1590         {
1591             return new DERBMPString(((ASN1OctetString)obj).getOctets());
1592         }
1593
1594         if (obj instanceof ASN1TaggedObject)
1595         {
1596             return getInstance(((ASN1TaggedObject)obj).getObject());
1597         }
1598
1599         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
1600     }
1601
1602     /**
1603      * return a BMP String from a tagged object.
1604      *
1605      * @param obj the tagged object holding the object we want
1606      * @param explicit true if the object is meant to be explicitly
1607      *              tagged false otherwise.
1608      * @exception IllegalArgumentException if the tagged object cannot
1609      *              be converted.
1610      */
1611     public static DERBMPString getInstance(
1612         ASN1TaggedObject obj,
1613         boolean          explicit)
1614     {
1615         return getInstance(obj.getObject());
1616     }
1617     
1618
1619     /**
1620      * basic constructor - byte encoded string.
1621      */
1622     public DERBMPString(
1623         byte[]   string)
1624     {
1625         char[]  cs = new char[string.length / 2];
1626
1627         for (int i = 0; i != cs.length; i++)
1628         {
1629             cs[i] = (char)((string[2 * i] << 8) | (string[2 * i + 1] & 0xff));
1630         }
1631
1632         this.string = new String(cs);
1633     }
1634
1635     /**
1636      * basic constructor
1637      */
1638     public DERBMPString(
1639         String   string)
1640     {
1641         this.string = string;
1642     }
1643
1644     public String getString()
1645     {
1646         return string;
1647     }
1648
1649     public int hashCode()
1650     {
1651         return this.getString().hashCode();
1652     }
1653
1654     public boolean equals(
1655         Object  o)
1656     {
1657         if (!(o instanceof DERBMPString))
1658         {
1659             return false;
1660         }
1661
1662         DERPrintableString  s = (DERPrintableString)o;
1663
1664         return this.getString().equals(s.getString());
1665     }
1666
1667     void encode(
1668         DEROutputStream  out)
1669         throws IOException
1670     {
1671         char[]  c = string.toCharArray();
1672         byte[]  b = new byte[c.length * 2];
1673
1674         for (int i = 0; i != c.length; i++)
1675         {
1676             b[2 * i] = (byte)(c[i] >> 8);
1677             b[2 * i + 1] = (byte)c[i];
1678         }
1679
1680         out.writeEncoded(BMP_STRING, b);
1681     }
1682 }
1683
1684
1685 class DERBoolean
1686     extends DERObject
1687 {
1688     byte         value;
1689
1690         public static final DERBoolean FALSE = new DERBoolean(false);
1691         public static final DERBoolean TRUE  = new DERBoolean(true);
1692
1693     /**
1694      * return a boolean from the passed in object.
1695      *
1696      * @exception IllegalArgumentException if the object cannot be converted.
1697      */
1698     public static DERBoolean getInstance(
1699         Object  obj)
1700     {
1701         if (obj == null || obj instanceof DERBoolean)
1702         {
1703             return (DERBoolean)obj;
1704         }
1705
1706         if (obj instanceof ASN1OctetString)
1707         {
1708             return new DERBoolean(((ASN1OctetString)obj).getOctets());
1709         }
1710
1711         if (obj instanceof ASN1TaggedObject)
1712         {
1713             return getInstance(((ASN1TaggedObject)obj).getObject());
1714         }
1715
1716         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
1717     }
1718
1719     /**
1720      * return a DERBoolean from the passed in boolean.
1721      */
1722     public static DERBoolean getInstance(
1723         boolean  value)
1724     {
1725         return (value ? TRUE : FALSE);
1726     }
1727
1728     /**
1729      * return a Boolean from a tagged object.
1730      *
1731      * @param obj the tagged object holding the object we want
1732      * @param explicit true if the object is meant to be explicitly
1733      *              tagged false otherwise.
1734      * @exception IllegalArgumentException if the tagged object cannot
1735      *               be converted.
1736      */
1737     public static DERBoolean getInstance(
1738         ASN1TaggedObject obj,
1739         boolean          explicit)
1740     {
1741         return getInstance(obj.getObject());
1742     }
1743     
1744     public DERBoolean(
1745         byte[]       value)
1746     {
1747         this.value = value[0];
1748     }
1749
1750     public DERBoolean(
1751         boolean     value)
1752     {
1753         this.value = (value) ? (byte)0xff : (byte)0;
1754     }
1755
1756     public boolean isTrue()
1757     {
1758         return (value != 0);
1759     }
1760
1761     void encode(
1762         DEROutputStream out)
1763         throws IOException
1764     {
1765         byte[]  bytes = new byte[1];
1766
1767         bytes[0] = value;
1768
1769         out.writeEncoded(BOOLEAN, bytes);
1770     }
1771     
1772     public boolean equals(
1773         Object  o)
1774     {
1775         if ((o == null) || !(o instanceof DERBoolean))
1776         {
1777             return false;
1778         }
1779
1780         return (value == ((DERBoolean)o).value);
1781     }
1782
1783 }
1784
1785
1786 class DERConstructedSequence
1787     extends ASN1Sequence
1788 {
1789     public void addObject(
1790         DEREncodable obj)
1791     {
1792         super.addObject(obj);
1793     }
1794
1795     public int getSize()
1796     {
1797         return size();
1798     }
1799
1800     /*
1801      * A note on the implementation:
1802      * <p>
1803      * As DER requires the constructed, definite-length model to
1804      * be used for structured types, this varies slightly from the
1805      * ASN.1 descriptions given. Rather than just outputing SEQUENCE,
1806      * we also have to specify CONSTRUCTED, and the objects length.
1807      */
1808     void encode(
1809         DEROutputStream out)
1810         throws IOException
1811     {
1812         ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
1813         DEROutputStream         dOut = new DEROutputStream(bOut);
1814         Enumeration             e = this.getObjects();
1815
1816         while (e.hasMoreElements())
1817         {
1818             Object    obj = e.nextElement();
1819
1820             dOut.writeObject(obj);
1821         }
1822
1823         dOut.close();
1824
1825         byte[]  bytes = bOut.toByteArray();
1826
1827         out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
1828     }
1829 }
1830
1831
1832 class DERConstructedSet
1833     extends ASN1Set
1834 {
1835     public DERConstructedSet()
1836     {
1837     }
1838
1839     /**
1840      * @param obj - a single object that makes up the set.
1841      */
1842     public DERConstructedSet(
1843         DEREncodable   obj)
1844     {
1845         this.addObject(obj);
1846     }
1847
1848     /**
1849      * @param v - a vector of objects making up the set.
1850      */
1851     public DERConstructedSet(
1852         DEREncodableVector   v)
1853     {
1854         for (int i = 0; i != v.size(); i++)
1855         {
1856             this.addObject(v.get(i));
1857         }
1858     }
1859
1860     public void addObject(
1861         DEREncodable    obj)
1862     {
1863         super.addObject(obj);
1864     }
1865
1866     public int getSize()
1867     {
1868         return size();
1869     }
1870
1871     /*
1872      * A note on the implementation:
1873      * <p>
1874      * As DER requires the constructed, definite-length model to
1875      * be used for structured types, this varies slightly from the
1876      * ASN.1 descriptions given. Rather than just outputing SET,
1877      * we also have to specify CONSTRUCTED, and the objects length.
1878      */
1879     void encode(
1880         DEROutputStream out)
1881         throws IOException
1882     {
1883         ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
1884         DEROutputStream         dOut = new DEROutputStream(bOut);
1885         Enumeration             e = this.getObjects();
1886
1887         while (e.hasMoreElements())
1888         {
1889             Object    obj = e.nextElement();
1890
1891             dOut.writeObject(obj);
1892         }
1893
1894         dOut.close();
1895
1896         byte[]  bytes = bOut.toByteArray();
1897
1898         out.writeEncoded(SET | CONSTRUCTED, bytes);
1899     }
1900 }
1901
1902 interface DEREncodable
1903 {
1904     public DERObject getDERObject();
1905 }
1906
1907
1908 /**
1909  * a general class for building up a vector of DER encodable objects
1910  */
1911 class DEREncodableVector
1912 {
1913     private Vector  v = new Vector();
1914
1915     public void add(
1916         DEREncodable   obj)
1917     {
1918         v.addElement(obj);
1919     }
1920
1921     public DEREncodable get(
1922         int i)
1923     {
1924         return (DEREncodable)v.elementAt(i);
1925     }
1926
1927     public int size()
1928     {
1929         return v.size();
1930     }
1931 }
1932
1933
1934 class DEREnumerated
1935     extends DERObject
1936 {
1937     byte[]      bytes;
1938
1939     /**
1940      * return an integer from the passed in object
1941      *
1942      * @exception IllegalArgumentException if the object cannot be converted.
1943      */
1944     public static DEREnumerated getInstance(
1945         Object  obj)
1946     {
1947         if (obj == null || obj instanceof DEREnumerated)
1948         {
1949             return (DEREnumerated)obj;
1950         }
1951
1952         if (obj instanceof ASN1OctetString)
1953         {
1954             return new DEREnumerated(((ASN1OctetString)obj).getOctets());
1955         }
1956
1957         if (obj instanceof ASN1TaggedObject)
1958         {
1959             return getInstance(((ASN1TaggedObject)obj).getObject());
1960         }
1961
1962         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
1963     }
1964
1965     /**
1966      * return an Enumerated from a tagged object.
1967      *
1968      * @param obj the tagged object holding the object we want
1969      * @param explicit true if the object is meant to be explicitly
1970      *              tagged false otherwise.
1971      * @exception IllegalArgumentException if the tagged object cannot
1972      *               be converted.
1973      */
1974     public static DEREnumerated getInstance(
1975         ASN1TaggedObject obj,
1976         boolean          explicit)
1977     {
1978         return getInstance(obj.getObject());
1979     }
1980
1981     public DEREnumerated(
1982         int         value)
1983     {
1984         bytes = BigInteger.valueOf(value).toByteArray();
1985     }
1986
1987     public DEREnumerated(
1988         BigInteger   value)
1989     {
1990         bytes = value.toByteArray();
1991     }
1992
1993     public DEREnumerated(
1994         byte[]   bytes)
1995     {
1996         this.bytes = bytes;
1997     }
1998
1999     public BigInteger getValue()
2000     {
2001         return new BigInteger(bytes);
2002     }
2003
2004     void encode(
2005         DEROutputStream out)
2006         throws IOException
2007     {
2008         out.writeEncoded(ENUMERATED, bytes);
2009     }
2010     
2011     public boolean equals(
2012         Object  o)
2013     {
2014         if (o == null || !(o instanceof DEREnumerated))
2015         {
2016             return false;
2017         }
2018
2019         DEREnumerated other = (DEREnumerated)o;
2020
2021         if (bytes.length != other.bytes.length)
2022         {
2023             return false;
2024         }
2025
2026         for (int i = 0; i != bytes.length; i++)
2027         {
2028             if (bytes[i] != other.bytes[i])
2029             {
2030                 return false;
2031             }
2032         }
2033
2034         return true;
2035     }
2036 }
2037
2038
2039 /**
2040  * Generalized time object.
2041  */
2042 class DERGeneralizedTime
2043     extends DERObject
2044 {
2045     String      time;
2046
2047     /**
2048      * return a generalized time from the passed in object
2049      *
2050      * @exception IllegalArgumentException if the object cannot be converted.
2051      */
2052     public static DERGeneralizedTime getInstance(
2053         Object  obj)
2054     {
2055         if (obj == null || obj instanceof DERGeneralizedTime)
2056         {
2057             return (DERGeneralizedTime)obj;
2058         }
2059
2060         if (obj instanceof ASN1OctetString)
2061         {
2062             return new DERGeneralizedTime(((ASN1OctetString)obj).getOctets());
2063         }
2064
2065         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
2066     }
2067
2068     /**
2069      * return a Generalized Time object from a tagged object.
2070      *
2071      * @param obj the tagged object holding the object we want
2072      * @param explicit true if the object is meant to be explicitly
2073      *              tagged false otherwise.
2074      * @exception IllegalArgumentException if the tagged object cannot
2075      *               be converted.
2076      */
2077     public static DERGeneralizedTime getInstance(
2078         ASN1TaggedObject obj,
2079         boolean          explicit)
2080     {
2081         return getInstance(obj.getObject());
2082     }
2083     
2084     /**
2085      * The correct format for this is YYYYMMDDHHMMSSZ, or without the Z
2086      * for local time, or Z+-HHMM on the end, for difference between local
2087      * time and UTC time.
2088      * <p>
2089      *
2090      * @param time the time string.
2091      */
2092     public DERGeneralizedTime(
2093         String  time)
2094     {
2095         this.time = time;
2096     }
2097
2098     /**
2099      * base constructer from a java.util.date object
2100      */
2101     public DERGeneralizedTime(
2102         Date time)
2103     {
2104         SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
2105
2106         dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
2107
2108         this.time = dateF.format(time);
2109     }
2110
2111     DERGeneralizedTime(
2112         byte[]  bytes)
2113     {
2114         //
2115         // explicitly convert to characters
2116         //
2117         char[]  dateC = new char[bytes.length];
2118
2119         for (int i = 0; i != dateC.length; i++)
2120         {
2121             dateC[i] = (char)(bytes[i] & 0xff);
2122         }
2123
2124         this.time = new String(dateC);
2125     }
2126
2127     /**
2128      * return the time - always in the form of 
2129      *  YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
2130      * <p>
2131      * Normally in a certificate we would expect "Z" rather than "GMT",
2132      * however adding the "GMT" means we can just use:
2133      * <pre>
2134      *     dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
2135      * </pre>
2136      * To read in the time and get a date which is compatible with our local
2137      * time zone.
2138      */
2139     public String getTime()
2140     {
2141         //
2142         // standardise the format.
2143         //
2144         if (time.length() == 15)
2145         {
2146             return time.substring(0, 14) + "GMT+00:00";
2147         }
2148         else if (time.length() == 17)
2149         {
2150             return time.substring(0, 14) + "GMT" + time.substring(15, 17) + ":" + time.substring(17, 19);
2151         }
2152
2153         return time;
2154     }
2155
2156     private byte[] getOctets()
2157     {
2158         char[]  cs = time.toCharArray();
2159         byte[]  bs = new byte[cs.length];
2160
2161         for (int i = 0; i != cs.length; i++)
2162         {
2163             bs[i] = (byte)cs[i];
2164         }
2165
2166         return bs;
2167     }
2168
2169
2170     void encode(
2171         DEROutputStream  out)
2172         throws IOException
2173     {
2174         out.writeEncoded(GENERALIZED_TIME, this.getOctets());
2175     }
2176     
2177     public boolean equals(
2178         Object  o)
2179     {
2180         if ((o == null) || !(o instanceof DERGeneralizedTime))
2181         {
2182             return false;
2183         }
2184
2185         return time.equals(((DERGeneralizedTime)o).time);
2186     }
2187 }
2188
2189
2190 /**
2191  * DER IA5String object - this is an ascii string.
2192  */
2193 class DERIA5String
2194     extends DERObject
2195     implements DERString
2196 {
2197     String  string;
2198
2199     /**
2200      * return a IA5 string from the passed in object
2201      *
2202      * @exception IllegalArgumentException if the object cannot be converted.
2203      */
2204     public static DERIA5String getInstance(
2205         Object  obj)
2206     {
2207         if (obj == null || obj instanceof DERIA5String)
2208         {
2209             return (DERIA5String)obj;
2210         }
2211
2212         if (obj instanceof ASN1OctetString)
2213         {
2214             return new DERIA5String(((ASN1OctetString)obj).getOctets());
2215         }
2216
2217         if (obj instanceof ASN1TaggedObject)
2218         {
2219             return getInstance(((ASN1TaggedObject)obj).getObject());
2220         }
2221
2222         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
2223     }
2224
2225     /**
2226      * return an IA5 String from a tagged object.
2227      *
2228      * @param obj the tagged object holding the object we want
2229      * @param explicit true if the object is meant to be explicitly
2230      *              tagged false otherwise.
2231      * @exception IllegalArgumentException if the tagged object cannot
2232      *               be converted.
2233      */
2234     public static DERIA5String getInstance(
2235         ASN1TaggedObject obj,
2236         boolean          explicit)
2237     {
2238         return getInstance(obj.getObject());
2239     }
2240
2241     /**
2242      * basic constructor - with bytes.
2243      */
2244     public DERIA5String(
2245         byte[]   string)
2246     {
2247         char[]  cs = new char[string.length];
2248
2249         for (int i = 0; i != cs.length; i++)
2250         {
2251             cs[i] = (char)(string[i] & 0xff);
2252         }
2253
2254         this.string = new String(cs);
2255     }
2256
2257     /**
2258      * basic constructor - with string.
2259      */
2260     public DERIA5String(
2261         String   string)
2262     {
2263         this.string = string;
2264     }
2265
2266     public String getString()
2267     {
2268         return string;
2269     }
2270
2271     public byte[] getOctets()
2272     {
2273         char[]  cs = string.toCharArray();
2274         byte[]  bs = new byte[cs.length];
2275
2276         for (int i = 0; i != cs.length; i++)
2277         {
2278             bs[i] = (byte)cs[i];
2279         }
2280
2281         return bs; 
2282     }
2283
2284     void encode(
2285         DEROutputStream  out)
2286         throws IOException
2287     {
2288         out.writeEncoded(IA5_STRING, this.getOctets());
2289     }
2290
2291     public int hashCode()
2292     {
2293         return this.getString().hashCode();
2294     }
2295
2296     public boolean equals(
2297         Object  o)
2298     {
2299         if (!(o instanceof DERIA5String))
2300         {
2301             return false;
2302         }
2303
2304         DERIA5String  s = (DERIA5String)o;
2305
2306         return this.getString().equals(s.getString());
2307     }
2308 }
2309
2310
2311
2312
2313 class DERInputStream
2314     extends FilterInputStream implements DERTags
2315 {
2316     public DERInputStream(
2317         InputStream is)
2318     {
2319         super(is);
2320     }
2321
2322     protected int readLength()
2323         throws IOException
2324     {
2325         int length = read();
2326         if (length < 0)
2327         {
2328             throw new IOException("EOF found when length expected");
2329         }
2330
2331         if (length == 0x80)
2332         {
2333             return -1;      // indefinite-length encoding
2334         }
2335
2336         if (length > 127)
2337         {
2338             int size = length & 0x7f;
2339
2340             length = 0;
2341             for (int i = 0; i < size; i++)
2342             {
2343                 int next = read();
2344
2345                 if (next < 0)
2346                 {
2347                     throw new IOException("EOF found reading length");
2348                 }
2349
2350                 length = (length << 8) + next;
2351             }
2352         }
2353
2354         return length;
2355     }
2356
2357     protected void readFully(
2358         byte[]  bytes)
2359         throws IOException
2360     {
2361         int     left = bytes.length;
2362
2363         if (left == 0)
2364         {
2365             return;
2366         }
2367
2368         while ((left -= read(bytes, bytes.length - left, left)) != 0)
2369         {
2370             ;
2371         }
2372     }
2373
2374         /**
2375          * build an object given its tag and a byte stream to construct it
2376          * from.
2377          */
2378     protected DERObject buildObject(
2379                 int         tag,
2380                 byte[]  bytes)
2381                 throws IOException
2382         {
2383                 switch (tag)
2384         {
2385         case NULL:
2386             return null;   
2387         case SEQUENCE | CONSTRUCTED:
2388             ByteArrayInputStream    bIn = new ByteArrayInputStream(bytes);
2389             BERInputStream          dIn = new BERInputStream(bIn);
2390             DERConstructedSequence  seq = new DERConstructedSequence();
2391
2392             try
2393             {
2394                 for (;;)
2395                 {
2396                     DERObject   obj = dIn.readObject();
2397
2398                     seq.addObject(obj);
2399                 }
2400             }
2401             catch (EOFException ex)
2402             {
2403                 return seq;
2404             }
2405         case SET | CONSTRUCTED:
2406             bIn = new ByteArrayInputStream(bytes);
2407             dIn = new BERInputStream(bIn);
2408
2409             DEREncodableVector    v = new DEREncodableVector();
2410
2411             try
2412             {
2413                 for (;;)
2414                 {
2415                     DERObject   obj = dIn.readObject();
2416
2417                     v.add(obj);
2418                 }
2419             }
2420             catch (EOFException ex)
2421             {
2422                 return new DERConstructedSet(v);
2423             }
2424         case BOOLEAN:
2425             return new DERBoolean(bytes);
2426         case INTEGER:
2427             return new DERInteger(bytes);
2428         case ENUMERATED:
2429             return new DEREnumerated(bytes);
2430         case OBJECT_IDENTIFIER:
2431             return new DERObjectIdentifier(bytes);
2432         case BIT_STRING:
2433             int     padBits = bytes[0];
2434             byte[]  data = new byte[bytes.length - 1];
2435
2436             System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
2437
2438             return new DERBitString(data, padBits);
2439         case UTF8_STRING:
2440             return new DERUTF8String(bytes);
2441         case PRINTABLE_STRING:
2442             return new DERPrintableString(bytes);
2443         case IA5_STRING:
2444             return new DERIA5String(bytes);
2445         case T61_STRING:
2446             return new DERT61String(bytes);
2447         case VISIBLE_STRING:
2448             return new DERVisibleString(bytes);
2449         case UNIVERSAL_STRING:
2450             return new DERUniversalString(bytes);
2451         case BMP_STRING:
2452             return new DERBMPString(bytes);
2453         case OCTET_STRING:
2454             return new DEROctetString(bytes);
2455         case UTC_TIME:
2456             return new DERUTCTime(bytes);
2457         case GENERALIZED_TIME:
2458             return new DERGeneralizedTime(bytes);
2459         default:
2460             //
2461             // with tagged object tag number is bottom 5 bits
2462             //
2463             if ((tag & TAGGED) != 0)  
2464             {
2465                 if ((tag & 0x1f) == 0x1f)
2466                 {
2467                     throw new IOException("unsupported high tag encountered");
2468                 }
2469
2470                 if (bytes.length == 0)        // empty tag!
2471                 {
2472                     return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence());
2473                 }
2474
2475                 //
2476                 // simple type - implicit... return an octet string
2477                 //
2478                 if ((tag & CONSTRUCTED) == 0)
2479                 {
2480                     return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
2481                 }
2482
2483                 bIn = new ByteArrayInputStream(bytes);
2484                 dIn = new BERInputStream(bIn);
2485
2486                 DEREncodable dObj = dIn.readObject();
2487
2488                 //
2489                 // explicitly tagged (probably!) - if it isn't we'd have to
2490                 // tell from the context
2491                 //
2492                 if (dIn.available() == 0)
2493                 {
2494                     return new DERTaggedObject(tag & 0x1f, dObj);
2495                 }
2496
2497                 //
2498                 // another implicit object, we'll create a sequence...
2499                 //
2500                 seq = new DERConstructedSequence();
2501
2502                 seq.addObject(dObj);
2503
2504                 try
2505                 {
2506                     for (;;)
2507                     {
2508                         dObj = dIn.readObject();
2509
2510                         seq.addObject(dObj);
2511                     }
2512                 }
2513                 catch (EOFException ex)
2514                 {
2515                     // ignore --
2516                 }
2517
2518                 return new DERTaggedObject(false, tag & 0x1f, seq);
2519             }
2520
2521             return new DERUnknownTag(tag, bytes);
2522         }
2523         }
2524
2525     public DERObject readObject()
2526         throws IOException
2527     {
2528         int tag = read();
2529         if (tag == -1)
2530         {
2531             throw new EOFException();
2532         }
2533
2534         int     length = readLength();
2535         byte[]  bytes = new byte[length];
2536
2537         readFully(bytes);
2538
2539                 return buildObject(tag, bytes);
2540         }
2541 }
2542
2543
2544 class DERInteger
2545     extends DERObject
2546 {
2547     byte[]      bytes;
2548
2549     /**
2550      * return an integer from the passed in object
2551      *
2552      * @exception IllegalArgumentException if the object cannot be converted.
2553      */
2554     public static DERInteger getInstance(
2555         Object  obj)
2556     {
2557         if (obj == null || obj instanceof DERInteger)
2558         {
2559             return (DERInteger)obj;
2560         }
2561
2562         if (obj instanceof ASN1OctetString)
2563         {
2564             return new DERInteger(((ASN1OctetString)obj).getOctets());
2565         }
2566
2567         if (obj instanceof ASN1TaggedObject)
2568         {
2569             return getInstance(((ASN1TaggedObject)obj).getObject());
2570         }
2571
2572         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
2573     }
2574
2575     /**
2576      * return an Integer from a tagged object.
2577      *
2578      * @param obj the tagged object holding the object we want
2579      * @param explicit true if the object is meant to be explicitly
2580      *              tagged false otherwise.
2581      * @exception IllegalArgumentException if the tagged object cannot
2582      *               be converted.
2583      */
2584     public static DERInteger getInstance(
2585         ASN1TaggedObject obj,
2586         boolean          explicit)
2587     {
2588         return getInstance(obj.getObject());
2589     }
2590
2591     public DERInteger(
2592         int         value)
2593     {
2594         bytes = BigInteger.valueOf(value).toByteArray();
2595     }
2596
2597     public DERInteger(
2598         BigInteger   value)
2599     {
2600         bytes = value.toByteArray();
2601     }
2602
2603     public DERInteger(
2604         byte[]   bytes)
2605     {
2606         this.bytes = bytes;
2607     }
2608
2609     public BigInteger getValue()
2610     {
2611         return new BigInteger(bytes);
2612     }
2613
2614     /**
2615      * in some cases positive values get crammed into a space,
2616      * that's not quite big enough...
2617      */
2618     public BigInteger getPositiveValue()
2619     {
2620         return new BigInteger(1, bytes);
2621     }
2622
2623     void encode(
2624         DEROutputStream out)
2625         throws IOException
2626     {
2627         out.writeEncoded(INTEGER, bytes);
2628     }
2629     
2630     public boolean equals(
2631         Object  o)
2632     {
2633         if (o == null || !(o instanceof DERInteger))
2634         {
2635             return false;
2636         }
2637
2638         DERInteger other = (DERInteger)o;
2639
2640         if (bytes.length != other.bytes.length)
2641         {
2642             return false;
2643         }
2644
2645         for (int i = 0; i != bytes.length; i++)
2646         {
2647             if (bytes[i] != other.bytes[i])
2648             {
2649                 return false;
2650             }
2651         }
2652
2653         return true;
2654     }
2655 }
2656
2657
2658 abstract class DERObject
2659     implements DERTags, DEREncodable
2660 {
2661     public DERObject getDERObject()
2662     {
2663         return this;
2664     }
2665
2666     abstract void encode(DEROutputStream out)
2667         throws IOException;
2668 }
2669
2670
2671 class DERObjectIdentifier
2672     extends DERObject
2673 {
2674     String      identifier;
2675
2676     /**
2677      * return an OID from the passed in object
2678      *
2679      * @exception IllegalArgumentException if the object cannot be converted.
2680      */
2681     public static DERObjectIdentifier getInstance(
2682         Object  obj)
2683     {
2684         if (obj == null || obj instanceof DERObjectIdentifier)
2685         {
2686             return (DERObjectIdentifier)obj;
2687         }
2688
2689         if (obj instanceof ASN1OctetString)
2690         {
2691             return new DERObjectIdentifier(((ASN1OctetString)obj).getOctets());
2692         }
2693
2694         if (obj instanceof ASN1TaggedObject)
2695         {
2696             return getInstance(((ASN1TaggedObject)obj).getObject());
2697         }
2698
2699         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
2700     }
2701
2702     /**
2703      * return an Object Identifier from a tagged object.
2704      *
2705      * @param obj the tagged object holding the object we want
2706      * @param explicit true if the object is meant to be explicitly
2707      *              tagged false otherwise.
2708      * @exception IllegalArgumentException if the tagged object cannot
2709      *               be converted.
2710      */
2711     public static DERObjectIdentifier getInstance(
2712         ASN1TaggedObject obj,
2713         boolean          explicit)
2714     {
2715         return getInstance(obj.getObject());
2716     }
2717     
2718
2719     DERObjectIdentifier(
2720         byte[]  bytes)
2721     {
2722         int             head = bytes[0] & 0xff;
2723         StringBuffer    objId = new StringBuffer();
2724         int             value = 0;
2725         boolean         first = true;
2726
2727         for (int i = 0; i != bytes.length; i++)
2728         {
2729             int b = bytes[i] & 0xff;
2730
2731             value = value * 128 + (b & 0x7f);
2732             if ((b & 0x80) == 0)             // end of number reached
2733             {
2734                 if (first)
2735                 {
2736                     switch (value / 40)
2737                     {
2738                     case 0:
2739                         objId.append('0');
2740                         break;
2741                     case 1:
2742                         objId.append('1');
2743                         value -= 40;
2744                         break;
2745                     default:
2746                         objId.append('2');
2747                         value -= 80;
2748                     }
2749                     first = false;
2750                 }
2751
2752                 objId.append('.');
2753                 objId.append(Integer.toString(value));
2754                 value = 0;
2755             }
2756         }
2757
2758         this.identifier = objId.toString();
2759     }
2760
2761     public DERObjectIdentifier(
2762         String  identifier)
2763     {
2764         this.identifier = identifier;
2765     }
2766
2767     public String getId()
2768     {
2769         return identifier;
2770     }
2771
2772     private void writeField(
2773         OutputStream    out,
2774         int             fieldValue)
2775         throws IOException
2776     {
2777         if (fieldValue >= (1 << 7))
2778         {
2779             if (fieldValue >= (1 << 14))
2780             {
2781                 if (fieldValue >= (1 << 21))
2782                 {
2783                     if (fieldValue >= (1 << 28))
2784                     {
2785                         out.write((fieldValue >> 28) | 0x80);
2786                     }
2787                     out.write((fieldValue >> 21) | 0x80);
2788                 }
2789                 out.write((fieldValue >> 14) | 0x80);
2790             }
2791             out.write((fieldValue >> 7) | 0x80);
2792         }
2793         out.write(fieldValue & 0x7f);
2794     }
2795
2796     void encode(
2797         DEROutputStream out)
2798         throws IOException
2799     {
2800         OIDTokenizer            tok = new OIDTokenizer(identifier);
2801         ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
2802         DEROutputStream         dOut = new DEROutputStream(bOut);
2803
2804         writeField(bOut, 
2805                     Integer.parseInt(tok.nextToken()) * 40
2806                     + Integer.parseInt(tok.nextToken()));
2807
2808         while (tok.hasMoreTokens())
2809         {
2810             writeField(bOut, Integer.parseInt(tok.nextToken()));
2811         }
2812
2813         dOut.close();
2814
2815         byte[]  bytes = bOut.toByteArray();
2816
2817         out.writeEncoded(OBJECT_IDENTIFIER, bytes);
2818     }
2819
2820     public int hashCode()
2821     {
2822         return identifier.hashCode();
2823     }
2824
2825     public boolean equals(
2826         Object  o)
2827     {
2828         if ((o == null) || !(o instanceof DERObjectIdentifier))
2829         {
2830             return false;
2831         }
2832
2833         return identifier.equals(((DERObjectIdentifier)o).identifier);
2834     }
2835 }
2836
2837
2838 class DEROctetString
2839     extends ASN1OctetString
2840 {
2841     /**
2842      * @param string the octets making up the octet string.
2843      */
2844     public DEROctetString(
2845         byte[]  string)
2846     {
2847         super(string);
2848     }
2849
2850     public DEROctetString(
2851         DEREncodable  obj)
2852     {
2853         super(obj);
2854     }
2855
2856     void encode(
2857         DEROutputStream out)
2858         throws IOException
2859     {
2860         out.writeEncoded(OCTET_STRING, string);
2861     }
2862 }
2863
2864
2865
2866 class DEROutputStream
2867     extends FilterOutputStream implements DERTags
2868 {
2869     public DEROutputStream(
2870         OutputStream    os)
2871     {
2872         super(os);
2873     }
2874
2875     private void writeLength(
2876         int length)
2877         throws IOException
2878     {
2879         if (length > 127)
2880         {
2881             int size = 1;
2882             int val = length;
2883
2884             while ((val >>>= 8) != 0)
2885             {
2886                 size++;
2887             }
2888
2889             write((byte)(size | 0x80));
2890
2891             for (int i = (size - 1) * 8; i >= 0; i -= 8)
2892             {
2893                 write((byte)(length >> i));
2894             }
2895         }
2896         else
2897         {
2898             write((byte)length);
2899         }
2900     }
2901
2902     void writeEncoded(
2903         int     tag,
2904         byte[]  bytes)
2905         throws IOException
2906     {
2907         write(tag);
2908         writeLength(bytes.length);
2909         write(bytes);
2910     }
2911
2912     protected void writeNull()
2913         throws IOException
2914     {
2915         write(NULL);
2916         write(0x00);
2917     }
2918
2919     public void writeObject(
2920         Object    obj)
2921         throws IOException
2922     {
2923         if (obj == null)
2924         {
2925             writeNull();
2926         }
2927         else if (obj instanceof DERObject)
2928         {
2929             ((DERObject)obj).encode(this);
2930         }
2931         else if (obj instanceof DEREncodable)
2932         {
2933             ((DEREncodable)obj).getDERObject().encode(this);
2934         }
2935         else 
2936         {
2937             throw new IOException("object not DEREncodable");
2938         }
2939     }
2940 }
2941
2942
2943 /**
2944  * DER PrintableString object.
2945  */
2946 class DERPrintableString
2947     extends DERObject
2948     implements DERString
2949 {
2950     String  string;
2951
2952     /**
2953      * return a printable string from the passed in object.
2954      * 
2955      * @exception IllegalArgumentException if the object cannot be converted.
2956      */
2957     public static DERPrintableString getInstance(
2958         Object  obj)
2959     {
2960         if (obj == null || obj instanceof DERPrintableString)
2961         {
2962             return (DERPrintableString)obj;
2963         }
2964
2965         if (obj instanceof ASN1OctetString)
2966         {
2967             return new DERPrintableString(((ASN1OctetString)obj).getOctets());
2968         }
2969
2970         if (obj instanceof ASN1TaggedObject)
2971         {
2972             return getInstance(((ASN1TaggedObject)obj).getObject());
2973         }
2974
2975         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
2976     }
2977
2978     /**
2979      * return a Printable String from a tagged object.
2980      *
2981      * @param obj the tagged object holding the object we want
2982      * @param explicit true if the object is meant to be explicitly
2983      *              tagged false otherwise.
2984      * @exception IllegalArgumentException if the tagged object cannot
2985      *               be converted.
2986      */
2987     public static DERPrintableString getInstance(
2988         ASN1TaggedObject obj,
2989         boolean          explicit)
2990     {
2991         return getInstance(obj.getObject());
2992     }
2993
2994     /**
2995      * basic constructor - byte encoded string.
2996      */
2997     public DERPrintableString(
2998         byte[]   string)
2999     {
3000         char[]  cs = new char[string.length];
3001
3002         for (int i = 0; i != cs.length; i++)
3003         {
3004             cs[i] = (char)(string[i] & 0xff);
3005         }
3006
3007         this.string = new String(cs);
3008     }
3009
3010     /**
3011      * basic constructor
3012      */
3013     public DERPrintableString(
3014         String   string)
3015     {
3016         this.string = string;
3017     }
3018
3019     public String getString()
3020     {
3021         return string;
3022     }
3023
3024     public byte[] getOctets()
3025     {
3026         char[]  cs = string.toCharArray();
3027         byte[]  bs = new byte[cs.length];
3028
3029         for (int i = 0; i != cs.length; i++)
3030         {
3031             bs[i] = (byte)cs[i];
3032         }
3033
3034         return bs; 
3035     }
3036
3037     void encode(
3038         DEROutputStream  out)
3039         throws IOException
3040     {
3041         out.writeEncoded(PRINTABLE_STRING, this.getOctets());
3042     }
3043
3044     public int hashCode()
3045     {
3046         return this.getString().hashCode();
3047     }
3048
3049     public boolean equals(
3050         Object  o)
3051     {
3052         if (!(o instanceof DERPrintableString))
3053         {
3054             return false;
3055         }
3056
3057         DERPrintableString  s = (DERPrintableString)o;
3058
3059         return this.getString().equals(s.getString());
3060     }
3061 }
3062
3063
3064 class DERSequence
3065     extends ASN1Sequence
3066 {
3067     /**
3068      * create an empty sequence
3069      */
3070     public DERSequence()
3071     {
3072     }
3073
3074     /**
3075      * create a sequence containing one object
3076      */
3077     public DERSequence(
3078         DEREncodable    obj)
3079     {
3080         this.addObject(obj);
3081     }
3082
3083     /**
3084      * create a sequence containing a vector of objects.
3085      */
3086     public DERSequence(
3087         DEREncodableVector   v)
3088     {
3089         for (int i = 0; i != v.size(); i++)
3090         {
3091             this.addObject(v.get(i));
3092         }
3093     }
3094
3095     /*
3096      * A note on the implementation:
3097      * <p>
3098      * As DER requires the constructed, definite-length model to
3099      * be used for structured types, this varies slightly from the
3100      * ASN.1 descriptions given. Rather than just outputing SEQUENCE,
3101      * we also have to specify CONSTRUCTED, and the objects length.
3102      */
3103     void encode(
3104         DEROutputStream out)
3105         throws IOException
3106     {
3107         ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
3108         DEROutputStream         dOut = new DEROutputStream(bOut);
3109         Enumeration             e = this.getObjects();
3110
3111         while (e.hasMoreElements())
3112         {
3113             Object    obj = e.nextElement();
3114
3115             dOut.writeObject(obj);
3116         }
3117
3118         dOut.close();
3119
3120         byte[]  bytes = bOut.toByteArray();
3121
3122         out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
3123     }
3124 }
3125
3126
3127 /**
3128  * A DER encoded set object
3129  */
3130 class DERSet
3131     extends ASN1Set
3132 {
3133     /**
3134      * create an empty set
3135      */
3136     public DERSet()
3137     {
3138     }
3139
3140     /**
3141      * @param obj - a single object that makes up the set.
3142      */
3143     public DERSet(
3144         DEREncodable   obj)
3145     {
3146         this.addObject(obj);
3147     }
3148
3149     /**
3150      * @param v - a vector of objects making up the set.
3151      */
3152     public DERSet(
3153         DEREncodableVector   v)
3154     {
3155         for (int i = 0; i != v.size(); i++)
3156         {
3157             this.addObject(v.get(i));
3158         }
3159     }
3160
3161     /*
3162      * A note on the implementation:
3163      * <p>
3164      * As DER requires the constructed, definite-length model to
3165      * be used for structured types, this varies slightly from the
3166      * ASN.1 descriptions given. Rather than just outputing SET,
3167      * we also have to specify CONSTRUCTED, and the objects length.
3168      */
3169     void encode(
3170         DEROutputStream out)
3171         throws IOException
3172     {
3173         ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
3174         DEROutputStream         dOut = new DEROutputStream(bOut);
3175         Enumeration             e = this.getObjects();
3176
3177         while (e.hasMoreElements())
3178         {
3179             Object    obj = e.nextElement();
3180
3181             dOut.writeObject(obj);
3182         }
3183
3184         dOut.close();
3185
3186         byte[]  bytes = bOut.toByteArray();
3187
3188         out.writeEncoded(SET | CONSTRUCTED, bytes);
3189     }
3190 }
3191
3192 /**
3193  * basic interface for DER string objects.
3194  */
3195 interface DERString
3196 {
3197     public String getString();
3198 }
3199
3200
3201 /**
3202  * DER T61String (also the teletex string)
3203  */
3204 class DERT61String
3205     extends DERObject
3206     implements DERString
3207 {
3208     String  string;
3209
3210     /**
3211      * return a T61 string from the passed in object.
3212      *
3213      * @exception IllegalArgumentException if the object cannot be converted.
3214      */
3215     public static DERT61String getInstance(
3216         Object  obj)
3217     {
3218         if (obj == null || obj instanceof DERT61String)
3219         {
3220             return (DERT61String)obj;
3221         }
3222
3223         if (obj instanceof ASN1OctetString)
3224         {
3225             return new DERT61String(((ASN1OctetString)obj).getOctets());
3226         }
3227
3228         if (obj instanceof ASN1TaggedObject)
3229         {
3230             return getInstance(((ASN1TaggedObject)obj).getObject());
3231         }
3232
3233         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
3234     }
3235
3236     /**
3237      * return an T61 String from a tagged object.
3238      *
3239      * @param obj the tagged object holding the object we want
3240      * @param explicit true if the object is meant to be explicitly
3241      *              tagged false otherwise.
3242      * @exception IllegalArgumentException if the tagged object cannot
3243      *               be converted.
3244      */
3245     public static DERT61String getInstance(
3246         ASN1TaggedObject obj,
3247         boolean          explicit)
3248     {
3249         return getInstance(obj.getObject());
3250     }
3251
3252     /**
3253      * basic constructor - with bytes.
3254      */
3255     public DERT61String(
3256         byte[]   string)
3257     {
3258         this.string = new String(string);
3259     }
3260
3261     /**
3262      * basic constructor - with string.
3263      */
3264     public DERT61String(
3265         String   string)
3266     {
3267         this.string = string;
3268     }
3269
3270     public String getString()
3271     {
3272         return string;
3273     }
3274
3275     void encode(
3276         DEROutputStream  out)
3277         throws IOException
3278     {
3279         out.writeEncoded(T61_STRING, string.getBytes());
3280     }
3281
3282     public boolean equals(
3283         Object  o)
3284     {
3285         if ((o == null) || !(o instanceof DERT61String))
3286         {
3287             return false;
3288         }
3289
3290         return this.getString().equals(((DERT61String)o).getString());
3291     }
3292 }
3293
3294
3295 /**
3296  * DER TaggedObject - in ASN.1 nottation this is any object proceeded by
3297  * a [n] where n is some number - these are assume to follow the construction
3298  * rules (as with sequences).
3299  */
3300 class DERTaggedObject
3301     extends ASN1TaggedObject
3302 {
3303     /**
3304      * @param tagNo the tag number for this object.
3305      * @param obj the tagged object.
3306      */
3307     public DERTaggedObject(
3308         int             tagNo,
3309         DEREncodable    obj)
3310     {
3311                 super(tagNo, obj);
3312     }
3313
3314     /**
3315      * @param explicit true if an explicitly tagged object.
3316      * @param tagNo the tag number for this object.
3317      * @param obj the tagged object.
3318      */
3319     public DERTaggedObject(
3320         boolean         explicit,
3321         int             tagNo,
3322         DEREncodable    obj)
3323     {
3324                 super(explicit, tagNo, obj);
3325     }
3326
3327     /**
3328      * create an implicitly tagged object that contains a zero
3329      * length sequence.
3330      */
3331     public DERTaggedObject(
3332         int             tagNo)
3333     {
3334         super(false, tagNo, new DERSequence());
3335     }
3336
3337     void encode(
3338         DEROutputStream  out)
3339         throws IOException
3340     {
3341         if (!empty)
3342         {
3343             ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
3344             DEROutputStream         dOut = new DEROutputStream(bOut);
3345
3346             dOut.writeObject(obj);
3347             dOut.close();
3348
3349             byte[]  bytes = bOut.toByteArray();
3350
3351             if (explicit)
3352             {
3353                 out.writeEncoded(CONSTRUCTED | TAGGED | tagNo, bytes);
3354             }
3355             else
3356             {
3357                 //
3358                 // need to mark constructed types...
3359                 //
3360                 if ((bytes[0] & CONSTRUCTED) != 0)
3361                 {
3362                     bytes[0] = (byte)(CONSTRUCTED | TAGGED | tagNo);
3363                 }
3364                 else
3365                 {
3366                     bytes[0] = (byte)(TAGGED | tagNo);
3367                 }
3368
3369                 out.write(bytes);
3370             }
3371         }
3372         else
3373         {
3374             out.writeEncoded(CONSTRUCTED | TAGGED | tagNo, new byte[0]);
3375         }
3376     }
3377 }
3378
3379 interface DERTags
3380 {
3381     public static final int BOOLEAN             = 0x01;
3382     public static final int INTEGER             = 0x02;
3383     public static final int BIT_STRING          = 0x03;
3384     public static final int OCTET_STRING        = 0x04;
3385     public static final int NULL                = 0x05;
3386     public static final int OBJECT_IDENTIFIER   = 0x06;
3387     public static final int EXTERNAL            = 0x08;
3388     public static final int ENUMERATED          = 0x0a;
3389     public static final int SEQUENCE            = 0x10;
3390     public static final int SEQUENCE_OF         = 0x10; // for completeness
3391     public static final int SET                 = 0x11;
3392     public static final int SET_OF              = 0x11; // for completeness
3393     public static final int CONSTRUCTED         = 0x20;
3394     public static final int TAGGED              = 0x80;
3395
3396     public static final int NUMERIC_STRING      = 0x12;
3397     public static final int PRINTABLE_STRING    = 0x13;
3398     public static final int T61_STRING          = 0x14;
3399     public static final int VIDEOTEX_STRING     = 0x15;
3400     public static final int IA5_STRING          = 0x16;
3401     public static final int UTC_TIME            = 0x17;
3402     public static final int GENERALIZED_TIME    = 0x18;
3403     public static final int GRAPHIC_STRING      = 0x19;
3404     public static final int VISIBLE_STRING      = 0x1a;
3405     public static final int GENERAL_STRING      = 0x1b;
3406     public static final int UNIVERSAL_STRING    = 0x1c;
3407     public static final int BMP_STRING          = 0x1e;
3408     public static final int UTF8_STRING         = 0x0c;
3409 }
3410
3411
3412 /**
3413  * DER UniversalString object.
3414  */
3415 class DERUniversalString
3416     extends DERObject
3417     implements DERString
3418 {
3419     byte[]  string;
3420     char[]  table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
3421
3422     /**
3423      * return a Universal String from the passed in object.
3424      *
3425      * @exception IllegalArgumentException if the object cannot be converted.
3426      */
3427     public static DERUniversalString getInstance(
3428         Object  obj)
3429     {
3430         if (obj == null || obj instanceof DERUniversalString)
3431         {
3432             return (DERUniversalString)obj;
3433         }
3434
3435         if (obj instanceof ASN1OctetString)
3436         {
3437             return new DERUniversalString(((ASN1OctetString)obj).getOctets());
3438         }
3439
3440         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
3441     }
3442
3443     /**
3444      * return a Universal String from a tagged object.
3445      *
3446      * @param obj the tagged object holding the object we want
3447      * @param explicit true if the object is meant to be explicitly
3448      *              tagged false otherwise.
3449      * @exception IllegalArgumentException if the tagged object cannot
3450      *               be converted.
3451      */
3452     public static DERUniversalString getInstance(
3453         ASN1TaggedObject obj,
3454         boolean          explicit)
3455     {
3456         return getInstance(obj.getObject());
3457     }
3458
3459     /**
3460      * basic constructor - byte encoded string.
3461      */
3462     public DERUniversalString(
3463         byte[]   string)
3464     {
3465         this.string = string;
3466     }
3467
3468     /**
3469      * UniversalStrings have characters which are 4 bytes long - for the
3470      * moment we just return them in Hex...
3471      */
3472     public String getString()
3473     {
3474         StringBuffer    buf = new StringBuffer();
3475
3476         for (int i = 0; i != string.length; i++)
3477         {
3478             buf.append(table[(string[i] >>> 4) % 0xf]);
3479             buf.append(table[string[i] & 0xf]);
3480         }
3481
3482         return buf.toString();
3483     }
3484
3485     public byte[] getOctets()
3486     {
3487         return string;
3488     }
3489
3490     void encode(
3491         DEROutputStream  out)
3492         throws IOException
3493     {
3494         out.writeEncoded(UNIVERSAL_STRING, this.getOctets());
3495     }
3496     
3497     public boolean equals(
3498         Object  o)
3499     {
3500         if ((o == null) || !(o instanceof DERUniversalString))
3501         {
3502             return false;
3503         }
3504
3505         return this.getString().equals(((DERUniversalString)o).getString());
3506     }
3507 }
3508
3509
3510 /**
3511  * We insert one of these when we find a tag we don't recognise.
3512  */
3513 class DERUnknownTag
3514     extends DERObject
3515 {
3516     int         tag;
3517     byte[]      data;
3518
3519     /**
3520      * @param tag the tag value.
3521      * @param data the octets making up the time.
3522      */
3523     public DERUnknownTag(
3524         int     tag,
3525         byte[]  data)
3526     {
3527         this.tag = tag;
3528         this.data = data;
3529     }
3530
3531     public int getTag()
3532     {
3533         return tag;
3534     }
3535
3536     public byte[] getData()
3537     {
3538         return data;
3539     }
3540
3541     void encode(
3542         DEROutputStream  out)
3543         throws IOException
3544     {
3545         out.writeEncoded(tag, data);
3546     }
3547     
3548         public boolean equals(
3549                 Object o)
3550         {
3551         if ((o == null) || !(o instanceof DERUnknownTag))
3552         {
3553             return false;
3554         }
3555         
3556         DERUnknownTag other = (DERUnknownTag)o;
3557         
3558         if(tag != other.tag)
3559         {
3560                         return false;
3561                 }
3562                 
3563                 if(data.length != other.data.length)
3564                 {
3565                         return false;
3566                 }
3567                 
3568                 for(int i = 0; i < data.length; i++) 
3569                 {
3570                         if(data[i] != other.data[i])
3571                         {
3572                                 return false;
3573                         }
3574                 }
3575                 
3576                 return true;
3577         }
3578 }
3579
3580
3581 /**
3582  * UTC time object.
3583  */
3584 class DERUTCTime
3585     extends DERObject
3586 {
3587     String      time;
3588
3589     /**
3590      * return an UTC Time from the passed in object.
3591      *
3592      * @exception IllegalArgumentException if the object cannot be converted.
3593      */
3594     public static DERUTCTime getInstance(
3595         Object  obj)
3596     {
3597         if (obj == null || obj instanceof DERUTCTime)
3598         {
3599             return (DERUTCTime)obj;
3600         }
3601
3602         if (obj instanceof ASN1OctetString)
3603         {
3604             return new DERUTCTime(((ASN1OctetString)obj).getOctets());
3605         }
3606
3607         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
3608     }
3609
3610     /**
3611      * return an UTC Time from a tagged object.
3612      *
3613      * @param obj the tagged object holding the object we want
3614      * @param explicit true if the object is meant to be explicitly
3615      *              tagged false otherwise.
3616      * @exception IllegalArgumentException if the tagged object cannot
3617      *               be converted.
3618      */
3619     public static DERUTCTime getInstance(
3620         ASN1TaggedObject obj,
3621         boolean          explicit)
3622     {
3623         return getInstance(obj.getObject());
3624     }
3625     
3626     /**
3627      * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
3628      * never encoded. When you're creating one of these objects from scratch, that's
3629      * what you want to use, otherwise we'll try to deal with whatever gets read from
3630      * the input stream... (this is why the input format is different from the getTime()
3631      * method output).
3632      * <p>
3633      *
3634      * @param time the time string.
3635      */
3636     public DERUTCTime(
3637         String  time)
3638     {
3639         this.time = time;
3640     }
3641
3642     /**
3643      * base constructer from a java.util.date object
3644      */
3645     public DERUTCTime(
3646        Date time)
3647     {
3648         SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
3649
3650         dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
3651
3652         this.time = dateF.format(time);
3653     }
3654
3655     DERUTCTime(
3656         byte[]  bytes)
3657     {
3658         //
3659         // explicitly convert to characters
3660         //
3661         char[]  dateC = new char[bytes.length];
3662
3663         for (int i = 0; i != dateC.length; i++)
3664         {
3665             dateC[i] = (char)(bytes[i] & 0xff);
3666         }
3667
3668         this.time = new String(dateC);
3669     }
3670
3671     /**
3672      * return the time - always in the form of 
3673      *  YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
3674      * <p>
3675      * Normally in a certificate we would expect "Z" rather than "GMT",
3676      * however adding the "GMT" means we can just use:
3677      * <pre>
3678      *     dateF = new SimpleDateFormat("yyMMddHHmmssz");
3679      * </pre>
3680      * To read in the time and get a date which is compatible with our local
3681      * time zone.
3682      * <p>
3683      * <b>Note:</b> In some cases, due to the local date processing, this
3684      * may lead to unexpected results. If you want to stick the normal
3685      * convention of 1950 to 2049 use the getAdjustedTime() method.
3686      */
3687     public String getTime()
3688     {
3689         //
3690         // standardise the format.
3691         //
3692         if (time.length() == 11)
3693         {
3694             return time.substring(0, 10) + "00GMT+00:00";
3695         }
3696         else if (time.length() == 13)
3697         {
3698             return time.substring(0, 12) + "GMT+00:00";
3699         }
3700         else if (time.length() == 17)
3701         {
3702             return time.substring(0, 12) + "GMT" + time.substring(12, 15) + ":" + time.substring(15, 17);
3703         }
3704
3705         return time;
3706     }
3707
3708     /**
3709      * return the time as an adjusted date with a 4 digit year. This goes
3710      * in the range of 1950 - 2049.
3711      */
3712     public String getAdjustedTime()
3713     {
3714         String   d = this.getTime();
3715
3716         if (d.charAt(0) < '5')
3717         {
3718             return "20" + d;
3719         }
3720         else
3721         {
3722             return "19" + d;
3723         }
3724     }
3725
3726     private byte[] getOctets()
3727     {
3728         char[]  cs = time.toCharArray();
3729         byte[]  bs = new byte[cs.length];
3730
3731         for (int i = 0; i != cs.length; i++)
3732         {
3733             bs[i] = (byte)cs[i];
3734         }
3735
3736         return bs;
3737     }
3738
3739     void encode(
3740         DEROutputStream  out)
3741         throws IOException
3742     {
3743         out.writeEncoded(UTC_TIME, this.getOctets());
3744     }
3745     
3746     public boolean equals(
3747         Object  o)
3748     {
3749         if ((o == null) || !(o instanceof DERUTCTime))
3750         {
3751             return false;
3752         }
3753
3754         return time.equals(((DERUTCTime)o).time);
3755     }
3756 }
3757
3758
3759 /**
3760  * DER UTF8String object.
3761  */
3762 class DERUTF8String
3763     extends DERObject
3764     implements DERString
3765 {
3766     String  string;
3767
3768     /**
3769      * return an UTF8 string from the passed in object.
3770      *
3771      * @exception IllegalArgumentException if the object cannot be converted.
3772      */
3773     public static DERUTF8String getInstance(
3774         Object  obj)
3775     {
3776         if (obj == null || obj instanceof DERUTF8String)
3777         {
3778             return (DERUTF8String)obj;
3779         }
3780
3781         if (obj instanceof ASN1OctetString)
3782         {
3783             return new DERUTF8String(((ASN1OctetString)obj).getOctets());
3784         }
3785
3786         if (obj instanceof ASN1TaggedObject)
3787         {
3788             return getInstance(((ASN1TaggedObject)obj).getObject());
3789         }
3790
3791         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
3792     }
3793
3794     /**
3795      * return an UTF8 String from a tagged object.
3796      *
3797      * @param obj the tagged object holding the object we want
3798      * @param explicit true if the object is meant to be explicitly
3799      *              tagged false otherwise.
3800      * @exception IllegalArgumentException if the tagged object cannot
3801      *               be converted.
3802      */
3803     public static DERUTF8String getInstance(
3804         ASN1TaggedObject obj,
3805         boolean          explicit)
3806     {
3807         return getInstance(obj.getObject());
3808     }
3809
3810     /**
3811      * basic constructor - byte encoded string.
3812      */
3813     DERUTF8String(
3814         byte[]   string)
3815     {
3816         int i = 0;
3817         int length = 0;
3818
3819         while (i < string.length)
3820         {
3821             length++;
3822             if ((string[i] & 0xe0) == 0xe0)
3823             {
3824                 i += 3;
3825             }
3826             else if ((string[i] & 0xc0) == 0xc0)
3827             {
3828                 i += 2;
3829             }
3830             else
3831             {
3832                 i += 1;
3833             }
3834         }
3835
3836         char[]  cs = new char[length];
3837
3838         i = 0;
3839         length = 0;
3840
3841         while (i < string.length)
3842         {
3843             char    ch;
3844
3845             if ((string[i] & 0xe0) == 0xe0)
3846             {
3847                 ch = (char)(((string[i] & 0x1f) << 12)
3848                       | ((string[i + 1] & 0x3f) << 6) | (string[i + 2] & 0x3f));
3849                 i += 3;
3850             }
3851             else if ((string[i] & 0xc0) == 0xc0)
3852             {
3853                 ch = (char)(((string[i] & 0x3f) << 6) | (string[i + 1] & 0x3f));
3854                 i += 2;
3855             }
3856             else
3857             {
3858                 ch = (char)(string[i] & 0xff);
3859                 i += 1;
3860             }
3861
3862             cs[length++] = ch;
3863         }
3864
3865         this.string = new String(cs);
3866     }
3867
3868     /**
3869      * basic constructor
3870      */
3871     public DERUTF8String(
3872         String   string)
3873     {
3874         this.string = string;
3875     }
3876
3877     public String getString()
3878     {
3879         return string;
3880     }
3881
3882     public int hashCode()
3883     {
3884         return this.getString().hashCode();
3885     }
3886
3887     public boolean equals(
3888         Object  o)
3889     {
3890         if (!(o instanceof DERUTF8String))
3891         {
3892             return false;
3893         }
3894
3895         DERUTF8String  s = (DERUTF8String)o;
3896
3897         return this.getString().equals(s.getString());
3898     }
3899
3900     void encode(
3901         DEROutputStream  out)
3902         throws IOException
3903     {
3904         char[]                  c = string.toCharArray();
3905         ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
3906
3907         for (int i = 0; i != c.length; i++)
3908         {
3909             char    ch = c[i];
3910
3911             if (ch < 0x0080)
3912             {
3913                 bOut.write(ch);
3914             }
3915             else if (ch < 0x0800)
3916             {
3917                 bOut.write(0xc0 | (ch >> 6));
3918                 bOut.write(0x80 | (ch & 0x3f));
3919             }
3920             else
3921             {
3922                 bOut.write(0xe0 | (ch >> 12));
3923                 bOut.write(0x80 | ((ch >> 6) & 0x3F));
3924                 bOut.write(0x80 | (ch & 0x3F));
3925             }
3926         }
3927
3928         out.writeEncoded(UTF8_STRING, bOut.toByteArray());
3929     }
3930 }
3931
3932
3933 /**
3934  * DER VisibleString object.
3935  */
3936 class DERVisibleString
3937     extends DERObject
3938     implements DERString
3939 {
3940     String  string;
3941
3942     /**
3943      * return a Visible String from the passed in object.
3944      *
3945      * @exception IllegalArgumentException if the object cannot be converted.
3946      */
3947     public static DERVisibleString getInstance(
3948         Object  obj)
3949     {
3950         if (obj == null || obj instanceof DERVisibleString)
3951         {
3952             return (DERVisibleString)obj;
3953         }
3954
3955         if (obj instanceof ASN1OctetString)
3956         {
3957             return new DERVisibleString(((ASN1OctetString)obj).getOctets());
3958         }
3959
3960         if (obj instanceof ASN1TaggedObject)
3961         {
3962             return getInstance(((ASN1TaggedObject)obj).getObject());
3963         }
3964
3965         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
3966     }
3967
3968     /**
3969      * return a Visible String from a tagged object.
3970      *
3971      * @param obj the tagged object holding the object we want
3972      * @param explicit true if the object is meant to be explicitly
3973      *              tagged false otherwise.
3974      * @exception IllegalArgumentException if the tagged object cannot
3975      *               be converted.
3976      */
3977     public static DERVisibleString getInstance(
3978         ASN1TaggedObject obj,
3979         boolean          explicit)
3980     {
3981         return getInstance(obj.getObject());
3982     }
3983
3984     /**
3985      * basic constructor - byte encoded string.
3986      */
3987     public DERVisibleString(
3988         byte[]   string)
3989     {
3990         char[]  cs = new char[string.length];
3991
3992         for (int i = 0; i != cs.length; i++)
3993         {
3994             cs[i] = (char)(string[i] & 0xff);
3995         }
3996
3997         this.string = new String(cs);
3998     }
3999
4000     /**
4001      * basic constructor
4002      */
4003     public DERVisibleString(
4004         String   string)
4005     {
4006         this.string = string;
4007     }
4008
4009     public String getString()
4010     {
4011         return string;
4012     }
4013
4014     public byte[] getOctets()
4015     {
4016         char[]  cs = string.toCharArray();
4017         byte[]  bs = new byte[cs.length];
4018
4019         for (int i = 0; i != cs.length; i++)
4020         {
4021             bs[i] = (byte)cs[i];
4022         }
4023
4024         return bs;
4025     }
4026
4027     void encode(
4028         DEROutputStream  out)
4029         throws IOException
4030     {
4031         out.writeEncoded(VISIBLE_STRING, this.getOctets());
4032     }
4033     
4034     public boolean equals(
4035         Object  o)
4036     {
4037         if ((o == null) || !(o instanceof DERVisibleString))
4038         {
4039             return false;
4040         }
4041
4042         return this.getString().equals(((DERVisibleString)o).getString());
4043     }
4044 }
4045
4046 /**
4047  * class for breaking up an OID into it's component tokens, ala
4048  * java.util.StringTokenizer. We need this class as some of the
4049  * lightweight Java environment don't support classes like
4050  * StringTokenizer.
4051  */
4052 class OIDTokenizer
4053 {
4054     private String  oid;
4055     private int     index;
4056
4057     public OIDTokenizer(
4058         String oid)
4059     {
4060         this.oid = oid;
4061         this.index = 0;
4062     }
4063
4064     public boolean hasMoreTokens()
4065     {
4066         return (index != -1);
4067     }
4068
4069     public String nextToken()
4070     {
4071         if (index == -1)
4072         {
4073             return null;
4074         }
4075
4076         String  token;
4077         int     end = oid.indexOf('.', index);
4078
4079         if (end == -1)
4080         {
4081             token = oid.substring(index);
4082             index = -1;
4083             return token;
4084         }
4085
4086         token = oid.substring(index, end);
4087
4088         index = end + 1;
4089         return token;
4090     }
4091 }
4092
4093
4094 interface PKCSObjectIdentifiers
4095 {
4096     //
4097     // pkcs-1 OBJECT IDENTIFIER ::= {
4098     //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
4099     //
4100     static final String                 pkcs_1                  = "1.2.840.113549.1.1";
4101     static final DERObjectIdentifier    rsaEncryption           = new DERObjectIdentifier(pkcs_1 + ".1");
4102     static final DERObjectIdentifier    md2WithRSAEncryption    = new DERObjectIdentifier(pkcs_1 + ".2");
4103     static final DERObjectIdentifier    md4WithRSAEncryption    = new DERObjectIdentifier(pkcs_1 + ".3");
4104     static final DERObjectIdentifier    md5WithRSAEncryption    = new DERObjectIdentifier(pkcs_1 + ".4");
4105     static final DERObjectIdentifier    sha1WithRSAEncryption   = new DERObjectIdentifier(pkcs_1 + ".5");
4106     static final DERObjectIdentifier    srsaOAEPEncryptionSET   = new DERObjectIdentifier(pkcs_1 + ".6");
4107     static final DERObjectIdentifier    sha256WithRSAEncryption   = new DERObjectIdentifier(pkcs_1 + ".11");
4108     static final DERObjectIdentifier    sha384WithRSAEncryption   = new DERObjectIdentifier(pkcs_1 + ".12");
4109     static final DERObjectIdentifier    sha512WithRSAEncryption   = new DERObjectIdentifier(pkcs_1 + ".13");
4110
4111     //
4112     // pkcs-3 OBJECT IDENTIFIER ::= {
4113     //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 }
4114     //
4115     static final String                 pkcs_3                  = "1.2.840.113549.1.3";
4116     static final DERObjectIdentifier    dhKeyAgreement          = new DERObjectIdentifier(pkcs_3 + ".1");
4117
4118     //
4119     // pkcs-5 OBJECT IDENTIFIER ::= {
4120     //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 }
4121     //
4122     static final String                 pkcs_5                  = "1.2.840.113549.1.5";
4123
4124     static final DERObjectIdentifier    id_PBES2                = new DERObjectIdentifier(pkcs_5 + ".13");
4125
4126     static final DERObjectIdentifier    id_PBKDF2               = new DERObjectIdentifier(pkcs_5 + ".12");
4127
4128     //
4129     // encryptionAlgorithm OBJECT IDENTIFIER ::= {
4130     //       iso(1) member-body(2) us(840) rsadsi(113549) 3 }
4131     //
4132     static final String                 encryptionAlgorithm     = "1.2.840.113549.3";
4133
4134     static final DERObjectIdentifier    des_EDE3_CBC            = new DERObjectIdentifier(encryptionAlgorithm + ".7");
4135     static final DERObjectIdentifier    RC2_CBC                 = new DERObjectIdentifier(encryptionAlgorithm + ".2");
4136
4137     //
4138     // object identifiers for digests
4139     //
4140
4141     //
4142     // md2 OBJECT IDENTIFIER ::=
4143     //      {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 2}
4144     //
4145     static final DERObjectIdentifier    md2                     = new DERObjectIdentifier("1.2.840.113549.2.2");
4146
4147     //
4148     // md5 OBJECT IDENTIFIER ::=
4149     //      {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
4150     //
4151     static final DERObjectIdentifier    md5                     = new DERObjectIdentifier("1.2.840.113549.2.5");
4152
4153     //
4154     // pkcs-7 OBJECT IDENTIFIER ::= {
4155     //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 }
4156     //
4157     static final String                 pkcs_7                  = "1.2.840.113549.1.7";
4158     static final DERObjectIdentifier    data                    = new DERObjectIdentifier(pkcs_7 + ".1");
4159     static final DERObjectIdentifier    signedData              = new DERObjectIdentifier(pkcs_7 + ".2");
4160     static final DERObjectIdentifier    envelopedData           = new DERObjectIdentifier(pkcs_7 + ".3");
4161     static final DERObjectIdentifier    signedAndEnvelopedData  = new DERObjectIdentifier(pkcs_7 + ".4");
4162     static final DERObjectIdentifier    digestedData            = new DERObjectIdentifier(pkcs_7 + ".5");
4163     static final DERObjectIdentifier    encryptedData           = new DERObjectIdentifier(pkcs_7 + ".6");
4164
4165     //
4166     // pkcs-9 OBJECT IDENTIFIER ::= {
4167     //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
4168     //
4169     static final String                 pkcs_9                  = "1.2.840.113549.1.9";
4170
4171     static final DERObjectIdentifier    pkcs_9_at_emailAddress  = new DERObjectIdentifier(pkcs_9 + ".1");
4172     static final DERObjectIdentifier    pkcs_9_at_unstructuredName = new DERObjectIdentifier(pkcs_9 + ".2");
4173     static final DERObjectIdentifier    pkcs_9_at_contentType = new DERObjectIdentifier(pkcs_9 + ".3");
4174     static final DERObjectIdentifier    pkcs_9_at_messageDigest = new DERObjectIdentifier(pkcs_9 + ".4");
4175     static final DERObjectIdentifier    pkcs_9_at_signingTime = new DERObjectIdentifier(pkcs_9 + ".5");
4176     static final DERObjectIdentifier    pkcs_9_at_counterSignature = new DERObjectIdentifier(pkcs_9 + ".6");
4177     static final DERObjectIdentifier    pkcs_9_at_challengePassword = new DERObjectIdentifier(pkcs_9 + ".7");
4178     static final DERObjectIdentifier    pkcs_9_at_unstructuredAddress = new DERObjectIdentifier(pkcs_9 + ".8");
4179     static final DERObjectIdentifier    pkcs_9_at_extendedCertificateAttributes = new DERObjectIdentifier(pkcs_9 + ".9");
4180
4181     static final DERObjectIdentifier    pkcs_9_at_signingDescription = new DERObjectIdentifier(pkcs_9 + ".13");
4182     static final DERObjectIdentifier    pkcs_9_at_extensionRequest = new DERObjectIdentifier(pkcs_9 + ".14");
4183     static final DERObjectIdentifier    pkcs_9_at_smimeCapabilities = new DERObjectIdentifier(pkcs_9 + ".15");
4184
4185     static final DERObjectIdentifier    pkcs_9_at_friendlyName  = new DERObjectIdentifier(pkcs_9 + ".20");
4186     static final DERObjectIdentifier    pkcs_9_at_localKeyId    = new DERObjectIdentifier(pkcs_9 + ".21");
4187
4188     static final DERObjectIdentifier    x509certType            = new DERObjectIdentifier(pkcs_9 + ".22.1");
4189
4190     //
4191     // SMIME capability sub oids.
4192     //
4193     static final DERObjectIdentifier    preferSignedData        = new DERObjectIdentifier(pkcs_9 + ".15.1");
4194     static final DERObjectIdentifier    canNotDecryptAny        = new DERObjectIdentifier(pkcs_9 + ".15.2");
4195     static final DERObjectIdentifier    sMIMECapabilitiesVersions = new DERObjectIdentifier(pkcs_9 + ".15.3");
4196
4197     //
4198     // other SMIME attributes
4199     //
4200
4201         //
4202         // id-aa OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
4203         // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) attributes(2)}
4204         //
4205         static String id_aa = "1.2.840.113549.1.9.16.2";
4206         
4207         /*
4208          * id-aa-encrypKeyPref OBJECT IDENTIFIER ::= {id-aa 11}
4209          * 
4210          */
4211         static DERObjectIdentifier id_aa_encrypKeyPref = new DERObjectIdentifier(id_aa + ".11");
4212
4213     //
4214     // pkcs-12 OBJECT IDENTIFIER ::= {
4215     //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 }
4216     //
4217     static final String                 pkcs_12                  = "1.2.840.113549.1.12";
4218     static final String                 bagtypes                 = pkcs_12 + ".10.1";
4219
4220     static final DERObjectIdentifier    keyBag                  = new DERObjectIdentifier(bagtypes + ".1");
4221     static final DERObjectIdentifier    pkcs8ShroudedKeyBag     = new DERObjectIdentifier(bagtypes + ".2");
4222     static final DERObjectIdentifier    certBag                 = new DERObjectIdentifier(bagtypes + ".3");
4223     static final DERObjectIdentifier    crlBag                  = new DERObjectIdentifier(bagtypes + ".4");
4224     static final DERObjectIdentifier    secretBag               = new DERObjectIdentifier(bagtypes + ".5");
4225     static final DERObjectIdentifier    safeContentsBag         = new DERObjectIdentifier(bagtypes + ".6");
4226 }
4227
4228
4229
4230
4231 class AlgorithmIdentifier
4232     implements DEREncodable
4233 {
4234     private DERObjectIdentifier objectId;
4235     private DEREncodable        parameters;
4236     private boolean             parametersDefined = false;
4237         
4238     public static AlgorithmIdentifier getInstance(
4239         ASN1TaggedObject obj,
4240         boolean          explicit)
4241     {
4242         return getInstance(ASN1Sequence.getInstance(obj, explicit));
4243     }
4244     
4245     public static AlgorithmIdentifier getInstance(
4246         Object  obj)
4247     {
4248         if (obj instanceof AlgorithmIdentifier)
4249         {
4250             return (AlgorithmIdentifier)obj;
4251         }
4252         
4253         if (obj instanceof DERObjectIdentifier)
4254         {
4255             return new AlgorithmIdentifier((DERObjectIdentifier)obj);
4256         }
4257
4258         if (obj instanceof String)
4259         {
4260             return new AlgorithmIdentifier((String)obj);
4261         }
4262
4263         if (obj instanceof ASN1Sequence)
4264         {
4265             return new AlgorithmIdentifier((ASN1Sequence)obj);
4266         }
4267
4268         throw new IllegalArgumentException("unknown object in factory");
4269     }
4270
4271     public AlgorithmIdentifier(
4272         DERObjectIdentifier     objectId)
4273     {
4274         this.objectId = objectId;
4275     }
4276
4277     public AlgorithmIdentifier(
4278         String     objectId)
4279     {
4280         this.objectId = new DERObjectIdentifier(objectId);
4281     }
4282
4283     public AlgorithmIdentifier(
4284         DERObjectIdentifier     objectId,
4285         DEREncodable            parameters)
4286     {
4287         parametersDefined = true;
4288         this.objectId = objectId;
4289         this.parameters = parameters;
4290     }
4291
4292     public AlgorithmIdentifier(
4293         ASN1Sequence   seq)
4294     {
4295         objectId = (DERObjectIdentifier)seq.getObjectAt(0);
4296
4297         if (seq.size() == 2)
4298         {
4299             parametersDefined = true;
4300             parameters = seq.getObjectAt(1);
4301         }
4302         else
4303         {
4304             parameters = null;
4305         }
4306     }
4307
4308     public DERObjectIdentifier getObjectId()
4309     {
4310         return objectId;
4311     }
4312
4313     public DEREncodable getParameters()
4314     {
4315         return parameters;
4316     }
4317
4318     /**
4319      * <pre>
4320      *      AlgorithmIdentifier ::= SEQUENCE {
4321      *                            algorithm OBJECT IDENTIFIER,
4322      *                            parameters ANY DEFINED BY algorithm OPTIONAL }
4323      * </pre>
4324      */
4325     public DERObject getDERObject()
4326     {
4327         DERConstructedSequence  seq = new DERConstructedSequence();
4328
4329         seq.addObject(objectId);
4330
4331         if (parametersDefined)
4332         {
4333             seq.addObject(parameters);
4334         }
4335
4336         return seq;
4337     }
4338
4339     public boolean equals(
4340         Object  o)
4341     {
4342         if ((o == null) || !(o instanceof AlgorithmIdentifier))
4343         {
4344             return false;
4345         }
4346
4347         AlgorithmIdentifier other = (AlgorithmIdentifier)o;
4348
4349         if (!this.getObjectId().equals(other.getObjectId()))
4350         {
4351             return false;
4352         }
4353
4354         if (this.getParameters() == null && other.getParameters() == null)
4355         {
4356             return true;
4357         }
4358
4359         if (this.getParameters() == null || other.getParameters() == null)
4360         {
4361             return false;
4362         }
4363
4364         ByteArrayOutputStream   b1Out = new ByteArrayOutputStream();
4365         ByteArrayOutputStream   b2Out = new ByteArrayOutputStream();
4366         DEROutputStream         d1Out = new DEROutputStream(b1Out);
4367         DEROutputStream         d2Out = new DEROutputStream(b2Out);
4368
4369         try
4370         {
4371             d1Out.writeObject(this.getParameters());
4372             d2Out.writeObject(other.getParameters());
4373
4374             byte[]  b1 = b1Out.toByteArray();
4375             byte[]  b2 = b2Out.toByteArray();
4376
4377             if (b1.length != b2.length)
4378             {
4379                 return false;
4380             }
4381
4382             for (int i = 0; i != b1.length; i++)
4383             {
4384                 if (b1[i] != b2[i])
4385                 {
4386                     return false;
4387                 }
4388             }
4389         }
4390         catch (Exception e)
4391         {
4392             return false;
4393         }
4394
4395         return true;
4396     }
4397 }
4398
4399
4400
4401
4402 /**
4403  * <pre>
4404  * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }
4405  *
4406  *   AuthorityKeyIdentifier ::= SEQUENCE {
4407  *      keyIdentifier             [0] IMPLICIT KeyIdentifier           OPTIONAL,
4408  *      authorityCertIssuer       [1] IMPLICIT GeneralNames            OPTIONAL,
4409  *      authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL  }
4410  *
4411  *   KeyIdentifier ::= OCTET STRING
4412  * </pre>
4413  *
4414  */
4415 class AuthorityKeyIdentifier
4416     implements DEREncodable, DERTags
4417 {
4418     ASN1OctetString keyidentifier=null;
4419     GeneralNames certissuer=null;
4420     DERInteger certserno=null;
4421
4422     public static AuthorityKeyIdentifier getInstance(
4423         ASN1TaggedObject obj,
4424         boolean          explicit)
4425     {
4426         return getInstance(ASN1Sequence.getInstance(obj, explicit));
4427     }
4428
4429     public static AuthorityKeyIdentifier getInstance(
4430         Object  obj)
4431     {
4432         if (obj instanceof AuthorityKeyIdentifier)
4433         {
4434             return (AuthorityKeyIdentifier)obj;
4435         }
4436         else if (obj instanceof ASN1Sequence)
4437         {
4438             return new AuthorityKeyIdentifier((ASN1Sequence)obj);
4439         }
4440
4441         throw new IllegalArgumentException("unknown object in factory");
4442     }
4443         
4444     public AuthorityKeyIdentifier(
4445         ASN1Sequence   seq)
4446     {
4447         Enumeration     e = seq.getObjects();
4448
4449         while (e.hasMoreElements())
4450         {
4451             DERTaggedObject o = (DERTaggedObject)e.nextElement();
4452
4453             switch (o.getTagNo())
4454             {
4455             case 0:
4456                 this.keyidentifier = ASN1OctetString.getInstance(o, false);
4457                 break;
4458             case 1:
4459                 this.certissuer = GeneralNames.getInstance(o, false);
4460                 break;
4461             case 2:
4462                 this.certserno = DERInteger.getInstance(o, false);
4463                 break;
4464             default:
4465                 throw new IllegalArgumentException("illegal tag");
4466             }
4467         }
4468     }
4469
4470     /**
4471      *
4472      * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
4473      * from SubjectPublicKeyInfo as defined in RFC2459.
4474      *
4475      * Example of making a AuthorityKeyIdentifier:
4476      * <pre>
4477      *   SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((DERConstructedSequence)new DERInputStream(
4478      *       new ByteArrayInputStream(publicKey.getEncoded())).readObject());
4479      *   AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
4480      * </pre>
4481      *
4482      **/
4483     public AuthorityKeyIdentifier(
4484         SubjectPublicKeyInfo    spki)
4485     {
4486         Digest  digest = new SHA1Digest();
4487         byte[]  resBuf = new byte[digest.getDigestSize()];
4488
4489         byte[] bytes = spki.getPublicKeyData().getBytes();
4490         digest.update(bytes, 0, bytes.length);
4491         digest.doFinal(resBuf, 0);
4492         this.keyidentifier = new DEROctetString(resBuf);
4493     }
4494
4495     /**
4496      * create an AuthorityKeyIdentifier with the GeneralNames tag and
4497      * the serial number provided as well.
4498      */
4499     public AuthorityKeyIdentifier(
4500         SubjectPublicKeyInfo    spki,
4501         GeneralNames            name,
4502         BigInteger              serialNumber)
4503     {
4504         Digest  digest = new SHA1Digest();
4505         byte[]  resBuf = new byte[digest.getDigestSize()];
4506
4507         byte[] bytes = spki.getPublicKeyData().getBytes();
4508         digest.update(bytes, 0, bytes.length);
4509         digest.doFinal(resBuf, 0);
4510
4511         this.keyidentifier = new DEROctetString(resBuf);
4512         this.certissuer = name;
4513         this.certserno = new DERInteger(serialNumber);
4514     }
4515
4516     public byte[] getKeyIdentifier()
4517     {
4518         if (keyidentifier != null)
4519         {
4520             return keyidentifier.getOctets();
4521         }
4522
4523         return null;
4524     }
4525
4526      /**
4527      * <pre>
4528      *   AuthorityKeyIdentifier ::= SEQUENCE {
4529      *      keyIdentifier             [0] IMPLICIT KeyIdentifier           OPTIONAL,
4530      *      authorityCertIssuer       [1] IMPLICIT GeneralNames            OPTIONAL,
4531      *      authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL  }
4532      *
4533      *   KeyIdentifier ::= OCTET STRING
4534      * </pre>
4535      */
4536     public DERObject getDERObject()
4537     {
4538         DERConstructedSequence  seq = new DERConstructedSequence();
4539
4540         if (keyidentifier != null)
4541         {
4542             seq.addObject(new DERTaggedObject(false, 0, keyidentifier));
4543         }
4544
4545         if (certissuer != null)
4546         {
4547             seq.addObject(new DERTaggedObject(false, 1, certissuer));
4548         }
4549
4550         if (certserno != null)
4551         {
4552             seq.addObject(new DERTaggedObject(false, 2, certserno));
4553         }
4554
4555
4556         return seq;
4557     }
4558
4559     public String toString()
4560     {
4561         return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.getOctets() + ")");
4562     }
4563 }
4564
4565
4566
4567 class BasicConstraints
4568     implements DEREncodable
4569 {
4570     DERBoolean  cA = new DERBoolean(false);
4571     DERInteger  pathLenConstraint = null;
4572
4573     public static BasicConstraints getInstance(
4574         ASN1TaggedObject obj,
4575         boolean          explicit)
4576     {
4577         return getInstance(ASN1Sequence.getInstance(obj, explicit));
4578     }
4579
4580     public static BasicConstraints getInstance(
4581         Object  obj)
4582     {
4583         if (obj instanceof BasicConstraints)
4584         {
4585             return (BasicConstraints)obj;
4586         }
4587         else if (obj instanceof ASN1Sequence)
4588         {
4589             return new BasicConstraints((ASN1Sequence)obj);
4590         }
4591
4592         throw new IllegalArgumentException("unknown object in factory");
4593     }
4594         
4595     public BasicConstraints(
4596         ASN1Sequence   seq)
4597     {
4598         if (seq.size() != 0)
4599         {
4600             this.cA = (DERBoolean)seq.getObjectAt(0);
4601             this.pathLenConstraint = (DERInteger)seq.getObjectAt(1);
4602         }
4603     }
4604
4605     public BasicConstraints(
4606         boolean cA,
4607         int     pathLenConstraint)
4608     {
4609         this.cA = new DERBoolean(cA);
4610         this.pathLenConstraint = new DERInteger(pathLenConstraint);
4611     }
4612
4613     public BasicConstraints(
4614         boolean cA)
4615     {
4616         this.cA = new DERBoolean(cA);
4617         this.pathLenConstraint = null;
4618     }
4619
4620     public boolean isCA()
4621     {
4622         return cA.isTrue();
4623     }
4624
4625     public BigInteger getPathLenConstraint()
4626     {
4627         if (pathLenConstraint != null)
4628         {
4629             return pathLenConstraint.getValue();
4630         }
4631
4632         return null;
4633     }
4634
4635     /**
4636      * <pre>
4637      * BasicConstraints := SEQUENCE {
4638      *    cA                  BOOLEAN DEFAULT FALSE,
4639      *    pathLenConstraint   INTEGER (0..MAX) OPTIONAL
4640      * }
4641      * </pre>
4642      */
4643     public DERObject getDERObject()
4644     {
4645         DERConstructedSequence  seq = new DERConstructedSequence();
4646
4647         seq.addObject(cA);
4648
4649         if (pathLenConstraint != null)
4650         {
4651             seq.addObject(pathLenConstraint);
4652         }
4653
4654         return seq;
4655     }
4656
4657     public String toString()
4658     {
4659         return "BasicConstraints: isCa(" + this.isCA() + "), pathLenConstraint = " + pathLenConstraint.getValue();
4660     }
4661 }
4662
4663
4664
4665 /**
4666  * PKIX RFC-2459
4667  *
4668  * The X.509 v2 CRL syntax is as follows.  For signature calculation,
4669  * the data that is to be signed is ASN.1 DER encoded.
4670  *
4671  * <pre>
4672  * CertificateList  ::=  SEQUENCE  {
4673  *      tbsCertList          TBSCertList,
4674  *      signatureAlgorithm   AlgorithmIdentifier,
4675  *      signatureValue       BIT STRING  }
4676  * </pre>
4677  */
4678 class CertificateList
4679     implements DEREncodable
4680 {
4681     TBSCertList            tbsCertList;
4682     AlgorithmIdentifier    sigAlgId;
4683     DERBitString           sig;
4684
4685     public static CertificateList getInstance(
4686         ASN1TaggedObject obj,
4687         boolean          explicit)
4688     {
4689         return getInstance(ASN1Sequence.getInstance(obj, explicit));
4690     }
4691
4692     public static CertificateList getInstance(
4693         Object  obj)
4694     {
4695         if (obj instanceof CertificateList)
4696         {
4697             return (CertificateList)obj;
4698         }
4699         else if (obj instanceof ASN1Sequence)
4700         {
4701             return new CertificateList((ASN1Sequence)obj);
4702         }
4703
4704         throw new IllegalArgumentException("unknown object in factory");
4705     }
4706
4707     public CertificateList(
4708         ASN1Sequence seq)
4709     {
4710         tbsCertList = TBSCertList.getInstance(seq.getObjectAt(0));
4711         sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
4712         sig = (DERBitString)seq.getObjectAt(2);
4713     }
4714
4715     public TBSCertList getTBSCertList()
4716     {
4717         return tbsCertList;
4718     }
4719
4720     public TBSCertList.CRLEntry[] getRevokedCertificates()
4721     {
4722         return tbsCertList.getRevokedCertificates();
4723     }
4724
4725     public AlgorithmIdentifier getSignatureAlgorithm()
4726     {
4727         return sigAlgId;
4728     }
4729
4730     public DERBitString getSignature()
4731     {
4732         return sig;
4733     }
4734
4735     public int getVersion()
4736     {
4737         return tbsCertList.getVersion();
4738     }
4739
4740     public X509Name getIssuer()
4741     {
4742         return tbsCertList.getIssuer();
4743     }
4744
4745     public Time getThisUpdate()
4746     {
4747         return tbsCertList.getThisUpdate();
4748     }
4749
4750     public Time getNextUpdate()
4751     {
4752         return tbsCertList.getNextUpdate();
4753     }
4754
4755     public DERObject getDERObject()
4756     {
4757         DERConstructedSequence seq = new DERConstructedSequence();
4758         seq.addObject(tbsCertList);
4759         seq.addObject(sigAlgId);
4760         seq.addObject(sig);
4761         return seq;
4762     }
4763 }
4764
4765
4766 class CRLDistPoint
4767     implements DEREncodable
4768 {
4769     ASN1Sequence  seq = null;
4770
4771     public static CRLDistPoint getInstance(
4772         ASN1TaggedObject obj,
4773         boolean          explicit)
4774     {
4775         return getInstance(ASN1Sequence.getInstance(obj, explicit));
4776     }
4777
4778     public static CRLDistPoint getInstance(
4779         Object  obj)
4780     {
4781         if (obj instanceof CRLDistPoint)
4782         {
4783             return (CRLDistPoint)obj;
4784         }
4785         else if (obj instanceof ASN1Sequence)
4786         {
4787             return new CRLDistPoint((ASN1Sequence)obj);
4788         }
4789
4790         throw new IllegalArgumentException("unknown object in factory");
4791     }
4792         
4793     public CRLDistPoint(
4794         ASN1Sequence seq)
4795     {
4796         this.seq = seq;
4797     }
4798     
4799     public CRLDistPoint(
4800         DistributionPoint[] points)
4801     {
4802         DEREncodableVector  v = new DEREncodableVector();
4803
4804         for (int i = 0; i != points.length; i++)
4805         {
4806             v.add(points[i]);
4807         }
4808
4809         seq = new DERSequence(v);
4810     }
4811
4812     /**
4813      * <pre>
4814      * CRLDistPoint ::= SEQUENCE SIZE {1..MAX} OF DistributionPoint
4815      * </pre>
4816      */
4817     public DERObject getDERObject()
4818     {
4819         return seq;
4820     }
4821 }
4822
4823
4824
4825 /**
4826  * <pre>
4827  * CRLNumber::= INTEGER(0..MAX)
4828  * </pre>
4829  */
4830 class CRLNumber
4831     extends DERInteger
4832 {
4833
4834     public CRLNumber(
4835         BigInteger number)
4836     {
4837         super(number);
4838     }
4839
4840     public BigInteger getCRLNumber()
4841     {
4842         return getPositiveValue();
4843     }
4844 }
4845
4846
4847 class CRLReason
4848     extends DEREnumerated
4849 {
4850     public static final int UNSPECIFIED = 0;
4851     public static final int KEY_COMPROMISE = 1;
4852     public static final int CA_COMPROMISE = 2;
4853     public static final int AFFILIATION_CHANGED = 3;
4854     public static final int SUPERSEDED = 4;
4855     public static final int CESSATION_OF_OPERATION  = 5;
4856     public static final int CERTIFICATE_HOLD = 6;
4857     public static final int REMOVE_FROM_CRL = 8;
4858     public static final int PRIVILEGE_WITHDRAWN = 9;
4859     public static final int AA_COMPROMISE = 10;
4860
4861     /**
4862      * <pre>
4863      * CRLReason ::= ENUMERATED {
4864      *  unspecified             (0),
4865      *  keyCompromise           (1),
4866      *  cACompromise            (2),
4867      *  affiliationChanged      (3),
4868      *  superseded              (4),
4869      *  cessationOfOperation    (5),
4870      *  certificateHold         (6),
4871      *  removeFromCRL           (8),
4872      *  privilegeWithdrawn      (9),
4873      *  aACompromise           (10)
4874      * }
4875      * </pre>
4876      */
4877     public CRLReason(
4878         int reason)
4879     {
4880         super(reason);
4881     }
4882 }
4883
4884
4885
4886 /**
4887  * <pre>
4888  * DigestInfo::=SEQUENCE{
4889  *          digestAlgorithm  AlgorithmIdentifier,
4890  *          digest OCTET STRING }
4891  * </pre>
4892  */
4893 class DigestInfo
4894     implements DEREncodable
4895 {
4896     private byte[]                  digest;
4897     private AlgorithmIdentifier     algId;
4898
4899     public static DigestInfo getInstance(
4900         ASN1TaggedObject obj,
4901         boolean          explicit)
4902     {
4903         return getInstance(ASN1Sequence.getInstance(obj, explicit));
4904     }
4905
4906     public static DigestInfo getInstance(
4907         Object  obj)
4908     {
4909         if (obj instanceof DigestInfo)
4910         {
4911             return (DigestInfo)obj;
4912         }
4913         else if (obj instanceof ASN1Sequence)
4914         {
4915             return new DigestInfo((ASN1Sequence)obj);
4916         }
4917
4918         throw new IllegalArgumentException("unknown object in factory");
4919     }
4920
4921     public DigestInfo(
4922         AlgorithmIdentifier  algId,
4923         byte[]               digest)
4924     {
4925         this.digest = digest;
4926         this.algId = algId;
4927     }
4928
4929     public DigestInfo(
4930         ASN1Sequence  obj)
4931     {
4932         Enumeration             e = obj.getObjects();
4933
4934         algId = AlgorithmIdentifier.getInstance(e.nextElement());
4935         digest = ((ASN1OctetString)e.nextElement()).getOctets();
4936     }
4937
4938     public AlgorithmIdentifier getAlgorithmId()
4939     {
4940         return algId;
4941     }
4942
4943     public byte[] getDigest()
4944     {
4945         return digest;
4946     }
4947
4948     public DERObject getDERObject()
4949     {
4950         DEREncodableVector  v = new DEREncodableVector();
4951
4952         v.add(algId);
4953         v.add(new DEROctetString(digest));
4954
4955         return new DERSequence(v);
4956     }
4957 }
4958
4959
4960 class DistributionPoint
4961     implements DEREncodable
4962 {
4963     ASN1Sequence  seq = null;
4964
4965     public static DistributionPoint getInstance(
4966         ASN1TaggedObject obj,
4967         boolean          explicit)
4968     {
4969         return getInstance(ASN1Sequence.getInstance(obj, explicit));
4970     }
4971
4972     public static DistributionPoint getInstance(
4973         Object obj)
4974     {
4975         if(obj == null || obj instanceof DistributionPoint) 
4976         {
4977             return (DistributionPoint)obj;
4978         }
4979         
4980         if(obj instanceof ASN1Sequence) 
4981         {
4982             return new DistributionPoint((ASN1Sequence)obj);
4983         }
4984         
4985         throw new IllegalArgumentException("Invalid DistributionPoint: " + obj.getClass().getName());
4986     }
4987
4988     public DistributionPoint(
4989         ASN1Sequence seq)
4990     {
4991         this.seq = seq;
4992     }
4993     
4994     public DistributionPoint(
4995         DistributionPointName   distributionPoint,
4996         ReasonFlags             reasons,
4997         GeneralNames            cRLIssuer)
4998     {
4999         DEREncodableVector  v = new DEREncodableVector();
5000
5001         if (distributionPoint != null)
5002         {
5003             v.add(new DERTaggedObject(0, distributionPoint));
5004         }
5005
5006         if (reasons != null)
5007         {
5008             v.add(new DERTaggedObject(1, reasons));
5009         }
5010
5011         if (cRLIssuer != null)
5012         {
5013             v.add(new DERTaggedObject(2, cRLIssuer));
5014         }
5015
5016         seq = new DERSequence(v);
5017     }
5018
5019     /**
5020      * <pre>
5021      * DistributionPoint ::= SEQUENCE {
5022      *      distributionPoint [0] DistributionPointName OPTIONAL,
5023      *      reasons           [1] ReasonFlags OPTIONAL,
5024      *      cRLIssuer         [2] GeneralNames OPTIONAL
5025      * }
5026      * </pre>
5027      */
5028     public DERObject getDERObject()
5029     {
5030         return seq;
5031     }
5032 }
5033
5034
5035 class DistributionPointName
5036     implements DEREncodable
5037 {
5038     DEREncodable        name;
5039     int                 type;
5040
5041     public static final int FULL_NAME = 0;
5042     public static final int NAME_RELATIVE_TO_CRL_ISSUER = 1;
5043
5044     public DistributionPointName(
5045         int             type,
5046         DEREncodable    name)
5047     {
5048         this.type = type;
5049         this.name = name;
5050     }
5051
5052     /**
5053      * <pre>
5054      * DistributionPointName ::= CHOICE {
5055      *     fullName                 [0] GeneralNames,
5056      *     nameRelativeToCRLIssuer  [1] RelativeDistinguishedName
5057      * }
5058      * </pre>
5059      */
5060     public DERObject getDERObject()
5061     {
5062         return new DERTaggedObject(false, type, name);
5063     }
5064 }
5065
5066
5067
5068 class DSAParameter
5069     implements DEREncodable
5070 {
5071     DERInteger      p, q, g;
5072
5073     public static DSAParameter getInstance(
5074         ASN1TaggedObject obj,
5075         boolean          explicit)
5076     {
5077         return getInstance(ASN1Sequence.getInstance(obj, explicit));
5078     }
5079
5080     public static DSAParameter getInstance(
5081         Object obj)
5082     {
5083         if(obj == null || obj instanceof DSAParameter) 
5084         {
5085             return (DSAParameter)obj;
5086         }
5087         
5088         if(obj instanceof ASN1Sequence) 
5089         {
5090             return new DSAParameter((ASN1Sequence)obj);
5091         }
5092         
5093         throw new IllegalArgumentException("Invalid DSAParameter: " + obj.getClass().getName());
5094     }
5095
5096     public DSAParameter(
5097         BigInteger  p,
5098         BigInteger  q,
5099         BigInteger  g)
5100     {
5101         this.p = new DERInteger(p);
5102         this.q = new DERInteger(q);
5103         this.g = new DERInteger(g);
5104     }
5105
5106     public DSAParameter(
5107         ASN1Sequence  seq)
5108     {
5109         Enumeration     e = seq.getObjects();
5110
5111         p = (DERInteger)e.nextElement();
5112         q = (DERInteger)e.nextElement();
5113         g = (DERInteger)e.nextElement();
5114     }
5115
5116     public BigInteger getP()
5117     {
5118         return p.getPositiveValue();
5119     }
5120
5121     public BigInteger getQ()
5122     {
5123         return q.getPositiveValue();
5124     }
5125
5126     public BigInteger getG()
5127     {
5128         return g.getPositiveValue();
5129     }
5130
5131     public DERObject getDERObject()
5132     {
5133         DEREncodableVector  v = new DEREncodableVector();
5134
5135         v.add(p);
5136         v.add(q);
5137         v.add(g);
5138
5139         return new DERSequence(v);
5140     }
5141 }
5142
5143
5144 /**
5145  * <pre>
5146  * GeneralName ::= CHOICE {
5147  *      otherName                       [0]     OtherName,
5148  *      rfc822Name                      [1]     IA5String,
5149  *      dNSName                         [2]     IA5String,
5150  *      x400Address                     [3]     ORAddress,
5151  *      directoryName                   [4]     Name,
5152  *      ediPartyName                    [5]     EDIPartyName,
5153  *      uniformResourceIdentifier       [6]     IA5String,
5154  *      iPAddress                       [7]     OCTET STRING,
5155  *      registeredID                    [8]     OBJECT IDENTIFIER}
5156  *
5157  * OtherName ::= SEQUENCE {
5158  *      type-id    OBJECT IDENTIFIER,
5159  *      value      [0] EXPLICIT ANY DEFINED BY type-id }
5160  *
5161  * EDIPartyName ::= SEQUENCE {
5162  *      nameAssigner            [0]     DirectoryString OPTIONAL,
5163  *      partyName               [1]     DirectoryString }
5164  * </pre>
5165  */
5166 class GeneralName
5167     implements DEREncodable
5168 {
5169     DEREncodable        obj;
5170     int                 tag;
5171         boolean                 isInsideImplicit = false;               // if we are in an implicitly tagged object
5172
5173     public GeneralName(
5174         X509Name  directoryName)
5175     {
5176         this.obj = directoryName;
5177         this.tag = 4;
5178     }
5179
5180     /**
5181      * When the subjectAltName extension contains an Internet mail address,
5182      * the address MUST be included as an rfc822Name. The format of an
5183      * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
5184      *
5185      * When the subjectAltName extension contains a domain name service
5186      * label, the domain name MUST be stored in the dNSName (an IA5String).
5187      * The name MUST be in the "preferred name syntax," as specified by RFC
5188      * 1034 [RFC 1034].
5189      *
5190      * When the subjectAltName extension contains a URI, the name MUST be
5191      * stored in the uniformResourceIdentifier (an IA5String). The name MUST
5192      * be a non-relative URL, and MUST follow the URL syntax and encoding
5193      * rules specified in [RFC 1738].  The name must include both a scheme
5194      * (e.g., "http" or "ftp") and a scheme-specific-part.  The scheme-
5195      * specific-part must include a fully qualified domain name or IP
5196      * address as the host.
5197      *
5198      * When the subjectAltName extension contains a iPAddress, the address
5199      * MUST be stored in the octet string in "network byte order," as
5200      * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
5201      * each octet is the LSB of the corresponding byte in the network
5202      * address. For IP Version 4, as specified in RFC 791, the octet string
5203      * MUST contain exactly four octets.  For IP Version 6, as specified in
5204      * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
5205      * 1883].
5206      */
5207     public GeneralName(
5208         DERObject name, int tag)
5209     {
5210         this.obj = name;
5211         this.tag = tag;
5212     }
5213
5214     /**
5215      * mark whether or not we are contained inside an implicitly tagged
5216      * object.
5217      * @deprecated
5218      */
5219         public void markInsideImplicit(
5220                 boolean         isInsideImplicit)
5221         {
5222                 this.isInsideImplicit = isInsideImplicit;
5223         }
5224
5225     public DERObject getDERObject()
5226     {
5227         if (obj.getDERObject() instanceof ASN1Sequence)
5228         {
5229             return new DERTaggedObject(true, tag, obj);
5230         }
5231         else
5232         {
5233             return new DERTaggedObject(false, tag, obj);
5234         }
5235     }
5236 }
5237
5238
5239
5240 class GeneralNames
5241     implements DEREncodable
5242 {
5243     ASN1Sequence            seq;
5244     boolean                 isInsideImplicit = false;
5245
5246     public static GeneralNames getInstance(
5247         Object  obj)
5248     {
5249         if (obj == null || obj instanceof GeneralNames)
5250         {
5251             return (GeneralNames)obj;
5252         }
5253
5254         if (obj instanceof ASN1Sequence)
5255         {
5256             return new GeneralNames((ASN1Sequence)obj);
5257         }
5258
5259         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
5260     }
5261
5262     public static GeneralNames getInstance(
5263         ASN1TaggedObject obj,
5264         boolean          explicit)
5265     {
5266         return getInstance(ASN1Sequence.getInstance(obj, explicit));
5267     }
5268
5269     public GeneralNames(
5270         ASN1Sequence  seq)
5271     {
5272         this.seq = seq;
5273     }
5274
5275     /*
5276      * this is a hack! But it will have to do until the ambiguity rules
5277      * get sorted out for implicit/explicit tagging...
5278      * @deprecated
5279      */
5280     public void markInsideImplicit(
5281         boolean    isInsideImplicit)
5282     {
5283         this.isInsideImplicit = isInsideImplicit;
5284     }
5285
5286     /**
5287      * <pre>
5288      * GeneralNames ::= SEQUENCE SIZE {1..MAX} OF GeneralName
5289      * </pre>
5290      */
5291     public DERObject getDERObject()
5292     {
5293         return seq;
5294     }
5295 }
5296
5297
5298 /**
5299  * <pre>
5300  *    id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
5301  *
5302  *    KeyUsage ::= BIT STRING {
5303  *         digitalSignature        (0),
5304  *         nonRepudiation          (1),
5305  *         keyEncipherment         (2),
5306  *         dataEncipherment        (3),
5307  *         keyAgreement            (4),
5308  *         keyCertSign             (5),
5309  *         cRLSign                 (6),
5310  *         encipherOnly            (7),
5311  *         decipherOnly            (8) }
5312  * </pre>
5313  */
5314 class KeyUsage
5315     extends DERBitString
5316 {
5317     public static final int        digitalSignature = (1 << 7); 
5318     public static final int        nonRepudiation   = (1 << 6);
5319     public static final int        keyEncipherment  = (1 << 5);
5320     public static final int        dataEncipherment = (1 << 4);
5321     public static final int        keyAgreement     = (1 << 3);
5322     public static final int        keyCertSign      = (1 << 2);
5323     public static final int        cRLSign          = (1 << 1);
5324     public static final int        encipherOnly     = (1 << 0);
5325     public static final int        decipherOnly     = (1 << 15);
5326
5327     /**
5328      * Basic constructor.
5329      * 
5330      * @param usage - the bitwise OR of the Key Usage flags giving the
5331      * allowed uses for the key.
5332      * e.g. (X509KeyUsage.keyEncipherment | X509KeyUsage.dataEncipherment)
5333      */
5334     public KeyUsage(
5335         int usage)
5336     {
5337         super(getBytes(usage), getPadBits(usage));
5338     }
5339
5340     public KeyUsage(
5341         DERBitString usage)
5342     {
5343         super(usage.getBytes(), usage.getPadBits());
5344     }
5345
5346     public String toString()
5347     {
5348         return "KeyUsage: 0x" + Integer.toHexString(data[0] & 0xff);
5349     }
5350 }
5351
5352
5353 class ReasonFlags
5354     extends DERBitString
5355 {
5356     public static final int UNUSED                  = (1 << 7);
5357     public static final int KEY_COMPROMISE          = (1 << 6);
5358     public static final int CA_COMPROMISE           = (1 << 5);
5359     public static final int AFFILIATION_CHANGED     = (1 << 4);
5360     public static final int SUPERSEDED              = (1 << 3);
5361     public static final int CESSATION_OF_OPERATION  = (1 << 2);
5362     public static final int CERTIFICATE_HOLD        = (1 << 1);
5363     public static final int PRIVILEGE_WITHDRAWN     = (1 << 0);
5364     public static final int AA_COMPROMISE           = (1 << 15);
5365
5366     /**
5367      * <pre>
5368      * ReasonFlags ::= BIT STRING {
5369      *    unused(0),
5370      *    keyCompromise(1),
5371      *    cACompromise(2),
5372      *    affiliationChanged(3),
5373      *    superseded(4),
5374      *    cessationOfOperation(5),
5375      *    certficateHold(6)
5376      * }
5377      * </pre>
5378      * @param reasons - the bitwise OR of the Key Reason flags giving the
5379      * allowed uses for the key.
5380      */
5381     public ReasonFlags(
5382         int reasons)
5383     {
5384         super(getBytes(reasons), getPadBits(reasons));
5385     }
5386
5387     public ReasonFlags(
5388         DERBitString reasons)
5389     {
5390         super(reasons.getBytes(), reasons.getPadBits());
5391     }
5392 }
5393
5394
5395
5396 class RSAPublicKeyStructure
5397     implements DEREncodable
5398 {
5399     private BigInteger  modulus;
5400     private BigInteger  publicExponent;
5401
5402     public static RSAPublicKeyStructure getInstance(
5403         ASN1TaggedObject obj,
5404         boolean          explicit)
5405     {
5406         return getInstance(ASN1Sequence.getInstance(obj, explicit));
5407     }
5408
5409     public static RSAPublicKeyStructure getInstance(
5410         Object obj)
5411     {
5412         if(obj == null || obj instanceof RSAPublicKeyStructure) 
5413         {
5414             return (RSAPublicKeyStructure)obj;
5415         }
5416         
5417         if(obj instanceof ASN1Sequence) 
5418         {
5419             return new RSAPublicKeyStructure((ASN1Sequence)obj);
5420         }
5421         
5422         throw new IllegalArgumentException("Invalid RSAPublicKeyStructure: " + obj.getClass().getName());
5423     }
5424     
5425     public RSAPublicKeyStructure(
5426         BigInteger  modulus,
5427         BigInteger  publicExponent)
5428     {
5429         this.modulus = modulus;
5430         this.publicExponent = publicExponent;
5431     }
5432
5433     public RSAPublicKeyStructure(
5434         ASN1Sequence  seq)
5435     {
5436         Enumeration e = seq.getObjects();
5437
5438         modulus = ((DERInteger)e.nextElement()).getValue();
5439         publicExponent = ((DERInteger)e.nextElement()).getValue();
5440     }
5441
5442     public BigInteger getModulus()
5443     {
5444         return modulus;
5445     }
5446
5447     public BigInteger getPublicExponent()
5448     {
5449         return publicExponent;
5450     }
5451
5452     /**
5453      * This outputs the key in PKCS1v2 format.
5454      * <pre>
5455      *      RSAPublicKey ::= SEQUENCE {
5456      *                          modulus INTEGER, -- n
5457      *                          publicExponent INTEGER, -- e
5458      *                      }
5459      * </pre>
5460      * <p>
5461      */
5462     public DERObject getDERObject()
5463     {
5464         DERConstructedSequence  seq = new DERConstructedSequence();
5465
5466         seq.addObject(new DERInteger(getModulus()));
5467         seq.addObject(new DERInteger(getPublicExponent()));
5468
5469         return seq;
5470     }
5471 }
5472
5473
5474 /**
5475  * <pre>
5476  * SubjectKeyIdentifier::= OCTET STRING
5477  * </pre>
5478  */
5479 class SubjectKeyIdentifier
5480     implements DEREncodable
5481 {
5482         private byte[] keyidentifier;
5483
5484     public static SubjectKeyIdentifier getInstance(
5485         ASN1TaggedObject obj,
5486         boolean          explicit)
5487     {
5488         return getInstance(ASN1OctetString.getInstance(obj, explicit));
5489     }
5490
5491     public static SubjectKeyIdentifier getInstance(
5492         Object obj)
5493     {
5494         if(obj == null || obj instanceof SubjectKeyIdentifier) 
5495         {
5496             return (SubjectKeyIdentifier)obj;
5497         }
5498         
5499         if(obj instanceof SubjectPublicKeyInfo) 
5500         {
5501             return new SubjectKeyIdentifier((SubjectPublicKeyInfo)obj);
5502         }
5503         
5504         if(obj instanceof ASN1OctetString) 
5505         {
5506             return new SubjectKeyIdentifier((ASN1OctetString)obj);
5507         }
5508         
5509         throw new IllegalArgumentException("Invalid SubjectKeyIdentifier: " + obj.getClass().getName());
5510     }
5511         
5512     public SubjectKeyIdentifier(
5513         byte[] keyid)
5514     {
5515         this.keyidentifier=keyid;
5516     }
5517
5518     public SubjectKeyIdentifier(
5519         ASN1OctetString  keyid)
5520     {
5521                 this.keyidentifier=keyid.getOctets();
5522
5523     }
5524
5525         /**
5526          *
5527          * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
5528          * from SubjectPublicKeyInfo as defined in RFC2459.
5529          *
5530          **/
5531         public SubjectKeyIdentifier(
5532                 SubjectPublicKeyInfo    spki)
5533         {
5534                 Digest  digest = new SHA1Digest();
5535                 byte[]  resBuf = new byte[digest.getDigestSize()];
5536
5537                 byte[] bytes = spki.getPublicKeyData().getBytes();
5538                 digest.update(bytes, 0, bytes.length);
5539                 digest.doFinal(resBuf, 0);
5540                 this.keyidentifier=resBuf;
5541         }
5542
5543     public byte[] getKeyIdentifier()
5544     {
5545         return keyidentifier;
5546     }
5547
5548      /**
5549      * <pre>
5550      * SubjectKeyIdentifier := OCTET STRING
5551      * </pre>
5552      */
5553     public DERObject getDERObject()
5554     {
5555         return new DEROctetString(keyidentifier);
5556     }
5557 }
5558
5559
5560
5561 /**
5562  * The object that contains the public key stored in a certficate.
5563  * <p>
5564  * The getEncoded() method in the public keys in the JCE produces a DER
5565  * encoded one of these.
5566  */
5567 class SubjectPublicKeyInfo
5568     implements DEREncodable
5569 {
5570     private AlgorithmIdentifier     algId;
5571     private DERBitString            keyData;
5572
5573     public static SubjectPublicKeyInfo getInstance(
5574         ASN1TaggedObject obj,
5575         boolean          explicit)
5576     {
5577         return getInstance(ASN1Sequence.getInstance(obj, explicit));
5578     }
5579
5580     public static SubjectPublicKeyInfo getInstance(
5581         Object  obj)
5582     {
5583         if (obj instanceof SubjectPublicKeyInfo)
5584         {
5585             return (SubjectPublicKeyInfo)obj;
5586         }
5587         else if (obj instanceof ASN1Sequence)
5588         {
5589             return new SubjectPublicKeyInfo((ASN1Sequence)obj);
5590         }
5591
5592         throw new IllegalArgumentException("unknown object in factory");
5593     }
5594
5595     public SubjectPublicKeyInfo(
5596         AlgorithmIdentifier algId,
5597         DEREncodable        publicKey)
5598     {
5599         this.keyData = new DERBitString(publicKey);
5600         this.algId = algId;
5601     }
5602
5603     public SubjectPublicKeyInfo(
5604         AlgorithmIdentifier algId,
5605         byte[]              publicKey)
5606     {
5607         this.keyData = new DERBitString(publicKey);
5608         this.algId = algId;
5609     }
5610
5611     public SubjectPublicKeyInfo(
5612         ASN1Sequence  seq)
5613     {
5614         Enumeration         e = seq.getObjects();
5615
5616         this.algId = AlgorithmIdentifier.getInstance(e.nextElement());
5617         this.keyData = (DERBitString)e.nextElement();
5618     }
5619
5620     public AlgorithmIdentifier getAlgorithmId()
5621     {
5622         return algId;
5623     }
5624
5625     /**
5626      * for when the public key is an encoded object - if the bitstring
5627      * can't be decoded this routine throws an IOException.
5628      *
5629      * @exception IOException - if the bit string doesn't represent a DER
5630      * encoded object.
5631      */
5632     public DERObject getPublicKey()
5633         throws IOException
5634     {
5635         ByteArrayInputStream    bIn = new ByteArrayInputStream(keyData.getBytes());
5636         DERInputStream          dIn = new DERInputStream(bIn);
5637
5638         return dIn.readObject();
5639     }
5640
5641     /**
5642      * for when the public key is raw bits...
5643      */
5644     public DERBitString getPublicKeyData()
5645     {
5646         return keyData;
5647     }
5648
5649     /**
5650      * <pre>
5651      * SubjectPublicKeyInfo ::= SEQUENCE {
5652      *                          algorithm AlgorithmIdentifier,
5653      *                          publicKey BIT STRING }
5654      * </pre>
5655      */
5656     public DERObject getDERObject()
5657     {
5658         DERConstructedSequence  seq = new DERConstructedSequence();
5659
5660         seq.addObject(algId);
5661         seq.addObject(keyData);
5662
5663         return seq;
5664     }
5665 }
5666
5667
5668 /**
5669  * <pre>
5670  * TBSCertificate ::= SEQUENCE {
5671  *      version          [ 0 ]  Version DEFAULT v1(0),
5672  *      serialNumber            CertificateSerialNumber,
5673  *      signature               AlgorithmIdentifier,
5674  *      issuer                  Name,
5675  *      validity                Validity,
5676  *      subject                 Name,
5677  *      subjectPublicKeyInfo    SubjectPublicKeyInfo,
5678  *      issuerUniqueID    [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
5679  *      subjectUniqueID   [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
5680  *      extensions        [ 3 ] Extensions OPTIONAL
5681  *      }
5682  * </pre>
5683  * <p>
5684  * Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
5685  * will parse them, but you really shouldn't be creating new ones.
5686  */
5687 class TBSCertificateStructure
5688     implements DEREncodable, X509ObjectIdentifiers, PKCSObjectIdentifiers
5689 {
5690     ASN1Sequence            seq;
5691
5692     DERInteger              version;
5693     DERInteger              serialNumber;
5694     AlgorithmIdentifier     signature;
5695     X509Name                issuer;
5696     Time                    startDate, endDate;
5697     X509Name                subject;
5698     SubjectPublicKeyInfo    subjectPublicKeyInfo;
5699     DERBitString            issuerUniqueId;
5700     DERBitString            subjectUniqueId;
5701     X509Extensions          extensions;
5702
5703     public static TBSCertificateStructure getInstance(
5704         ASN1TaggedObject obj,
5705         boolean          explicit)
5706     {
5707         return getInstance(ASN1Sequence.getInstance(obj, explicit));
5708     }
5709
5710     public static TBSCertificateStructure getInstance(
5711         Object  obj)
5712     {
5713         if (obj instanceof TBSCertificateStructure)
5714         {
5715             return (TBSCertificateStructure)obj;
5716         }
5717         else if (obj instanceof ASN1Sequence)
5718         {
5719             return new TBSCertificateStructure((ASN1Sequence)obj);
5720         }
5721
5722         throw new IllegalArgumentException("unknown object in factory");
5723     }
5724
5725     public TBSCertificateStructure(
5726         ASN1Sequence  seq)
5727     {
5728         int         seqStart = 0;
5729
5730         this.seq = seq;
5731
5732         //
5733         // some certficates don't include a version number - we assume v1
5734         //
5735         if (seq.getObjectAt(0) instanceof DERTaggedObject)
5736         {
5737             version = DERInteger.getInstance(seq.getObjectAt(0));
5738         }
5739         else
5740         {
5741             seqStart = -1;          // field 0 is missing!
5742             version = new DERInteger(0);
5743         }
5744
5745         serialNumber = DERInteger.getInstance(seq.getObjectAt(seqStart + 1));
5746
5747         signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqStart + 2));
5748         issuer = X509Name.getInstance(seq.getObjectAt(seqStart + 3));
5749
5750         //
5751         // before and after dates
5752         //
5753         ASN1Sequence  dates = (ASN1Sequence)seq.getObjectAt(seqStart + 4);
5754
5755         startDate = Time.getInstance(dates.getObjectAt(0));
5756         endDate = Time.getInstance(dates.getObjectAt(1));
5757
5758         subject = X509Name.getInstance(seq.getObjectAt(seqStart + 5));
5759
5760         //
5761         // public key info.
5762         //
5763         subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(seqStart + 6));
5764
5765         for (int extras = seq.size() - (seqStart + 6) - 1; extras > 0; extras--)
5766         {
5767             DERTaggedObject extra = (DERTaggedObject)seq.getObjectAt(seqStart + 6 + extras);
5768
5769             switch (extra.getTagNo())
5770             {
5771             case 1:
5772                 issuerUniqueId = DERBitString.getInstance(extra);
5773                 break;
5774             case 2:
5775                 subjectUniqueId = DERBitString.getInstance(extra);
5776                 break;
5777             case 3:
5778                 extensions = X509Extensions.getInstance(extra);
5779             }
5780         }
5781     }
5782
5783     public int getVersion()
5784     {
5785         return version.getValue().intValue() + 1;
5786     }
5787
5788     public DERInteger getVersionNumber()
5789     {
5790         return version;
5791     }
5792
5793     public DERInteger getSerialNumber()
5794     {
5795         return serialNumber;
5796     }
5797
5798     public AlgorithmIdentifier getSignature()
5799     {
5800         return signature;
5801     }
5802
5803     public X509Name getIssuer()
5804     {
5805         return issuer;
5806     }
5807
5808     public Time getStartDate()
5809     {
5810         return startDate;
5811     }
5812
5813     public Time getEndDate()
5814     {
5815         return endDate;
5816     }
5817
5818     public X509Name getSubject()
5819     {
5820         return subject;
5821     }
5822
5823     public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
5824     {
5825         return subjectPublicKeyInfo;
5826     }
5827
5828     public DERBitString getIssuerUniqueId()
5829     {
5830         return issuerUniqueId;
5831     }
5832
5833     public DERBitString getSubjectUniqueId()
5834     {
5835         return subjectUniqueId;
5836     }
5837
5838     public X509Extensions getExtensions()
5839     {
5840         return extensions;
5841     }
5842
5843     public DERObject getDERObject()
5844     {
5845         return seq;
5846     }
5847 }
5848
5849
5850
5851 /**
5852  * PKIX RFC-2459
5853  *
5854  * <pre>
5855  * TBSCertList  ::=  SEQUENCE  {
5856  *      version                 Version OPTIONAL,
5857  *                                   -- if present, shall be v2
5858  *      signature               AlgorithmIdentifier,
5859  *      issuer                  Name,
5860  *      thisUpdate              Time,
5861  *      nextUpdate              Time OPTIONAL,
5862  *      revokedCertificates     SEQUENCE OF SEQUENCE  {
5863  *           userCertificate         CertificateSerialNumber,
5864  *           revocationDate          Time,
5865  *           crlEntryExtensions      Extensions OPTIONAL
5866  *                                         -- if present, shall be v2
5867  *                                }  OPTIONAL,
5868  *      crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
5869  *                                         -- if present, shall be v2
5870  *                                }
5871  * </pre>
5872  */
5873
5874 class TBSCertList
5875     implements DEREncodable
5876 {
5877     class CRLEntry
5878         implements DEREncodable
5879     {
5880         DERConstructedSequence  seq;
5881
5882         DERInteger          userCertificate;
5883         Time                revocationDate;
5884         X509Extensions      crlEntryExtensions;
5885
5886         public CRLEntry(
5887             DERConstructedSequence  seq)
5888         {
5889             this.seq = seq;
5890
5891             userCertificate = (DERInteger)seq.getObjectAt(0);
5892             revocationDate = Time.getInstance(seq.getObjectAt(1));
5893             if (seq.getSize() == 3)
5894             {
5895                 crlEntryExtensions = X509Extensions.getInstance(seq.getObjectAt(2));
5896             }
5897         }
5898
5899         public DERInteger getUserCertificate()
5900         {
5901             return userCertificate;
5902         }
5903
5904         public Time getRevocationDate()
5905         {
5906             return revocationDate;
5907         }
5908
5909         public X509Extensions getExtensions()
5910         {
5911             return crlEntryExtensions;
5912         }
5913
5914         public DERObject getDERObject()
5915         {
5916             return seq;
5917         }
5918     }
5919
5920     ASN1Sequence     seq;
5921
5922     DERInteger              version;
5923     AlgorithmIdentifier     signature;
5924     X509Name                issuer;
5925     Time                    thisUpdate;
5926     Time                    nextUpdate;
5927     CRLEntry[]              revokedCertificates;
5928     X509Extensions          crlExtensions;
5929
5930     public static TBSCertList getInstance(
5931         ASN1TaggedObject obj,
5932         boolean          explicit)
5933     {
5934         return getInstance(ASN1Sequence.getInstance(obj, explicit));
5935     }
5936
5937     public static TBSCertList getInstance(
5938         Object  obj)
5939     {
5940         if (obj instanceof TBSCertList)
5941         {
5942             return (TBSCertList)obj;
5943         }
5944         else if (obj instanceof ASN1Sequence)
5945         {
5946             return new TBSCertList((ASN1Sequence)obj);
5947         }
5948
5949         throw new IllegalArgumentException("unknown object in factory");
5950     }
5951
5952     public TBSCertList(
5953         ASN1Sequence  seq)
5954     {
5955         int seqPos = 0;
5956
5957         this.seq = seq;
5958
5959         if (seq.getObjectAt(seqPos) instanceof DERInteger)
5960         {
5961             version = (DERInteger)seq.getObjectAt(seqPos++);
5962         }
5963         else
5964         {
5965             version = new DERInteger(0);
5966         }
5967
5968         signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqPos++));
5969         issuer = X509Name.getInstance(seq.getObjectAt(seqPos++));
5970         thisUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
5971
5972         if (seqPos < seq.size()
5973             && (seq.getObjectAt(seqPos) instanceof DERUTCTime
5974                || seq.getObjectAt(seqPos) instanceof DERGeneralizedTime
5975                || seq.getObjectAt(seqPos) instanceof Time))
5976         {
5977             nextUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
5978         }
5979
5980         if (seqPos < seq.size()
5981             && !(seq.getObjectAt(seqPos) instanceof DERTaggedObject))
5982         {
5983             DERConstructedSequence certs = (DERConstructedSequence)seq.getObjectAt(seqPos++);
5984             revokedCertificates = new CRLEntry[certs.getSize()];
5985
5986             for ( int i = 0; i < revokedCertificates.length; i++)
5987             {
5988                 revokedCertificates[i] = new CRLEntry((DERConstructedSequence)certs.getObjectAt(i));
5989             }
5990         }
5991
5992         if (seqPos < seq.size()
5993             && seq.getObjectAt(seqPos) instanceof DERTaggedObject)
5994         {
5995             crlExtensions = X509Extensions.getInstance(seq.getObjectAt(seqPos++));
5996         }
5997     }
5998
5999     public int getVersion()
6000     {
6001         return version.getValue().intValue() + 1;
6002     }
6003
6004     public DERInteger getVersionNumber()
6005     {
6006         return version;
6007     }
6008
6009     public AlgorithmIdentifier getSignature()
6010     {
6011         return signature;
6012     }
6013
6014     public X509Name getIssuer()
6015     {
6016         return issuer;
6017     }
6018
6019     public Time getThisUpdate()
6020     {
6021         return thisUpdate;
6022     }
6023
6024     public Time getNextUpdate()
6025     {
6026         return nextUpdate;
6027     }
6028
6029     public CRLEntry[] getRevokedCertificates()
6030     {
6031         return revokedCertificates;
6032     }
6033
6034     public X509Extensions getExtensions()
6035     {
6036         return crlExtensions;
6037     }
6038
6039     public DERObject getDERObject()
6040     {
6041         return seq;
6042     }
6043 }
6044
6045
6046
6047 class Time
6048     implements DEREncodable
6049 {
6050     DERObject   time;
6051
6052     public static Time getInstance(
6053         ASN1TaggedObject obj,
6054         boolean          explicit)
6055     {
6056         return getInstance(obj.getObject());
6057     }
6058
6059     public Time(
6060         DERObject   time)
6061     {
6062         if (!(time instanceof DERUTCTime)
6063             && !(time instanceof DERGeneralizedTime))
6064         {
6065             throw new IllegalArgumentException("unknown object passed to Time");
6066         }
6067
6068         this.time = time; 
6069     }
6070
6071     /**
6072      * creates a time object from a given date - if the date is between 1950
6073      * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
6074      * is used.
6075      */
6076     public Time(
6077         Date    date)
6078     {
6079         SimpleTimeZone      tz = new SimpleTimeZone(0, "Z");
6080         SimpleDateFormat    dateF = new SimpleDateFormat("yyyyMMddHHmmss");
6081
6082         dateF.setTimeZone(tz);
6083
6084         String  d = dateF.format(date) + "Z";
6085         int     year = Integer.parseInt(d.substring(0, 4));
6086
6087         if (year < 1950 || year > 2049)
6088         {
6089             time = new DERGeneralizedTime(d);
6090         }
6091         else
6092         {
6093             time = new DERUTCTime(d.substring(2));
6094         }
6095     }
6096
6097     public static Time getInstance(
6098         Object  obj)
6099     {
6100         if (obj instanceof Time)
6101         {
6102             return (Time)obj;
6103         }
6104         else if (obj instanceof DERUTCTime)
6105         {
6106             return new Time((DERUTCTime)obj);
6107         }
6108         else if (obj instanceof DERGeneralizedTime)
6109         {
6110             return new Time((DERGeneralizedTime)obj);
6111         }
6112
6113         throw new IllegalArgumentException("unknown object in factory");
6114     }
6115
6116     public String getTime()
6117     {
6118         if (time instanceof DERUTCTime)
6119         {
6120             return ((DERUTCTime)time).getAdjustedTime();
6121         }
6122         else
6123         {
6124             return ((DERGeneralizedTime)time).getTime();
6125         }
6126     }
6127
6128     public Date getDate()
6129     {
6130         SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
6131
6132         return dateF.parse(this.getTime(), new ParsePosition(0));
6133     }
6134
6135     /**
6136      * <pre>
6137      * Time ::= CHOICE {
6138      *             utcTime        UTCTime,
6139      *             generalTime    GeneralizedTime }
6140      * </pre>
6141      */
6142     public DERObject getDERObject()
6143     {
6144         return time;
6145     }
6146 }
6147
6148
6149 /**
6150  * Generator for Version 1 TBSCertificateStructures.
6151  * <pre>
6152  * TBSCertificate ::= SEQUENCE {
6153  *      version          [ 0 ]  Version DEFAULT v1(0),
6154  *      serialNumber            CertificateSerialNumber,
6155  *      signature               AlgorithmIdentifier,
6156  *      issuer                  Name,
6157  *      validity                Validity,
6158  *      subject                 Name,
6159  *      subjectPublicKeyInfo    SubjectPublicKeyInfo,
6160  *      }
6161  * </pre>
6162  *
6163  */
6164 class V1TBSCertificateGenerator
6165 {
6166     DERTaggedObject         version = new DERTaggedObject(0, new DERInteger(0));
6167
6168     DERInteger              serialNumber;
6169     AlgorithmIdentifier     signature;
6170     X509Name                issuer;
6171     Time                    startDate, endDate;
6172     X509Name                subject;
6173     SubjectPublicKeyInfo    subjectPublicKeyInfo;
6174
6175     public V1TBSCertificateGenerator()
6176     {
6177     }
6178
6179     public void setSerialNumber(
6180         DERInteger  serialNumber)
6181     {
6182         this.serialNumber = serialNumber;
6183     }
6184
6185     public void setSignature(
6186         AlgorithmIdentifier    signature)
6187     {
6188         this.signature = signature;
6189     }
6190
6191     public void setIssuer(
6192         X509Name    issuer)
6193     {
6194         this.issuer = issuer;
6195     }
6196
6197     public void setStartDate(
6198         Time startDate)
6199     {
6200         this.startDate = startDate;
6201     }
6202
6203     public void setStartDate(
6204         DERUTCTime startDate)
6205     {
6206         this.startDate = new Time(startDate);
6207     }
6208
6209     public void setEndDate(
6210         Time endDate)
6211     {
6212         this.endDate = endDate;
6213     }
6214
6215     public void setEndDate(
6216         DERUTCTime endDate)
6217     {
6218         this.endDate = new Time(endDate);
6219     }
6220
6221     public void setSubject(
6222         X509Name    subject)
6223     {
6224         this.subject = subject;
6225     }
6226
6227     public void setSubjectPublicKeyInfo(
6228         SubjectPublicKeyInfo    pubKeyInfo)
6229     {
6230         this.subjectPublicKeyInfo = pubKeyInfo;
6231     }
6232
6233     public TBSCertificateStructure generateTBSCertificate()
6234     {
6235         if ((serialNumber == null) || (signature == null)
6236             || (issuer == null) || (startDate == null) || (endDate == null)
6237             || (subject == null) || (subjectPublicKeyInfo == null))
6238         {
6239             throw new IllegalStateException("not all mandatory fields set in V1 TBScertificate generator");
6240         }
6241
6242         DERConstructedSequence  seq = new DERConstructedSequence();
6243
6244         seq.addObject(version);
6245         seq.addObject(serialNumber);
6246         seq.addObject(signature);
6247         seq.addObject(issuer);
6248
6249         //
6250         // before and after dates
6251         //
6252         DERConstructedSequence  validity = new DERConstructedSequence();
6253
6254         validity.addObject(startDate);
6255         validity.addObject(endDate);
6256
6257         seq.addObject(validity);
6258
6259         seq.addObject(subject);
6260
6261         seq.addObject(subjectPublicKeyInfo);
6262
6263         return new TBSCertificateStructure(seq);
6264     }
6265 }
6266
6267
6268
6269 /**
6270  * Generator for Version 2 TBSCertList structures.
6271  * <pre>
6272  *  TBSCertList  ::=  SEQUENCE  {
6273  *       version                 Version OPTIONAL,
6274  *                                    -- if present, shall be v2
6275  *       signature               AlgorithmIdentifier,
6276  *       issuer                  Name,
6277  *       thisUpdate              Time,
6278  *       nextUpdate              Time OPTIONAL,
6279  *       revokedCertificates     SEQUENCE OF SEQUENCE  {
6280  *            userCertificate         CertificateSerialNumber,
6281  *            revocationDate          Time,
6282  *            crlEntryExtensions      Extensions OPTIONAL
6283  *                                          -- if present, shall be v2
6284  *                                 }  OPTIONAL,
6285  *       crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
6286  *                                          -- if present, shall be v2
6287  *                                 }
6288  * </pre>
6289  *
6290  * <b>Note: This class may be subject to change</b>
6291  */
6292 class V2TBSCertListGenerator
6293 {
6294     DERInteger version = new DERInteger(1);
6295
6296     AlgorithmIdentifier     signature;
6297     X509Name                issuer;
6298     Time                    thisUpdate, nextUpdate=null;
6299     X509Extensions          extensions=null;
6300     private Vector          crlentries=null;
6301
6302     public V2TBSCertListGenerator()
6303     {
6304     }
6305
6306
6307     public void setSignature(
6308         AlgorithmIdentifier    signature)
6309     {
6310         this.signature = signature;
6311     }
6312
6313     public void setIssuer(
6314         X509Name    issuer)
6315     {
6316         this.issuer = issuer;
6317     }
6318
6319     public void setThisUpdate(
6320         DERUTCTime thisUpdate)
6321     {
6322         this.thisUpdate = new Time(thisUpdate);
6323     }
6324
6325     public void setNextUpdate(
6326         DERUTCTime nextUpdate)
6327     {
6328         this.nextUpdate = new Time(nextUpdate);
6329     }
6330
6331     public void setThisUpdate(
6332         Time thisUpdate)
6333     {
6334         this.thisUpdate = thisUpdate;
6335     }
6336
6337     public void setNextUpdate(
6338         Time nextUpdate)
6339     {
6340         this.nextUpdate = nextUpdate;
6341     }
6342
6343     public void addCRLEntry(
6344         DERConstructedSequence crlEntry)
6345     {
6346         if (crlentries == null)
6347             crlentries = new Vector();
6348         crlentries.addElement(crlEntry);
6349     }
6350
6351     public void addCRLEntry(DERInteger userCertificate, DERUTCTime revocationDate, int reason)
6352     {
6353         addCRLEntry(userCertificate, new Time(revocationDate), reason);
6354     }
6355
6356     public void addCRLEntry(DERInteger userCertificate, Time revocationDate, int reason)
6357     {
6358         DERConstructedSequence seq = new DERConstructedSequence();
6359         seq.addObject(userCertificate);
6360         seq.addObject(revocationDate);
6361         
6362         if (reason != 0)
6363         {
6364             CRLReason rf = new CRLReason(reason);
6365             ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
6366             DEROutputStream         dOut = new DEROutputStream(bOut);
6367             try
6368             {
6369                 dOut.writeObject(rf);
6370             }
6371             catch (IOException e)
6372             {
6373                 throw new IllegalArgumentException("error encoding value: " + e);
6374             }
6375             byte[] value = bOut.toByteArray();
6376             DERConstructedSequence eseq = new DERConstructedSequence();
6377             DERConstructedSequence eseq1 = new DERConstructedSequence();
6378             eseq1.addObject(X509Extensions.ReasonCode);
6379             eseq1.addObject(new DEROctetString(value));
6380             eseq.addObject(eseq1);
6381             X509Extensions ex = new X509Extensions(eseq);
6382             seq.addObject(ex);
6383         }
6384         if (crlentries == null)
6385             crlentries = new Vector();
6386         crlentries.addElement(seq);
6387     }
6388
6389     public void setExtensions(
6390         X509Extensions    extensions)
6391     {
6392         this.extensions = extensions;
6393     }
6394
6395     public TBSCertList generateTBSCertList()
6396     {
6397         if ((signature == null) || (issuer == null) || (thisUpdate == null))
6398         {
6399             throw new IllegalStateException("Not all mandatory fields set in V2 TBSCertList generator.");
6400         }
6401
6402         DERConstructedSequence  seq = new DERConstructedSequence();
6403
6404         seq.addObject(version);
6405         seq.addObject(signature);
6406         seq.addObject(issuer);
6407
6408         seq.addObject(thisUpdate);
6409         if (nextUpdate != null)
6410             seq.addObject(nextUpdate);
6411
6412         // Add CRLEntries if they exist
6413         if (crlentries != null) {
6414             DERConstructedSequence certseq = new DERConstructedSequence();
6415             Enumeration it = crlentries.elements();
6416             while( it.hasMoreElements() ) {
6417                 certseq.addObject((DERConstructedSequence)it.nextElement());
6418             }
6419             seq.addObject(certseq);
6420         }
6421
6422         if (extensions != null)
6423         {
6424             seq.addObject(new DERTaggedObject(0, extensions));
6425         }
6426
6427         return new TBSCertList(seq);
6428     }
6429 }
6430
6431
6432 /**
6433  * Generator for Version 3 TBSCertificateStructures.
6434  * <pre>
6435  * TBSCertificate ::= SEQUENCE {
6436  *      version          [ 0 ]  Version DEFAULT v1(0),
6437  *      serialNumber            CertificateSerialNumber,
6438  *      signature               AlgorithmIdentifier,
6439  *      issuer                  Name,
6440  *      validity                Validity,
6441  *      subject                 Name,
6442  *      subjectPublicKeyInfo    SubjectPublicKeyInfo,
6443  *      issuerUniqueID    [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
6444  *      subjectUniqueID   [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
6445  *      extensions        [ 3 ] Extensions OPTIONAL
6446  *      }
6447  * </pre>
6448  *
6449  */
6450 class V3TBSCertificateGenerator
6451 {
6452     DERTaggedObject         version = new DERTaggedObject(0, new DERInteger(2));
6453
6454     DERInteger              serialNumber;
6455     AlgorithmIdentifier     signature;
6456     X509Name                issuer;
6457     Time                    startDate, endDate;
6458     X509Name                subject;
6459     SubjectPublicKeyInfo    subjectPublicKeyInfo;
6460     X509Extensions          extensions;
6461
6462     public V3TBSCertificateGenerator()
6463     {
6464     }
6465
6466     public void setSerialNumber(
6467         DERInteger  serialNumber)
6468     {
6469         this.serialNumber = serialNumber;
6470     }
6471
6472     public void setSignature(
6473         AlgorithmIdentifier    signature)
6474     {
6475         this.signature = signature;
6476     }
6477
6478     public void setIssuer(
6479         X509Name    issuer)
6480     {
6481         this.issuer = issuer;
6482     }
6483
6484     public void setStartDate(
6485         DERUTCTime startDate)
6486     {
6487         this.startDate = new Time(startDate);
6488     }
6489
6490     public void setStartDate(
6491         Time startDate)
6492     {
6493         this.startDate = startDate;
6494     }
6495
6496     public void setEndDate(
6497         DERUTCTime endDate)
6498     {
6499         this.endDate = new Time(endDate);
6500     }
6501
6502     public void setEndDate(
6503         Time endDate)
6504     {
6505         this.endDate = endDate;
6506     }
6507
6508     public void setSubject(
6509         X509Name    subject)
6510     {
6511         this.subject = subject;
6512     }
6513
6514     public void setSubjectPublicKeyInfo(
6515         SubjectPublicKeyInfo    pubKeyInfo)
6516     {
6517         this.subjectPublicKeyInfo = pubKeyInfo;
6518     }
6519
6520     public void setExtensions(
6521         X509Extensions    extensions)
6522     {
6523         this.extensions = extensions;
6524     }
6525
6526     public TBSCertificateStructure generateTBSCertificate()
6527     {
6528         if ((serialNumber == null) || (signature == null)
6529             || (issuer == null) || (startDate == null) || (endDate == null)
6530             || (subject == null) || (subjectPublicKeyInfo == null))
6531         {
6532             throw new IllegalStateException("not all mandatory fields set in V3 TBScertificate generator");
6533         }
6534
6535         DERConstructedSequence  seq = new DERConstructedSequence();
6536
6537         seq.addObject(version);
6538         seq.addObject(serialNumber);
6539         seq.addObject(signature);
6540         seq.addObject(issuer);
6541
6542         //
6543         // before and after dates
6544         //
6545         DERConstructedSequence  validity = new DERConstructedSequence();
6546
6547         validity.addObject(startDate);
6548         validity.addObject(endDate);
6549
6550         seq.addObject(validity);
6551
6552         seq.addObject(subject);
6553
6554         seq.addObject(subjectPublicKeyInfo);
6555
6556         if (extensions != null)
6557         {
6558             seq.addObject(new DERTaggedObject(3, extensions));
6559         }
6560
6561         return new TBSCertificateStructure(seq);
6562     }
6563 }
6564
6565
6566 /**
6567  * an X509Certificate structure.
6568  * <pre>
6569  *  Certificate ::= SEQUENCE {
6570  *      tbsCertificate          TBSCertificate,
6571  *      signatureAlgorithm      AlgorithmIdentifier,
6572  *      signature               BIT STRING
6573  *  }
6574  * </pre>
6575  */
6576 class X509CertificateStructure
6577     implements DEREncodable, X509ObjectIdentifiers, PKCSObjectIdentifiers
6578 {
6579     ASN1Sequence  seq;
6580     TBSCertificateStructure tbsCert;
6581     AlgorithmIdentifier     sigAlgId;
6582     DERBitString            sig;
6583
6584     public static X509CertificateStructure getInstance(
6585         ASN1TaggedObject obj,
6586         boolean          explicit)
6587     {
6588         return getInstance(ASN1Sequence.getInstance(obj, explicit));
6589     }
6590         
6591     public static X509CertificateStructure getInstance(
6592         Object  obj)
6593     {
6594         if (obj instanceof X509CertificateStructure)
6595         {
6596             return (X509CertificateStructure)obj;
6597         }
6598         else if (obj instanceof ASN1Sequence)
6599         {
6600             return new X509CertificateStructure((ASN1Sequence)obj);
6601         }
6602
6603         throw new IllegalArgumentException("unknown object in factory");
6604     }
6605
6606     public X509CertificateStructure(
6607         ASN1Sequence  seq)
6608     {
6609         this.seq = seq;
6610
6611         //
6612         // correct x509 certficate
6613         //
6614         if (seq.size() == 3)
6615         {
6616             tbsCert = TBSCertificateStructure.getInstance(seq.getObjectAt(0));
6617             sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
6618
6619             sig = (DERBitString)seq.getObjectAt(2);
6620         }
6621     }
6622
6623     public TBSCertificateStructure getTBSCertificate()
6624     {
6625         return tbsCert;
6626     }
6627
6628     public int getVersion()
6629     {
6630         return tbsCert.getVersion();
6631     }
6632
6633     public DERInteger getSerialNumber()
6634     {
6635         return tbsCert.getSerialNumber();
6636     }
6637
6638     public X509Name getIssuer()
6639     {
6640         return tbsCert.getIssuer();
6641     }
6642
6643     public Time getStartDate()
6644     {
6645         return tbsCert.getStartDate();
6646     }
6647
6648     public Time getEndDate()
6649     {
6650         return tbsCert.getEndDate();
6651     }
6652
6653     public X509Name getSubject()
6654     {
6655         return tbsCert.getSubject();
6656     }
6657
6658     public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
6659     {
6660         return tbsCert.getSubjectPublicKeyInfo();
6661     }
6662
6663     public AlgorithmIdentifier getSignatureAlgorithm()
6664     {
6665         return sigAlgId;
6666     }
6667
6668     public DERBitString getSignature()
6669     {
6670         return sig;
6671     }
6672
6673     public DERObject getDERObject()
6674     {
6675         return seq;
6676     }
6677 }
6678
6679
6680 /**
6681  * an object for the elements in the X.509 V3 extension block.
6682  */
6683 class X509Extension
6684 {
6685     boolean             critical;
6686     DEROctetString      value;
6687
6688     public X509Extension(
6689         DERBoolean              critical,
6690         DEROctetString          value)
6691     {
6692         this.critical = critical.isTrue();
6693         this.value = value;
6694     }
6695
6696     public X509Extension(
6697         boolean                 critical,
6698         DEROctetString          value)
6699     {
6700         this.critical = critical;
6701         this.value = value;
6702     }
6703
6704     public boolean isCritical()
6705     {
6706         return critical;
6707     }
6708
6709     public DEROctetString getValue()
6710     {
6711         return value;
6712     }
6713
6714     public int hashCode()
6715     {
6716         if (this.isCritical())
6717         {
6718             return this.getValue().hashCode();
6719         }
6720
6721         
6722         return ~this.getValue().hashCode();
6723     }
6724
6725     public boolean equals(
6726         Object  o)
6727     {
6728         if (o == null || !(o instanceof X509Extension))
6729         {
6730             return false;
6731         }
6732
6733         X509Extension   other = (X509Extension)o;
6734
6735         return other.getValue().equals(this.getValue())
6736             && (other.isCritical() == this.isCritical());
6737     }
6738 }
6739
6740
6741
6742 class X509Extensions
6743     implements DEREncodable
6744 {
6745     /**
6746      * Subject Key Identifier 
6747      */
6748     public static final DERObjectIdentifier SubjectKeyIdentifier = new DERObjectIdentifier("2.5.29.14");
6749
6750     /**
6751      * Key Usage 
6752      */
6753     public static final DERObjectIdentifier KeyUsage = new DERObjectIdentifier("2.5.29.15");
6754
6755     /**
6756      * Private Key Usage Period 
6757      */
6758     public static final DERObjectIdentifier PrivateKeyUsagePeriod = new DERObjectIdentifier("2.5.29.16");
6759
6760     /**
6761      * Subject Alternative Name 
6762      */
6763     public static final DERObjectIdentifier SubjectAlternativeName = new DERObjectIdentifier("2.5.29.17");
6764
6765     /**
6766      * Issuer Alternative Name 
6767      */
6768     public static final DERObjectIdentifier IssuerAlternativeName = new DERObjectIdentifier("2.5.29.18");
6769
6770     /**
6771      * Basic Constraints 
6772      */
6773     public static final DERObjectIdentifier BasicConstraints = new DERObjectIdentifier("2.5.29.19");
6774
6775     /**
6776      * CRL Number 
6777      */
6778     public static final DERObjectIdentifier CRLNumber = new DERObjectIdentifier("2.5.29.20");
6779
6780     /**
6781      * Reason code 
6782      */
6783     public static final DERObjectIdentifier ReasonCode = new DERObjectIdentifier("2.5.29.21");
6784
6785     /**
6786      * Hold Instruction Code 
6787      */
6788     public static final DERObjectIdentifier InstructionCode = new DERObjectIdentifier("2.5.29.23");
6789
6790     /**
6791      * Invalidity Date 
6792      */
6793     public static final DERObjectIdentifier InvalidityDate = new DERObjectIdentifier("2.5.29.24");
6794
6795     /**
6796      * Delta CRL indicator 
6797      */
6798     public static final DERObjectIdentifier DeltaCRLIndicator = new DERObjectIdentifier("2.5.29.27");
6799
6800     /**
6801      * Issuing Distribution Point 
6802      */
6803     public static final DERObjectIdentifier IssuingDistributionPoint = new DERObjectIdentifier("2.5.29.28");
6804
6805     /**
6806      * Certificate Issuer 
6807      */
6808     public static final DERObjectIdentifier CertificateIssuer = new DERObjectIdentifier("2.5.29.29");
6809
6810     /**
6811      * Name Constraints 
6812      */
6813     public static final DERObjectIdentifier NameConstraints = new DERObjectIdentifier("2.5.29.30");
6814
6815     /**
6816      * CRL Distribution Points 
6817      */
6818     public static final DERObjectIdentifier CRLDistributionPoints = new DERObjectIdentifier("2.5.29.31");
6819
6820     /**
6821      * Certificate Policies 
6822      */
6823     public static final DERObjectIdentifier CertificatePolicies = new DERObjectIdentifier("2.5.29.32");
6824
6825     /**
6826      * Policy Mappings 
6827      */
6828     public static final DERObjectIdentifier PolicyMappings = new DERObjectIdentifier("2.5.29.33");
6829
6830     /**
6831      * Authority Key Identifier 
6832      */
6833     public static final DERObjectIdentifier AuthorityKeyIdentifier = new DERObjectIdentifier("2.5.29.35");
6834
6835     /**
6836      * Policy Constraints 
6837      */
6838     public static final DERObjectIdentifier PolicyConstraints = new DERObjectIdentifier("2.5.29.36");
6839
6840     /**
6841      * Extended Key Usage 
6842      */
6843     public static final DERObjectIdentifier ExtendedKeyUsage = new DERObjectIdentifier("2.5.29.37");
6844
6845     private Hashtable               extensions = new Hashtable();
6846     private Vector                  ordering = new Vector();
6847
6848     public static X509Extensions getInstance(
6849         ASN1TaggedObject obj,
6850         boolean          explicit)
6851     {
6852         return getInstance(ASN1Sequence.getInstance(obj, explicit));
6853     }
6854
6855     public static X509Extensions getInstance(
6856         Object  obj)
6857     {
6858         if (obj == null || obj instanceof X509Extensions)
6859         {
6860             return (X509Extensions)obj;
6861         }
6862
6863         if (obj instanceof ASN1Sequence)
6864         {
6865             return new X509Extensions((ASN1Sequence)obj);
6866         }
6867
6868         if (obj instanceof ASN1TaggedObject)
6869         {
6870             return getInstance(((ASN1TaggedObject)obj).getObject());
6871         }
6872
6873         throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
6874     }
6875
6876     /**
6877      * Constructor from DERConstructedSequence.
6878      *
6879      * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
6880      */
6881     public X509Extensions(
6882         ASN1Sequence  seq)
6883     {
6884         Enumeration e = seq.getObjects();
6885
6886         while (e.hasMoreElements())
6887         {
6888             ASN1Sequence            s = (ASN1Sequence)e.nextElement();
6889             Enumeration             e1 = s.getObjects();
6890
6891             if (s.size() == 3)
6892             {
6893                 extensions.put(s.getObjectAt(0), new X509Extension((DERBoolean)s.getObjectAt(1), (DEROctetString)s.getObjectAt(2)));
6894             }
6895             else
6896             {
6897                 extensions.put(s.getObjectAt(0), new X509Extension(false, (DEROctetString)s.getObjectAt(1)));
6898             }
6899
6900             ordering.addElement(s.getObjectAt(0));
6901         }
6902     }
6903
6904     /**
6905      * constructor from a table of extensions.
6906      * <p>
6907      * it's is assumed the table contains OID/String pairs.
6908      */
6909     public X509Extensions(
6910         Hashtable  extensions)
6911     {
6912         this(null, extensions);
6913     }
6914
6915     /**
6916      * constructor from a table of extensions with ordering
6917      * <p>
6918      * it's is assumed the table contains OID/String pairs.
6919      */
6920     public X509Extensions(
6921         Vector      ordering,
6922         Hashtable   extensions)
6923     {
6924         Enumeration e;
6925
6926         if (ordering == null)
6927         {
6928             e = extensions.keys();
6929         }
6930         else
6931         {
6932             e = ordering.elements();
6933         }
6934
6935         while (e.hasMoreElements())
6936         {
6937             this.ordering.addElement(e.nextElement()); 
6938         }
6939
6940         e = this.ordering.elements();
6941
6942         while (e.hasMoreElements())
6943         {
6944             DERObjectIdentifier     oid = (DERObjectIdentifier)e.nextElement();
6945             X509Extension           ext = (X509Extension)extensions.get(oid);
6946
6947             this.extensions.put(oid, ext);
6948         }
6949     }
6950
6951     /**
6952      * return an Enumeration of the extension field's object ids.
6953      */
6954     public Enumeration oids()
6955     {
6956         return ordering.elements();
6957     }
6958
6959     /**
6960      * return the extension represented by the object identifier
6961      * passed in.
6962      *
6963      * @return the extension if it's present, null otherwise.
6964      */
6965     public X509Extension getExtension(
6966         DERObjectIdentifier oid)
6967     {
6968         return (X509Extension)extensions.get(oid);
6969     }
6970
6971     public DERObject getDERObject()
6972     {
6973         DEREncodableVector      vec = new DEREncodableVector();
6974         Enumeration             e = ordering.elements();
6975
6976         while (e.hasMoreElements())
6977         {
6978             DERObjectIdentifier     oid = (DERObjectIdentifier)e.nextElement();
6979             X509Extension           ext = (X509Extension)extensions.get(oid);
6980             DEREncodableVector      v = new DEREncodableVector();
6981
6982             v.add(oid);
6983
6984             if (ext.isCritical())
6985             {
6986                 v.add(new DERBoolean(true));
6987             }
6988
6989             v.add(ext.getValue());
6990
6991             vec.add(new DERSequence(v));
6992         }
6993
6994         return new DERSequence(vec);
6995     }
6996
6997     public int hashCode()
6998     {
6999         Enumeration     e = extensions.keys();
7000         int             hashCode = 0;
7001
7002         while (e.hasMoreElements())
7003         {
7004             Object  o = e.nextElement();
7005
7006             hashCode ^= o.hashCode();
7007             hashCode ^= extensions.get(o).hashCode();
7008         }
7009
7010         return hashCode;
7011     }
7012
7013     public boolean equals(
7014         Object o)
7015     {
7016         if (o == null || !(o instanceof X509Extensions))
7017         {
7018             return false;
7019         }
7020
7021         X509Extensions  other = (X509Extensions)o;
7022
7023         Enumeration     e1 = extensions.keys();
7024         Enumeration     e2 = other.extensions.keys();
7025
7026         while (e1.hasMoreElements() && e2.hasMoreElements())
7027         {
7028             Object  o1 = e1.nextElement();
7029             Object  o2 = e2.nextElement();
7030             
7031             if (!o1.equals(o2))
7032             {
7033                 return false;
7034             }
7035         }
7036
7037         if (e1.hasMoreElements() || e2.hasMoreElements())
7038         {
7039             return false;
7040         }
7041
7042         return true;
7043     }
7044 }
7045
7046
7047
7048 class X509Name
7049     implements DEREncodable
7050 {
7051     /**
7052      * country code - StringType(SIZE(2))
7053      */
7054     public static final DERObjectIdentifier C = new DERObjectIdentifier("2.5.4.6");
7055
7056     /**
7057      * organization - StringType(SIZE(1..64))
7058      */
7059     public static final DERObjectIdentifier O = new DERObjectIdentifier("2.5.4.10");
7060
7061     /**
7062      * organizational unit name - StringType(SIZE(1..64))
7063      */
7064     public static final DERObjectIdentifier OU = new DERObjectIdentifier("2.5.4.11");
7065
7066     /**
7067      * Title
7068      */
7069     public static final DERObjectIdentifier T = new DERObjectIdentifier("2.5.4.12");
7070
7071     /**
7072      * common name - StringType(SIZE(1..64))
7073      */
7074     public static final DERObjectIdentifier CN = new DERObjectIdentifier("2.5.4.3");
7075
7076     /**
7077      * device serial number name - StringType(SIZE(1..64))
7078      */
7079     public static final DERObjectIdentifier SN = new DERObjectIdentifier("2.5.4.5");
7080
7081     /**
7082      * locality name - StringType(SIZE(1..64))
7083      */
7084     public static final DERObjectIdentifier L = new DERObjectIdentifier("2.5.4.7");
7085
7086     /**
7087      * state, or province name - StringType(SIZE(1..64))
7088      */
7089     public static final DERObjectIdentifier ST = new DERObjectIdentifier("2.5.4.8");
7090
7091
7092     /**
7093      * email address (RSA PKCS#9 extension) - IA5String
7094      * <p>
7095      * note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
7096      */
7097     public static final DERObjectIdentifier EmailAddress = new DERObjectIdentifier("1.2.840.113549.1.9.1");
7098         
7099         /**
7100          * email address in Verisign certificates
7101          */
7102         public static final DERObjectIdentifier E = EmailAddress;
7103         
7104     /*
7105      * others...
7106      */
7107     public static final DERObjectIdentifier DC = new DERObjectIdentifier("0.9.2342.19200300.100.1.25");
7108
7109     /**
7110      * LDAP User id.
7111      */
7112     public static final DERObjectIdentifier UID = new DERObjectIdentifier("0.9.2342.19200300.100.1.1");
7113
7114     /**
7115      * look up table translating OID values into their common symbols.
7116      */
7117     public static Hashtable OIDLookUp = new Hashtable();
7118
7119     /**
7120      * look up table translating common symbols into their OIDS.
7121      */
7122     public static Hashtable SymbolLookUp = new Hashtable();
7123
7124     static
7125     {
7126         OIDLookUp.put(C, "C");
7127         OIDLookUp.put(O, "O");
7128         OIDLookUp.put(T, "T");
7129         OIDLookUp.put(OU, "OU");
7130         OIDLookUp.put(CN, "CN");
7131         OIDLookUp.put(L, "L");
7132         OIDLookUp.put(ST, "ST");
7133         OIDLookUp.put(SN, "SN");
7134         OIDLookUp.put(EmailAddress, "E");
7135         OIDLookUp.put(DC, "DC");
7136         OIDLookUp.put(UID, "UID");
7137
7138         SymbolLookUp.put("c", C);
7139         SymbolLookUp.put("o", O);
7140         SymbolLookUp.put("t", T);
7141         SymbolLookUp.put("ou", OU);
7142         SymbolLookUp.put("cn", CN);
7143         SymbolLookUp.put("l", L);
7144         SymbolLookUp.put("st", ST);
7145         SymbolLookUp.put("sn", SN);
7146         SymbolLookUp.put("emailaddress", E);
7147         SymbolLookUp.put("dc", DC);
7148         SymbolLookUp.put("e", E);
7149         SymbolLookUp.put("uid", UID);
7150     }
7151
7152     private Vector                  ordering = new Vector();
7153     private Vector                  values = new Vector();
7154     private ASN1Sequence            seq;
7155
7156     public static X509Name getInstance(
7157         ASN1TaggedObject obj,
7158         boolean          explicit)
7159     {
7160         return getInstance(ASN1Sequence.getInstance(obj, explicit));
7161     }
7162
7163     public static X509Name getInstance(
7164         Object  obj)
7165     {
7166         if (obj == null || obj instanceof X509Name)
7167         {
7168             return (X509Name)obj;
7169         }
7170         else if (obj instanceof ASN1Sequence)
7171         {
7172             return new X509Name((ASN1Sequence)obj);
7173         }
7174
7175         throw new IllegalArgumentException("unknown object in factory");
7176     }
7177
7178     /**
7179      * Constructor from ASN1Sequence
7180      *
7181      * the principal will be a list of constructed sets, each containing an (OID, String) pair.
7182      */
7183     public X509Name(
7184         ASN1Sequence  seq)
7185     {
7186         this.seq = seq;
7187
7188         Enumeration e = seq.getObjects();
7189
7190         while (e.hasMoreElements())
7191         {
7192             ASN1Set         set = (ASN1Set)e.nextElement();
7193             ASN1Sequence    s = (ASN1Sequence)set.getObjectAt(0);
7194
7195             ordering.addElement(s.getObjectAt(0));
7196             values.addElement(((DERString)s.getObjectAt(1)).getString());
7197         }
7198     }
7199
7200     /**
7201      * constructor from a table of attributes.
7202      * <p>
7203      * it's is assumed the table contains OID/String pairs, and the contents
7204      * of the table are copied into an internal table as part of the 
7205      * construction process.
7206      * <p>
7207      * <b>Note:</b> if the name you are trying to generate should be
7208      * following a specific ordering, you should use the constructor
7209      * with the ordering specified below.
7210      */
7211     public X509Name(
7212         Hashtable  attributes)
7213     {
7214         this(null, attributes);
7215     }
7216
7217     /**
7218      * constructor from a table of attributes with ordering.
7219      * <p>
7220      * it's is assumed the table contains OID/String pairs, and the contents
7221      * of the table are copied into an internal table as part of the 
7222      * construction process. The ordering vector should contain the OIDs
7223      * in the order they are meant to be encoded or printed in toString.
7224      */
7225     public X509Name(
7226         Vector      ordering,
7227         Hashtable   attributes)
7228     {
7229         if (ordering != null)
7230         {
7231             for (int i = 0; i != ordering.size(); i++)
7232             {
7233                 this.ordering.addElement(ordering.elementAt(i));
7234             }
7235         }
7236         else
7237         {
7238             Enumeration     e = attributes.keys();
7239
7240             while (e.hasMoreElements())
7241             {
7242                 this.ordering.addElement(e.nextElement());
7243             }
7244         }
7245
7246         for (int i = 0; i != this.ordering.size(); i++)
7247         {
7248             DERObjectIdentifier     oid = (DERObjectIdentifier)this.ordering.elementAt(i);
7249
7250             if (OIDLookUp.get(oid) == null)
7251             {
7252                 throw new IllegalArgumentException("Unknown object id - " + oid.getId() + " - passed to distinguished name");
7253             }
7254
7255             if (attributes.get(oid) == null)
7256             {
7257                 throw new IllegalArgumentException("No attribute for object id - " + oid.getId() + " - passed to distinguished name");
7258             }
7259
7260             this.values.addElement(attributes.get(oid)); // copy the hash table
7261         }
7262     }
7263
7264     /**
7265      * takes two vectors one of the oids and the other of the values.
7266      */
7267     public X509Name(
7268         Vector  ordering,
7269         Vector  values)
7270     {
7271         if (ordering.size() != values.size())
7272         {
7273             throw new IllegalArgumentException("ordering vector must be same length as values.");
7274         }
7275
7276         for (int i = 0; i < ordering.size(); i++)
7277         {
7278             this.ordering.addElement(ordering.elementAt(i));
7279             this.values.addElement(values.elementAt(i));
7280         }
7281     }
7282
7283     /**
7284      * takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
7285      * some such, converting it into an ordered set of name attributes.
7286      */
7287     public X509Name(
7288         String  dirName)
7289     {
7290         X509NameTokenizer   nTok = new X509NameTokenizer(dirName);
7291
7292         while (nTok.hasMoreTokens())
7293         {
7294             String  token = nTok.nextToken();
7295             int     index = token.indexOf('=');
7296
7297             if (index == -1)
7298             {
7299                 throw new IllegalArgumentException("badly formated directory string");
7300             }
7301
7302             String              name = token.substring(0, index);
7303             String              value = token.substring(index + 1);
7304             DERObjectIdentifier oid = null;
7305
7306             if (name.toUpperCase().startsWith("OID."))
7307             {
7308                 oid = new DERObjectIdentifier(name.substring(4));
7309             }
7310             else if (name.charAt(0) >= '0' && name.charAt(0) <= '9')
7311             {
7312                 oid = new DERObjectIdentifier(name);
7313             }
7314             else
7315             {
7316                 oid = (DERObjectIdentifier)SymbolLookUp.get(name.toLowerCase());
7317                 if (oid == null)
7318                 {
7319                     throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name");
7320                 }
7321             }
7322
7323             this.ordering.addElement(oid);
7324             this.values.addElement(value);
7325         }
7326     }
7327
7328     /**
7329      * return false if we have characters out of the range of a printable
7330      * string, true otherwise.
7331      */
7332     private boolean canBePrintable(
7333         String  str)
7334     {
7335         for (int i = str.length() - 1; i >= 0; i--)
7336         {
7337             if (str.charAt(i) > 0x007f)
7338             {
7339                 return false;
7340             }
7341         }
7342
7343         return true;
7344     }
7345
7346     public DERObject getDERObject()
7347     {
7348         if (seq == null)
7349         {
7350             DEREncodableVector  vec = new DEREncodableVector();
7351
7352             for (int i = 0; i != ordering.size(); i++)
7353             {
7354                 DEREncodableVector      v = new DEREncodableVector();
7355                 DERObjectIdentifier     oid = (DERObjectIdentifier)ordering.elementAt(i);
7356
7357                 v.add(oid);
7358
7359                 String  str = (String)values.elementAt(i);
7360
7361                 if (oid.equals(EmailAddress))
7362                 {
7363                     v.add(new DERIA5String(str));
7364                 }
7365                 else
7366                 {
7367                     if (canBePrintable(str))
7368                     {
7369                         v.add(new DERPrintableString(str));
7370                     }
7371                     else
7372                     {
7373                         v.add(new DERUTF8String(str));
7374                     }
7375                 }
7376
7377                 vec.add(new DERSet(new DERSequence(v)));
7378             }
7379
7380             seq = new DERSequence(vec);
7381         }
7382
7383         return seq;
7384     }
7385
7386     /**
7387      * test for equality - note: case is ignored.
7388      */
7389     public boolean equals(Object _obj) 
7390     {
7391         if (_obj == this)
7392         {
7393             return true;
7394         }
7395
7396         if (_obj == null || !(_obj instanceof X509Name))
7397         {
7398             return false;
7399         }
7400         
7401         X509Name _oxn          = (X509Name)_obj;
7402         int      _orderingSize = ordering.size();
7403
7404         if (_orderingSize != _oxn.ordering.size()) 
7405         {
7406                         return false;
7407                 }
7408                 
7409                 boolean[] _indexes = new boolean[_orderingSize];
7410
7411                 for(int i = 0; i < _orderingSize; i++) 
7412                 {
7413                         boolean _found = false;
7414                         String  _oid   = ((DERObjectIdentifier)ordering.elementAt(i)).getId();
7415                         String  _val   = (String)values.elementAt(i);
7416                         
7417                         for(int j = 0; j < _orderingSize; j++) 
7418                         {
7419                                 if(_indexes[j] == true)
7420                                 {
7421                                         continue;
7422                                 }
7423                                 
7424                                 String _oOID = ((DERObjectIdentifier)_oxn.ordering.elementAt(j)).getId();
7425                                 String _oVal = (String)_oxn.values.elementAt(j);
7426
7427                 // was equalsIgnoreCase but MIDP doesn't like that.
7428                                 if(_oid.equals(_oOID) && _val.toLowerCase().equals(_oVal.toLowerCase()))
7429                                 {
7430                                         _indexes[j] = true;
7431                                         _found      = true;
7432                                         break;
7433                                 }
7434
7435                         }
7436
7437                         if(!_found)
7438                         {
7439                                 return false;
7440                         }
7441                 }
7442                 
7443                 return true;
7444         }
7445         
7446     public int hashCode()
7447     {
7448         ASN1Sequence  seq = (ASN1Sequence)this.getDERObject();
7449         Enumeration   e = seq.getObjects();
7450         int           hashCode = 0;
7451
7452         while (e.hasMoreElements())
7453         {
7454             hashCode ^= e.nextElement().hashCode();
7455         }
7456
7457         return hashCode;
7458     }
7459
7460     public String toString()
7461     {
7462         StringBuffer            buf = new StringBuffer();
7463         boolean                 first = true;
7464         Enumeration             e1 = ordering.elements();
7465         Enumeration             e2 = values.elements();
7466
7467         while (e1.hasMoreElements())
7468         {
7469             Object                  oid = e1.nextElement();
7470             String                  sym = (String)OIDLookUp.get(oid);
7471             
7472             if (first)
7473             {
7474                 first = false;
7475             }
7476             else
7477             {
7478                 buf.append(",");
7479             }
7480
7481             if (sym != null)
7482             {
7483                 buf.append(sym);
7484             }
7485             else
7486             {
7487                 buf.append(((DERObjectIdentifier)oid).getId());
7488             }
7489
7490             buf.append("=");
7491
7492             int     index = buf.length();
7493
7494             buf.append((String)e2.nextElement());
7495
7496             int     end = buf.length();
7497
7498             while (index != end)
7499             {
7500                 if ((buf.charAt(index) == ',')
7501                    || (buf.charAt(index) == '"')
7502                    || (buf.charAt(index) == '\\')
7503                    || (buf.charAt(index) == '+')
7504                    || (buf.charAt(index) == '<')
7505                    || (buf.charAt(index) == '>')
7506                    || (buf.charAt(index) == ';'))
7507                 {
7508                     buf.insert(index, "\\");
7509                     index++;
7510                     end++;
7511                 }
7512
7513                 index++;
7514             }
7515         }
7516
7517         return buf.toString();
7518     }
7519 }
7520
7521 /**
7522  * class for breaking up an X500 Name into it's component tokens, ala
7523  * java.util.StringTokenizer. We need this class as some of the
7524  * lightweight Java environment don't support classes like
7525  * StringTokenizer.
7526  */
7527 class X509NameTokenizer
7528 {
7529     private String          oid;
7530     private int             index;
7531     private StringBuffer    buf = new StringBuffer();
7532
7533     public X509NameTokenizer(
7534         String oid)
7535     {
7536         this.oid = oid;
7537         this.index = -1;
7538     }
7539
7540     public boolean hasMoreTokens()
7541     {
7542         return (index != oid.length());
7543     }
7544
7545     public String nextToken()
7546     {
7547         if (index == oid.length())
7548         {
7549             return null;
7550         }
7551
7552         int     end = index + 1;
7553         boolean quoted = false;
7554         boolean escaped = false;
7555
7556         buf.setLength(0);
7557
7558         while (end != oid.length())
7559         {
7560             char    c = oid.charAt(end);
7561
7562             if (c == '"')
7563             {
7564                 if (!escaped)
7565                 {
7566                     quoted = !quoted;
7567                 }
7568                 else
7569                 {
7570                     buf.append(c);
7571                 }
7572                 escaped = false;
7573             }
7574             else
7575             {
7576                 if (escaped || quoted)
7577                 {
7578                     buf.append(c);
7579                     escaped = false;
7580                 }
7581                 else if (c == '\\')
7582                 {
7583                     escaped = true;
7584                 }
7585                 else if (c == ',')
7586                 {
7587                     break;
7588                 }
7589                 else
7590                 {
7591                     buf.append(c);
7592                 }
7593             }
7594             end++;
7595         }
7596
7597         index = end;
7598         return buf.toString().trim();
7599     }
7600 }
7601
7602
7603 interface X509ObjectIdentifiers
7604 {
7605     //
7606     // base id
7607     //
7608     static final String                 id                      = "2.5.4";
7609
7610     static final DERObjectIdentifier    commonName              = new DERObjectIdentifier(id + ".3");
7611     static final DERObjectIdentifier    countryName             = new DERObjectIdentifier(id + ".6");
7612     static final DERObjectIdentifier    localityName            = new DERObjectIdentifier(id + ".7");
7613     static final DERObjectIdentifier    stateOrProvinceName     = new DERObjectIdentifier(id + ".8");
7614     static final DERObjectIdentifier    organization            = new DERObjectIdentifier(id + ".10");
7615     static final DERObjectIdentifier    organizationalUnitName  = new DERObjectIdentifier(id + ".11");
7616
7617     // id-SHA1 OBJECT IDENTIFIER ::=    
7618     //   {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 }    //
7619     static final DERObjectIdentifier    id_SHA1                 = new DERObjectIdentifier("1.3.14.3.2.26");
7620
7621     //
7622     // ripemd160 OBJECT IDENTIFIER ::=
7623     //      {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) hashAlgorithm(2) RIPEMD-160(1)}
7624     //
7625     static final DERObjectIdentifier    ripemd160               = new DERObjectIdentifier("1.3.36.3.2.1");
7626
7627     //
7628     // ripemd160WithRSAEncryption OBJECT IDENTIFIER ::=
7629     //      {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) signatureAlgorithm(3) rsaSignature(1) rsaSignatureWithripemd160(2) }
7630     //
7631     static final DERObjectIdentifier    ripemd160WithRSAEncryption = new DERObjectIdentifier("1.3.36.3.3.1.2");
7632
7633
7634         static final DERObjectIdentifier        id_ea_rsa = new DERObjectIdentifier("2.5.8.1.1");
7635 }
7636
7637
7638
7639 /**
7640  * base interface that a public/private key block cipher needs
7641  * to conform to.
7642  */
7643 interface AsymmetricBlockCipher
7644 {
7645     /**
7646      * initialise the cipher.
7647      *
7648      * @param forEncryption if true the cipher is initialised for 
7649      *  encryption, if false for decryption.
7650      * @param param the key and other data required by the cipher.
7651      */
7652     public void init(boolean forEncryption, CipherParameters param);
7653
7654     /**
7655      * returns the largest size an input block can be.
7656      *
7657      * @return maximum size for an input block.
7658      */
7659     public int getInputBlockSize();
7660
7661     /**
7662      * returns the maximum size of the block produced by this cipher.
7663      *
7664      * @return maximum size of the output block produced by the cipher.
7665      */
7666     public int getOutputBlockSize();
7667
7668     /**
7669      * process the block of len bytes stored in in from offset inOff.
7670      *
7671      * @param in the input data
7672      * @param inOff offset into the in array where the data starts
7673      * @param len the length of the block to be processed.
7674      * @return the resulting byte array of the encryption/decryption process.
7675      * @exception InvalidCipherTextException data decrypts improperly.
7676      * @exception DataLengthException the input data is too large for the cipher.
7677      */
7678     public byte[] processBlock(byte[] in, int inOff, int len)
7679         throws InvalidCipherTextException;
7680 }
7681
7682 /**
7683  * a holding class for public/private parameter pairs.
7684  */
7685 class AsymmetricCipherKeyPair
7686 {
7687     private CipherParameters    publicParam;
7688     private CipherParameters    privateParam;
7689
7690     /**
7691      * basic constructor.
7692      *
7693      * @param publicParam a public key parameters object.
7694      * @param privateParam the corresponding private key parameters.
7695      */
7696     public AsymmetricCipherKeyPair(
7697         CipherParameters    publicParam,
7698         CipherParameters    privateParam)
7699     {
7700         this.publicParam = publicParam;
7701         this.privateParam = privateParam;
7702     }
7703
7704     /**
7705      * return the public key parameters.
7706      *
7707      * @return the public key parameters.
7708      */
7709     public CipherParameters getPublic()
7710     {
7711         return publicParam;
7712     }
7713
7714     /**
7715      * return the private key parameters.
7716      *
7717      * @return the private key parameters.
7718      */
7719     public CipherParameters getPrivate()
7720     {
7721         return privateParam;
7722     }
7723 }
7724
7725 /**
7726  * interface that a public/private key pair generator should conform to.
7727  */
7728 interface AsymmetricCipherKeyPairGenerator
7729 {
7730     /**
7731      * intialise the key pair generator.
7732      *
7733      * @param the parameters the key pair is to be initialised with.
7734      */
7735     public void init(KeyGenerationParameters param);
7736
7737     /**
7738      * return an AsymmetricCipherKeyPair containing the generated keys.
7739      *
7740      * @return an AsymmetricCipherKeyPair containing the generated keys.
7741      */
7742     public AsymmetricCipherKeyPair generateKeyPair();
7743 }
7744
7745
7746
7747 /**
7748  * Block cipher engines are expected to conform to this interface.
7749  */
7750 interface BlockCipher
7751 {
7752     /**
7753      * Initialise the cipher.
7754      *
7755      * @param forEncryption if true the cipher is initialised for
7756      *  encryption, if false for decryption.
7757      * @param param the key and other data required by the cipher.
7758      * @exception IllegalArgumentException if the params argument is
7759      * inappropriate.
7760      */
7761     public void init(boolean forEncryption, CipherParameters params)
7762         throws IllegalArgumentException;
7763
7764     /**
7765      * Return the name of the algorithm the cipher implements.
7766      *
7767      * @return the name of the algorithm the cipher implements.
7768      */
7769     public String getAlgorithmName();
7770
7771     /**
7772      * Return the block size for this cipher (in bytes).
7773      *
7774      * @return the block size for this cipher in bytes.
7775      */
7776     public int getBlockSize();
7777
7778     /**
7779      * Process one block of input from the array in and write it to
7780      * the out array.
7781      *
7782      * @param in the array containing the input data.
7783      * @param inOff offset into the in array the data starts at.
7784      * @param out the array the output data will be copied into.
7785      * @param outOff the offset into the out array the output will start at.
7786      * @exception DataLengthException if there isn't enough data in in, or
7787      * space in out.
7788      * @exception IllegalStateException if the cipher isn't initialised.
7789      * @return the number of bytes processed and produced.
7790      */
7791     public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
7792         throws DataLengthException, IllegalStateException;
7793
7794     /**
7795      * Reset the cipher. After resetting the cipher is in the same state
7796      * as it was after the last init (if there was one).
7797      */
7798     public void reset();
7799 }
7800
7801
7802 /**
7803  * The base class for symmetric, or secret, cipher key generators.
7804  */
7805 class CipherKeyGenerator
7806 {
7807     protected Random  random;
7808     protected int           strength;
7809
7810     /**
7811      * initialise the key generator.
7812      *
7813      * @param param the parameters to be used for key generation
7814      */
7815     public void init(
7816         KeyGenerationParameters param)
7817     {
7818         this.random = param.getRandom();
7819         this.strength = (param.getStrength() + 7) / 8;
7820     }
7821
7822     /**
7823      * generate a secret key.
7824      *
7825      * @return a byte array containing the key value.
7826      */
7827     public byte[] generateKey()
7828     {
7829         byte[]  key = new byte[strength];
7830
7831         random.nextBytes(key);
7832
7833         return key;
7834     }
7835 }
7836
7837 /**
7838  * all parameter classes implement this.
7839  */
7840 interface CipherParameters
7841 {
7842 }
7843
7844 /**
7845  * the foundation class for the hard exceptions thrown by the crypto packages.
7846  */
7847 class CryptoException 
7848     extends Exception
7849 {
7850     /**
7851      * base constructor.
7852      */
7853     public CryptoException()
7854     {
7855     }
7856
7857     /**
7858      * create a CryptoException with the given message.
7859      *
7860      * @param message the message to be carried with the exception.
7861      */
7862     public CryptoException(
7863         String  message)
7864     {
7865         super(message);
7866     }
7867 }
7868
7869 /**
7870  * this exception is thrown if a buffer that is meant to have output
7871  * copied into it turns out to be too short, or if we've been given 
7872  * insufficient input. In general this exception will get thrown rather
7873  * than an ArrayOutOfBounds exception.
7874  */
7875 class DataLengthException 
7876     extends RuntimeCryptoException
7877 {
7878     /**
7879      * base constructor.
7880      */
7881     public DataLengthException()
7882     {
7883     }
7884
7885     /**
7886      * create a DataLengthException with the given message.
7887      *
7888      * @param message the message to be carried with the exception.
7889      */
7890     public DataLengthException(
7891         String  message)
7892     {
7893         super(message);
7894     }
7895 }
7896
7897 /**
7898  * interface that a message digest conforms to.
7899  */
7900 interface Digest
7901 {
7902     /**
7903      * return the algorithm name
7904      *
7905      * @return the algorithm name
7906      */
7907     public String getAlgorithmName();
7908
7909     /**
7910      * return the size, in bytes, of the digest produced by this message digest.
7911      *
7912      * @return the size, in bytes, of the digest produced by this message digest.
7913      */
7914         public int getDigestSize();
7915
7916     /**
7917      * update the message digest with a single byte.
7918      *
7919      * @param in the input byte to be entered.
7920      */
7921         public void update(byte in);
7922
7923     /**
7924      * update the message digest with a block of bytes.
7925      *
7926      * @param in the byte array containing the data.
7927      * @param inOff the offset into the byte array where the data starts.
7928      * @param len the length of the data.
7929      */
7930         public void update(byte[] in, int inOff, int len);
7931
7932     /**
7933      * close the digest, producing the final digest value. The doFinal
7934      * call leaves the digest reset.
7935      *
7936      * @param out the array the digest is to be copied into.
7937      * @param outOff the offset into the out array the digest is to start at.
7938      */
7939         public int doFinal(byte[] out, int outOff);
7940
7941     /**
7942      * reset the digest back to it's initial state.
7943      */
7944     public void reset();
7945 }
7946
7947
7948 /**
7949  * base implementation of MD4 family style digest as outlined in
7950  * "Handbook of Applied Cryptography", pages 344 - 347.
7951  */
7952 abstract class GeneralDigest
7953     implements Digest
7954 {
7955     private byte[]  xBuf;
7956     private int     xBufOff;
7957
7958     private long    byteCount;
7959
7960         /**
7961          * Standard constructor
7962          */
7963         protected GeneralDigest()
7964         {
7965                 xBuf = new byte[4];
7966                 xBufOff = 0;
7967         }
7968
7969         /**
7970          * Copy constructor.  We are using copy constructors in place
7971          * of the Object.clone() interface as this interface is not
7972          * supported by J2ME.
7973          */
7974         protected GeneralDigest(GeneralDigest t)
7975         {
7976         xBuf = new byte[t.xBuf.length];
7977                 System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
7978
7979                 xBufOff = t.xBufOff;
7980                 byteCount = t.byteCount;
7981         }
7982
7983     public void update(
7984         byte in)
7985     {
7986         xBuf[xBufOff++] = in;
7987
7988         if (xBufOff == xBuf.length)
7989         {
7990             processWord(xBuf, 0);
7991             xBufOff = 0;
7992         }
7993
7994         byteCount++;
7995     }
7996
7997     public void update(
7998         byte[]  in,
7999         int     inOff,
8000         int     len)
8001     {
8002         //
8003         // fill the current word
8004         //
8005         while ((xBufOff != 0) && (len > 0))
8006         {
8007             update(in[inOff]);
8008
8009             inOff++;
8010             len--;
8011         }
8012
8013         //
8014         // process whole words.
8015         //
8016         while (len > xBuf.length)
8017         {
8018             processWord(in, inOff);
8019
8020             inOff += xBuf.length;
8021             len -= xBuf.length;
8022             byteCount += xBuf.length;
8023         }
8024
8025         //
8026         // load in the remainder.
8027         //
8028         while (len > 0)
8029         {
8030             update(in[inOff]);
8031
8032             inOff++;
8033             len--;
8034         }
8035     }
8036
8037     public void finish()
8038     {
8039         long    bitLength = (byteCount << 3);
8040
8041         //
8042         // add the pad bytes.
8043         //
8044         update((byte)128);
8045
8046         while (xBufOff != 0)
8047         {
8048             update((byte)0);
8049         }
8050
8051         processLength(bitLength);
8052
8053         processBlock();
8054     }
8055
8056     public void reset()
8057     {
8058         byteCount = 0;
8059
8060         xBufOff = 0;
8061                 for ( int i = 0; i < xBuf.length; i++ ) {
8062                         xBuf[i] = 0;
8063                 }
8064     }
8065
8066     protected abstract void processWord(byte[] in, int inOff);
8067
8068     protected abstract void processLength(long bitLength);
8069
8070     protected abstract void processBlock();
8071 }
8072
8073 /**
8074  * implementation of MD2
8075  * as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
8076  */
8077 class MD2Digest\r
8078     implements Digest\r
8079 {\r
8080     private static final int DIGEST_LENGTH = 16;\r
8081 \r
8082     /* X buffer */\r
8083     private byte[]   X = new byte[48];\r
8084     private int     xOff;
8085 \r    /* M buffer */
8086 \r    private byte[]   M = new byte[16];\r
8087     private int     mOff;
8088 \r    /* check sum */
8089 \r    private byte[]   C = new byte[16];
8090     private int COff;
8091
8092     public MD2Digest()\r
8093     {\r
8094         reset();\r
8095     }\r
8096         public MD2Digest(MD2Digest t)\r
8097         {
8098                 System.arraycopy(t.X, 0, X, 0, t.X.length);
8099                 xOff = t.xOff;
8100                 System.arraycopy(t.M, 0, M, 0, t.M.length);
8101                 mOff = t.mOff;
8102                 System.arraycopy(t.C, 0, C, 0, t.C.length);
8103                 COff = t.COff;
8104         }
8105     /**\r
8106      * return the algorithm name
8107      *
8108      * @return the algorithm name
8109      */
8110     public String getAlgorithmName()
8111     {
8112         return "MD2";
8113     }
8114     /**
8115      * return the size, in bytes, of the digest produced by this message digest.
8116      *
8117      * @return the size, in bytes, of the digest produced by this message digest.
8118      */
8119         public int getDigestSize()
8120     {
8121         return DIGEST_LENGTH;
8122     }
8123     /**
8124      * close the digest, producing the final digest value. The doFinal
8125      * call leaves the digest reset.
8126      *
8127      * @param out the array the digest is to be copied into.
8128      * @param outOff the offset into the out array the digest is to start at.
8129      */
8130         public int doFinal(byte[] out, int outOff)
8131     {
8132         // add padding
8133         byte paddingByte = (byte)(M.length-mOff);
8134         for (int i=mOff;i<M.length;i++)
8135         {
8136             M[i] = paddingByte;
8137         }
8138         //do final check sum
8139         processCheckSum(M);
8140         // do final block process
8141         processBlock(M);
8142
8143         processBlock(C);
8144
8145         System.arraycopy(X,xOff,out,outOff,16);
8146
8147         reset();
8148
8149         return DIGEST_LENGTH;
8150     }
8151     /**
8152      * reset the digest back to it's initial state.
8153      */
8154     public void reset()\r
8155     {\r
8156         xOff = 0;\r
8157         for (int i = 0; i != X.length; i++)
8158         {
8159             X[i] = 0;
8160         }
8161         mOff = 0;\r
8162         for (int i = 0; i != M.length; i++)
8163         {
8164             M[i] = 0;
8165         }
8166         COff = 0;\r
8167         for (int i = 0; i != C.length; i++)
8168         {
8169             C[i] = 0;
8170         }
8171     }\r
8172     /**\r
8173      * update the message digest with a single byte.
8174      *
8175      * @param in the input byte to be entered.
8176      */
8177         public void update(byte in)
8178     {
8179         M[mOff++] = in;
8180
8181         if (mOff == 16)
8182         {
8183             processCheckSum(M);
8184             processBlock(M);
8185             mOff = 0;
8186         }
8187     }
8188
8189     /**
8190      * update the message digest with a block of bytes.
8191      *
8192      * @param in the byte array containing the data.
8193      * @param inOff the offset into the byte array where the data starts.
8194      * @param len the length of the data.
8195      */
8196         public void update(byte[] in, int inOff, int len)\r
8197     {\r
8198         //\r
8199         // fill the current word
8200         //
8201         while ((mOff != 0) && (len > 0))
8202         {
8203             update(in[inOff]);
8204             inOff++;
8205             len--;
8206         }
8207
8208         //
8209         // process whole words.
8210         //
8211         while (len > 16)
8212         {
8213             System.arraycopy(in,inOff,M,0,16);
8214             processCheckSum(M);
8215             processBlock(M);
8216             len -= 16;
8217             inOff += 16;
8218         }
8219
8220         //
8221         // load in the remainder.
8222         //
8223         while (len > 0)
8224         {
8225             update(in[inOff]);
8226             inOff++;
8227             len--;
8228         }\r
8229     }\r
8230     protected void processCheckSum(byte[] m)\r
8231     {\r
8232         int L = C[15];\r
8233         for (int i=0;i<16;i++)\r
8234         {\r
8235             C[i] ^= S[(m[i] ^ L) & 0xff];\r
8236             L = C[i];\r
8237         }\r
8238     }\r
8239     protected void processBlock(byte[] m)\r
8240     {
8241         for (int i=0;i<16;i++)
8242         {
8243             X[i+16] = m[i];
8244             X[i+32] = (byte)(m[i] ^ X[i]);
8245         }
8246         // encrypt block
8247         int t = 0;
8248
8249         for (int j=0;j<18;j++)
8250         {
8251             for (int k=0;k<48;k++)
8252             {
8253                 t = X[k] ^= S[t];
8254                 t = t & 0xff;
8255             }
8256             t = (t + j)%256;
8257         }
8258      }
8259      // 256-byte random permutation constructed from the digits of PI
8260     private static final byte[] S = {\r
8261       (byte)41,(byte)46,(byte)67,(byte)201,(byte)162,(byte)216,(byte)124,\r
8262       (byte)1,(byte)61,(byte)54,(byte)84,(byte)161,(byte)236,(byte)240,\r
8263       (byte)6,(byte)19,(byte)98,(byte)167,(byte)5,(byte)243,(byte)192,\r
8264       (byte)199,(byte)115,(byte)140,(byte)152,(byte)147,(byte)43,(byte)217,\r
8265       (byte)188,(byte)76,(byte)130,(byte)202,(byte)30,(byte)155,(byte)87,\r
8266       (byte)60,(byte)253,(byte)212,(byte)224,(byte)22,(byte)103,(byte)66,\r
8267       (byte)111,(byte)24,(byte)138,(byte)23,(byte)229,(byte)18,(byte)190,\r
8268       (byte)78,(byte)196,(byte)214,(byte)218,(byte)158,(byte)222,(byte)73,\r
8269       (byte)160,(byte)251,(byte)245,(byte)142,(byte)187,(byte)47,(byte)238,\r
8270       (byte)122,(byte)169,(byte)104,(byte)121,(byte)145,(byte)21,(byte)178,\r
8271       (byte)7,(byte)63,(byte)148,(byte)194,(byte)16,(byte)137,(byte)11,\r
8272       (byte)34,(byte)95,(byte)33,(byte)128,(byte)127,(byte)93,(byte)154,\r
8273       (byte)90,(byte)144,(byte)50,(byte)39,(byte)53,(byte)62,(byte)204,\r
8274       (byte)231,(byte)191,(byte)247,(byte)151,(byte)3,(byte)255,(byte)25,\r
8275       (byte)48,(byte)179,(byte)72,(byte)165,(byte)181,(byte)209,(byte)215,\r
8276       (byte)94,(byte)146,(byte)42,(byte)172,(byte)86,(byte)170,(byte)198,\r
8277       (byte)79,(byte)184,(byte)56,(byte)210,(byte)150,(byte)164,(byte)125,\r
8278       (byte)182,(byte)118,(byte)252,(byte)107,(byte)226,(byte)156,(byte)116,\r
8279       (byte)4,(byte)241,(byte)69,(byte)157,(byte)112,(byte)89,(byte)100,\r
8280       (byte)113,(byte)135,(byte)32,(byte)134,(byte)91,(byte)207,(byte)101,\r
8281       (byte)230,(byte)45,(byte)168,(byte)2,(byte)27,(byte)96,(byte)37,\r
8282       (byte)173,(byte)174,(byte)176,(byte)185,(byte)246,(byte)28,(byte)70,\r
8283       (byte)97,(byte)105,(byte)52,(byte)64,(byte)126,(byte)15,(byte)85,\r
8284       (byte)71,(byte)163,(byte)35,(byte)221,(byte)81,(byte)175,(byte)58,\r
8285       (byte)195,(byte)92,(byte)249,(byte)206,(byte)186,(byte)197,(byte)234,\r
8286       (byte)38,(byte)44,(byte)83,(byte)13,(byte)110,(byte)133,(byte)40,\r
8287       (byte)132, 9,(byte)211,(byte)223,(byte)205,(byte)244,(byte)65,\r
8288       (byte)129,(byte)77,(byte)82,(byte)106,(byte)220,(byte)55,(byte)200,\r
8289       (byte)108,(byte)193,(byte)171,(byte)250,(byte)36,(byte)225,(byte)123,\r
8290       (byte)8,(byte)12,(byte)189,(byte)177,(byte)74,(byte)120,(byte)136,\r
8291       (byte)149,(byte)139,(byte)227,(byte)99,(byte)232,(byte)109,(byte)233,\r
8292       (byte)203,(byte)213,(byte)254,(byte)59,(byte)0,(byte)29,(byte)57,\r
8293       (byte)242,(byte)239,(byte)183,(byte)14,(byte)102,(byte)88,(byte)208,\r
8294       (byte)228,(byte)166,(byte)119,(byte)114,(byte)248,(byte)235,(byte)117,\r
8295       (byte)75,(byte)10,(byte)49,(byte)68,(byte)80,(byte)180,(byte)143,\r
8296       (byte)237,(byte)31,(byte)26,(byte)219,(byte)153,(byte)141,(byte)51,\r
8297       (byte)159,(byte)17,(byte)131,(byte)20\r
8298     };\r
8299 }\r
8300
8301
8302 /**
8303  * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
8304  */
8305 class MD5Digest
8306     extends GeneralDigest
8307 {
8308     private static final int    DIGEST_LENGTH = 16;
8309
8310     private int     H1, H2, H3, H4;         // IV's
8311
8312     private int[]   X = new int[16];
8313     private int     xOff;
8314
8315         /**
8316          * Standard constructor
8317          */
8318     public MD5Digest()
8319     {
8320         reset();
8321     }
8322
8323         /**
8324          * Copy constructor.  This will copy the state of the provided
8325          * message digest.
8326          */
8327         public MD5Digest(MD5Digest t)
8328         {
8329                 super(t);
8330
8331                 H1 = t.H1;
8332                 H2 = t.H2;
8333                 H3 = t.H3;
8334                 H4 = t.H4;
8335
8336                 System.arraycopy(t.X, 0, X, 0, t.X.length);
8337                 xOff = t.xOff;
8338         }
8339
8340     public String getAlgorithmName()
8341     {
8342         return "MD5";
8343     }
8344
8345     public int getDigestSize()
8346     {
8347         return DIGEST_LENGTH;
8348     }
8349
8350     protected void processWord(
8351         byte[]  in,
8352         int     inOff)
8353     {
8354         X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
8355             | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); 
8356
8357         if (xOff == 16)
8358         {
8359             processBlock();
8360         }
8361     }
8362
8363     protected void processLength(
8364         long    bitLength)
8365     {
8366         if (xOff > 14)
8367         {
8368             processBlock();
8369         }
8370
8371         X[14] = (int)(bitLength & 0xffffffff);
8372         X[15] = (int)(bitLength >>> 32);
8373     }
8374
8375     private void unpackWord(
8376         int     word,
8377         byte[]  out,
8378         int     outOff)
8379     {
8380         out[outOff]     = (byte)word;
8381         out[outOff + 1] = (byte)(word >>> 8);
8382         out[outOff + 2] = (byte)(word >>> 16);
8383         out[outOff + 3] = (byte)(word >>> 24);
8384     }
8385
8386     public int doFinal(
8387         byte[]  out,
8388         int     outOff)
8389     {
8390         finish();
8391
8392         unpackWord(H1, out, outOff);
8393         unpackWord(H2, out, outOff + 4);
8394         unpackWord(H3, out, outOff + 8);
8395         unpackWord(H4, out, outOff + 12);
8396
8397         reset();
8398
8399         return DIGEST_LENGTH;
8400     }
8401
8402     /**
8403      * reset the chaining variables to the IV values.
8404      */
8405     public void reset()
8406     {
8407         super.reset();
8408
8409         H1 = 0x67452301;
8410         H2 = 0xefcdab89;
8411         H3 = 0x98badcfe;
8412         H4 = 0x10325476;
8413
8414         xOff = 0;
8415
8416         for (int i = 0; i != X.length; i++)
8417         {
8418             X[i] = 0;
8419         }
8420     }
8421
8422     //
8423     // round 1 left rotates
8424     //
8425     private static final int S11 = 7;
8426     private static final int S12 = 12;
8427     private static final int S13 = 17;
8428     private static final int S14 = 22;
8429
8430     //
8431     // round 2 left rotates
8432     //
8433     private static final int S21 = 5;
8434     private static final int S22 = 9;
8435     private static final int S23 = 14;
8436     private static final int S24 = 20;
8437
8438     //
8439     // round 3 left rotates
8440     //
8441     private static final int S31 = 4;
8442     private static final int S32 = 11;
8443     private static final int S33 = 16;
8444     private static final int S34 = 23;
8445
8446     //
8447     // round 4 left rotates
8448     //
8449     private static final int S41 = 6;
8450     private static final int S42 = 10;
8451     private static final int S43 = 15;
8452     private static final int S44 = 21;
8453
8454     /*
8455      * rotate int x left n bits.
8456      */
8457     private int rotateLeft(
8458         int x,
8459         int n)
8460     {
8461         return (x << n) | (x >>> (32 - n));
8462     }
8463
8464     /*
8465      * F, G, H and I are the basic MD5 functions.
8466      */
8467     private int F(
8468         int u,
8469         int v,
8470         int w)
8471     {
8472         return (u & v) | (~u & w);
8473     }
8474
8475     private int G(
8476         int u,
8477         int v,
8478         int w)
8479     {
8480         return (u & w) | (v & ~w);
8481     }
8482
8483     private int H(
8484         int u,
8485         int v,
8486         int w)
8487     {
8488         return u ^ v ^ w;
8489     }
8490
8491     private int K(
8492         int u,
8493         int v,
8494         int w)
8495     {
8496         return v ^ (u | ~w);
8497     }
8498
8499     protected void processBlock()
8500     {
8501         int a = H1;
8502         int b = H2;
8503         int c = H3;
8504         int d = H4;
8505
8506         //
8507         // Round 1 - F cycle, 16 times.
8508         //
8509         a = rotateLeft((a + F(b, c, d) + X[ 0] + 0xd76aa478), S11) + b;
8510         d = rotateLeft((d + F(a, b, c) + X[ 1] + 0xe8c7b756), S12) + a;
8511         c = rotateLeft((c + F(d, a, b) + X[ 2] + 0x242070db), S13) + d;
8512         b = rotateLeft((b + F(c, d, a) + X[ 3] + 0xc1bdceee), S14) + c;
8513         a = rotateLeft((a + F(b, c, d) + X[ 4] + 0xf57c0faf), S11) + b;
8514         d = rotateLeft((d + F(a, b, c) + X[ 5] + 0x4787c62a), S12) + a;
8515         c = rotateLeft((c + F(d, a, b) + X[ 6] + 0xa8304613), S13) + d;
8516         b = rotateLeft((b + F(c, d, a) + X[ 7] + 0xfd469501), S14) + c;
8517         a = rotateLeft((a + F(b, c, d) + X[ 8] + 0x698098d8), S11) + b;
8518         d = rotateLeft((d + F(a, b, c) + X[ 9] + 0x8b44f7af), S12) + a;
8519         c = rotateLeft((c + F(d, a, b) + X[10] + 0xffff5bb1), S13) + d;
8520         b = rotateLeft((b + F(c, d, a) + X[11] + 0x895cd7be), S14) + c;
8521         a = rotateLeft((a + F(b, c, d) + X[12] + 0x6b901122), S11) + b;
8522         d = rotateLeft((d + F(a, b, c) + X[13] + 0xfd987193), S12) + a;
8523         c = rotateLeft((c + F(d, a, b) + X[14] + 0xa679438e), S13) + d;
8524         b = rotateLeft((b + F(c, d, a) + X[15] + 0x49b40821), S14) + c;
8525
8526         //
8527         // Round 2 - G cycle, 16 times.
8528         //
8529         a = rotateLeft((a + G(b, c, d) + X[ 1] + 0xf61e2562), S21) + b;
8530         d = rotateLeft((d + G(a, b, c) + X[ 6] + 0xc040b340), S22) + a;
8531         c = rotateLeft((c + G(d, a, b) + X[11] + 0x265e5a51), S23) + d;
8532         b = rotateLeft((b + G(c, d, a) + X[ 0] + 0xe9b6c7aa), S24) + c;
8533         a = rotateLeft((a + G(b, c, d) + X[ 5] + 0xd62f105d), S21) + b;
8534         d = rotateLeft((d + G(a, b, c) + X[10] + 0x02441453), S22) + a;
8535         c = rotateLeft((c + G(d, a, b) + X[15] + 0xd8a1e681), S23) + d;
8536         b = rotateLeft((b + G(c, d, a) + X[ 4] + 0xe7d3fbc8), S24) + c;
8537         a = rotateLeft((a + G(b, c, d) + X[ 9] + 0x21e1cde6), S21) + b;
8538         d = rotateLeft((d + G(a, b, c) + X[14] + 0xc33707d6), S22) + a;
8539         c = rotateLeft((c + G(d, a, b) + X[ 3] + 0xf4d50d87), S23) + d;
8540         b = rotateLeft((b + G(c, d, a) + X[ 8] + 0x455a14ed), S24) + c;
8541         a = rotateLeft((a + G(b, c, d) + X[13] + 0xa9e3e905), S21) + b;
8542         d = rotateLeft((d + G(a, b, c) + X[ 2] + 0xfcefa3f8), S22) + a;
8543         c = rotateLeft((c + G(d, a, b) + X[ 7] + 0x676f02d9), S23) + d;
8544         b = rotateLeft((b + G(c, d, a) + X[12] + 0x8d2a4c8a), S24) + c;
8545
8546         //
8547         // Round 3 - H cycle, 16 times.
8548         //
8549         a = rotateLeft((a + H(b, c, d) + X[ 5] + 0xfffa3942), S31) + b;
8550         d = rotateLeft((d + H(a, b, c) + X[ 8] + 0x8771f681), S32) + a;
8551         c = rotateLeft((c + H(d, a, b) + X[11] + 0x6d9d6122), S33) + d;
8552         b = rotateLeft((b + H(c, d, a) + X[14] + 0xfde5380c), S34) + c;
8553         a = rotateLeft((a + H(b, c, d) + X[ 1] + 0xa4beea44), S31) + b;
8554         d = rotateLeft((d + H(a, b, c) + X[ 4] + 0x4bdecfa9), S32) + a;
8555         c = rotateLeft((c + H(d, a, b) + X[ 7] + 0xf6bb4b60), S33) + d;
8556         b = rotateLeft((b + H(c, d, a) + X[10] + 0xbebfbc70), S34) + c;
8557         a = rotateLeft((a + H(b, c, d) + X[13] + 0x289b7ec6), S31) + b;
8558         d = rotateLeft((d + H(a, b, c) + X[ 0] + 0xeaa127fa), S32) + a;
8559         c = rotateLeft((c + H(d, a, b) + X[ 3] + 0xd4ef3085), S33) + d;
8560         b = rotateLeft((b + H(c, d, a) + X[ 6] + 0x04881d05), S34) + c;
8561         a = rotateLeft((a + H(b, c, d) + X[ 9] + 0xd9d4d039), S31) + b;
8562         d = rotateLeft((d + H(a, b, c) + X[12] + 0xe6db99e5), S32) + a;
8563         c = rotateLeft((c + H(d, a, b) + X[15] + 0x1fa27cf8), S33) + d;
8564         b = rotateLeft((b + H(c, d, a) + X[ 2] + 0xc4ac5665), S34) + c;
8565
8566         //
8567         // Round 4 - K cycle, 16 times.
8568         //
8569         a = rotateLeft((a + K(b, c, d) + X[ 0] + 0xf4292244), S41) + b;
8570         d = rotateLeft((d + K(a, b, c) + X[ 7] + 0x432aff97), S42) + a;
8571         c = rotateLeft((c + K(d, a, b) + X[14] + 0xab9423a7), S43) + d;
8572         b = rotateLeft((b + K(c, d, a) + X[ 5] + 0xfc93a039), S44) + c;
8573         a = rotateLeft((a + K(b, c, d) + X[12] + 0x655b59c3), S41) + b;
8574         d = rotateLeft((d + K(a, b, c) + X[ 3] + 0x8f0ccc92), S42) + a;
8575         c = rotateLeft((c + K(d, a, b) + X[10] + 0xffeff47d), S43) + d;
8576         b = rotateLeft((b + K(c, d, a) + X[ 1] + 0x85845dd1), S44) + c;
8577         a = rotateLeft((a + K(b, c, d) + X[ 8] + 0x6fa87e4f), S41) + b;
8578         d = rotateLeft((d + K(a, b, c) + X[15] + 0xfe2ce6e0), S42) + a;
8579         c = rotateLeft((c + K(d, a, b) + X[ 6] + 0xa3014314), S43) + d;
8580         b = rotateLeft((b + K(c, d, a) + X[13] + 0x4e0811a1), S44) + c;
8581         a = rotateLeft((a + K(b, c, d) + X[ 4] + 0xf7537e82), S41) + b;
8582         d = rotateLeft((d + K(a, b, c) + X[11] + 0xbd3af235), S42) + a;
8583         c = rotateLeft((c + K(d, a, b) + X[ 2] + 0x2ad7d2bb), S43) + d;
8584         b = rotateLeft((b + K(c, d, a) + X[ 9] + 0xeb86d391), S44) + c;
8585
8586         H1 += a;
8587         H2 += b;
8588         H3 += c;
8589         H4 += d;
8590
8591         //
8592         // reset the offset and clean out the word buffer.
8593         //
8594         xOff = 0;
8595         for (int i = 0; i != X.length; i++)
8596         {
8597             X[i] = 0;
8598         }
8599     }
8600 }
8601
8602
8603 /**
8604  * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
8605  *
8606  * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
8607  * is the "endienness" of the word processing!
8608  */
8609 class SHA1Digest
8610     extends GeneralDigest
8611 {
8612     private static final int    DIGEST_LENGTH = 20;
8613
8614     private int     H1, H2, H3, H4, H5;
8615
8616     private int[]   X = new int[80];
8617     private int     xOff;
8618
8619         /**
8620          * Standard constructor
8621          */
8622     public SHA1Digest()
8623     {
8624         reset();
8625     }
8626
8627         /**
8628          * Copy constructor.  This will copy the state of the provided
8629          * message digest.
8630          */
8631         public SHA1Digest(SHA1Digest t)
8632         {
8633                 super(t);
8634
8635                 H1 = t.H1;
8636                 H2 = t.H2;
8637                 H3 = t.H3;
8638                 H4 = t.H4;
8639                 H5 = t.H5;
8640
8641                 System.arraycopy(t.X, 0, X, 0, t.X.length);
8642                 xOff = t.xOff;
8643         }
8644
8645     public String getAlgorithmName()
8646     {
8647         return "SHA-1";
8648     }
8649
8650     public int getDigestSize()
8651     {
8652         return DIGEST_LENGTH;
8653     }
8654
8655     protected void processWord(
8656         byte[]  in,
8657         int     inOff)
8658     {
8659         X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16)
8660                     | ((in[inOff + 2] & 0xff) << 8) | ((in[inOff + 3] & 0xff)); 
8661
8662         if (xOff == 16)
8663         {
8664             processBlock();
8665         }
8666     }
8667
8668     private void unpackWord(
8669         int     word,
8670         byte[]  out,
8671         int     outOff)
8672     {
8673         out[outOff]     = (byte)(word >>> 24);
8674         out[outOff + 1] = (byte)(word >>> 16);
8675         out[outOff + 2] = (byte)(word >>> 8);
8676         out[outOff + 3] = (byte)word;
8677     }
8678
8679     protected void processLength(
8680         long    bitLength)
8681     {
8682         if (xOff > 14)
8683         {
8684             processBlock();
8685         }
8686
8687         X[14] = (int)(bitLength >>> 32);
8688         X[15] = (int)(bitLength & 0xffffffff);
8689     }
8690
8691     public int doFinal(
8692         byte[]  out,
8693         int     outOff)
8694     {
8695         finish();
8696
8697         unpackWord(H1, out, outOff);
8698         unpackWord(H2, out, outOff + 4);
8699         unpackWord(H3, out, outOff + 8);
8700         unpackWord(H4, out, outOff + 12);
8701         unpackWord(H5, out, outOff + 16);
8702
8703         reset();
8704
8705         return DIGEST_LENGTH;
8706     }
8707
8708     /**
8709      * reset the chaining variables
8710      */
8711     public void reset()
8712     {
8713         super.reset();
8714
8715         H1 = 0x67452301;
8716         H2 = 0xefcdab89;
8717         H3 = 0x98badcfe;
8718         H4 = 0x10325476;
8719         H5 = 0xc3d2e1f0;
8720
8721         xOff = 0;
8722         for (int i = 0; i != X.length; i++)
8723         {
8724             X[i] = 0;
8725         }
8726     }
8727
8728     //
8729     // Additive constants
8730     //
8731     private static final int    Y1 = 0x5a827999;
8732     private static final int    Y2 = 0x6ed9eba1;
8733     private static final int    Y3 = 0x8f1bbcdc;
8734     private static final int    Y4 = 0xca62c1d6;
8735
8736     private int f(
8737         int    u,
8738         int    v,
8739         int    w)
8740     {
8741         return ((u & v) | ((~u) & w));
8742     }
8743
8744     private int h(
8745         int    u,
8746         int    v,
8747         int    w)
8748     {
8749         return (u ^ v ^ w);
8750     }
8751
8752     private int g(
8753         int    u,
8754         int    v,
8755         int    w)
8756     {
8757         return ((u & v) | (u & w) | (v & w));
8758     }
8759
8760     private int rotateLeft(
8761         int    x,
8762         int    n)
8763     {
8764         return (x << n) | (x >>> (32 - n));
8765     }
8766
8767     protected void processBlock()
8768     {
8769         //
8770         // expand 16 word block into 80 word block.
8771         //
8772         for (int i = 16; i <= 79; i++)
8773         {
8774             X[i] = rotateLeft((X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]), 1);
8775         }
8776
8777         //
8778         // set up working variables.
8779         //
8780         int     A = H1;
8781         int     B = H2;
8782         int     C = H3;
8783         int     D = H4;
8784         int     E = H5;
8785
8786         //
8787         // round 1
8788         //
8789         for (int j = 0; j <= 19; j++)
8790         {
8791             int     t = rotateLeft(A, 5) + f(B, C, D) + E + X[j] + Y1;
8792
8793             E = D;
8794             D = C;
8795             C = rotateLeft(B, 30);
8796             B = A;
8797             A = t;
8798         }
8799
8800         //
8801         // round 2
8802         //
8803         for (int j = 20; j <= 39; j++)
8804         {
8805             int     t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y2;
8806
8807             E = D;
8808             D = C;
8809             C = rotateLeft(B, 30);
8810             B = A;
8811             A = t;
8812         }
8813
8814         //
8815         // round 3
8816         //
8817         for (int j = 40; j <= 59; j++)
8818         {
8819             int     t = rotateLeft(A, 5) + g(B, C, D) + E + X[j] + Y3;
8820
8821             E = D;
8822             D = C;
8823             C = rotateLeft(B, 30);
8824             B = A;
8825             A = t;
8826         }
8827
8828         //
8829         // round 4
8830         //
8831         for (int j = 60; j <= 79; j++)
8832         {
8833             int     t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y4;
8834
8835             E = D;
8836             D = C;
8837             C = rotateLeft(B, 30);
8838             B = A;
8839             A = t;
8840         }
8841
8842         H1 += A;
8843         H2 += B;
8844         H3 += C;
8845         H4 += D;
8846         H5 += E;
8847
8848         //
8849         // reset the offset and clean out the word buffer.
8850         //
8851         xOff = 0;
8852         for (int i = 0; i != X.length; i++)
8853         {
8854             X[i] = 0;
8855         }
8856     }
8857 }
8858
8859
8860
8861 /**
8862  * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
8863  * depends on your application - see PKCS1 Version 2 for details.
8864  */
8865 class PKCS1Encoding
8866     implements AsymmetricBlockCipher
8867 {
8868     private static int      HEADER_LENGTH = 10;
8869
8870     private Random            random;
8871     private AsymmetricBlockCipher   engine;
8872     private boolean                 forEncryption;
8873     private boolean                 forPrivateKey;
8874
8875     public PKCS1Encoding(
8876         AsymmetricBlockCipher   cipher)
8877     {
8878         this.engine = cipher;
8879     }   
8880
8881     public AsymmetricBlockCipher getUnderlyingCipher()
8882     {
8883         return engine;
8884     }
8885
8886     public void init(
8887         boolean             forEncryption,
8888         CipherParameters    param)
8889     {
8890         AsymmetricKeyParameter  kParam;
8891
8892         if (param instanceof ParametersWithRandom)
8893         {
8894             ParametersWithRandom    rParam = (ParametersWithRandom)param;
8895
8896             this.random = rParam.getRandom();
8897             kParam = (AsymmetricKeyParameter)rParam.getParameters();
8898         }
8899         else
8900         {
8901             this.random = new Random();
8902             kParam = (AsymmetricKeyParameter)param;
8903         }
8904
8905         engine.init(forEncryption, kParam);
8906
8907         this.forPrivateKey = kParam.isPrivate();
8908         this.forEncryption = forEncryption;
8909     }
8910
8911     public int getInputBlockSize()
8912     {
8913         int     baseBlockSize = engine.getInputBlockSize();
8914
8915         if (forEncryption)
8916         {
8917             return baseBlockSize - HEADER_LENGTH;
8918         }
8919         else
8920         {
8921             return baseBlockSize;
8922         }
8923     }
8924
8925     public int getOutputBlockSize()
8926     {
8927         int     baseBlockSize = engine.getOutputBlockSize();
8928
8929         if (forEncryption)
8930         {
8931             return baseBlockSize;
8932         }
8933         else
8934         {
8935             return baseBlockSize - HEADER_LENGTH;
8936         }
8937     }
8938
8939     public byte[] processBlock(
8940         byte[]  in,
8941         int     inOff,
8942         int     inLen)
8943         throws InvalidCipherTextException
8944     {
8945         if (forEncryption)
8946         {
8947             return encodeBlock(in, inOff, inLen);
8948         }
8949         else
8950         {
8951             return decodeBlock(in, inOff, inLen);
8952         }
8953     }
8954
8955     private byte[] encodeBlock(
8956         byte[]  in,
8957         int     inOff,
8958         int     inLen)
8959         throws InvalidCipherTextException
8960     {
8961         byte[]  block = new byte[engine.getInputBlockSize()];
8962
8963         if (forPrivateKey)
8964         {
8965             block[0] = 0x01;                        // type code 1
8966
8967             for (int i = 1; i != block.length - inLen - 1; i++)
8968             {
8969                 block[i] = (byte)0xFF;
8970             }
8971         }
8972         else
8973         {
8974             random.nextBytes(block);                // random fill
8975
8976             block[0] = 0x02;                        // type code 2
8977
8978             //
8979             // a zero byte marks the end of the padding, so all
8980             // the pad bytes must be non-zero.
8981             //
8982             for (int i = 1; i != block.length - inLen - 1; i++)
8983             {
8984                 while (block[i] == 0)
8985                 {
8986                     block[i] = (byte)random.nextInt();
8987                 }
8988             }
8989         }
8990
8991         block[block.length - inLen - 1] = 0x00;       // mark the end of the padding
8992         System.arraycopy(in, inOff, block, block.length - inLen, inLen);
8993
8994         return engine.processBlock(block, 0, block.length);
8995     }
8996
8997     /**
8998      * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
8999      */
9000     private byte[] decodeBlock(
9001         byte[]  in,
9002         int     inOff,
9003         int     inLen)
9004         throws InvalidCipherTextException
9005     {
9006         byte[]  block = engine.processBlock(in, inOff, inLen);
9007
9008         if (block.length < getOutputBlockSize())
9009         {
9010             throw new InvalidCipherTextException("block truncated");
9011         }
9012
9013         if (block[0] != 1 && block[0] != 2)
9014         {
9015             throw new InvalidCipherTextException("unknown block type");
9016         }
9017
9018         //
9019         // find and extract the message block.
9020         //
9021         int start;
9022
9023         for (start = 1; start != block.length; start++)
9024         {
9025             if (block[start] == 0)
9026             {
9027                 break;
9028             }
9029         }
9030
9031         start++;           // data should start at the next byte
9032
9033         if (start >= block.length || start < HEADER_LENGTH)
9034         {
9035             throw new InvalidCipherTextException("no data in block");
9036         }
9037
9038         byte[]  result = new byte[block.length - start];
9039
9040         System.arraycopy(block, start, result, 0, result.length);
9041
9042         return result;
9043     }
9044 }
9045 \r
9046 \r
9047 class RC4Engine implements StreamCipher\r
9048 {\r
9049     private final static int STATE_LENGTH = 256;\r
9050 \r
9051     /*\r
9052      * variables to hold the state of the RC4 engine\r
9053      * during encryption and decryption\r
9054      */\r
9055 \r
9056     private byte[]      engineState = null;\r
9057     private int         x = 0;\r
9058     private int         y = 0;\r
9059     private byte[]      workingKey = null;\r
9060 \r
9061     /**\r
9062      * initialise a RC4 cipher.\r
9063      *\r
9064      * @param forEncryption whether or not we are for encryption.\r
9065      * @param params the parameters required to set up the cipher.\r
9066      * @exception IllegalArgumentException if the params argument is\r
9067      * inappropriate.\r
9068      */\r
9069     public void init(\r
9070         boolean             forEncryption, \r
9071         CipherParameters     params\r
9072     )\r
9073     {\r
9074         if (params instanceof KeyParameter)\r
9075         {\r
9076             /* \r
9077              * RC4 encryption and decryption is completely\r
9078              * symmetrical, so the 'forEncryption' is \r
9079              * irrelevant.\r
9080              */\r
9081             workingKey = ((KeyParameter)params).getKey();\r
9082             setKey(workingKey);\r
9083 \r
9084             return;\r
9085         }\r
9086 \r
9087         throw new IllegalArgumentException("invalid parameter passed to RC4 init - " + params.getClass().getName());\r
9088     }\r
9089 \r
9090     public String getAlgorithmName()\r
9091     {\r
9092         return "RC4";\r
9093     }\r
9094 \r
9095     public byte returnByte(byte in)\r
9096     {\r
9097         x = (x + 1) & 0xff;\r
9098         y = (engineState[x] + y) & 0xff;\r
9099 \r
9100         // swap\r
9101         byte tmp = engineState[x];\r
9102         engineState[x] = engineState[y];\r
9103         engineState[y] = tmp;\r
9104 \r
9105         // xor\r
9106         return (byte)(in ^ engineState[(engineState[x] + engineState[y]) & 0xff]);\r
9107     }\r
9108 \r
9109     public void processBytes(\r
9110         byte[]     in, \r
9111         int     inOff, \r
9112         int     len, \r
9113         byte[]     out, \r
9114         int     outOff\r
9115     )\r
9116     {\r
9117         if ((inOff + len) > in.length)\r
9118         {\r
9119             throw new DataLengthException("input buffer too short");\r
9120         }\r
9121 \r
9122         if ((outOff + len) > out.length)\r
9123         {\r
9124             throw new DataLengthException("output buffer too short");\r
9125         }\r
9126 \r
9127         for (int i = 0; i < len ; i++)\r
9128         {\r
9129             x = (x + 1) & 0xff;\r
9130             y = (engineState[x] + y) & 0xff;\r
9131 \r
9132             // swap\r
9133             byte tmp = engineState[x];\r
9134             engineState[x] = engineState[y];\r
9135             engineState[y] = tmp;\r
9136 \r
9137             // xor\r
9138             out[i+outOff] = (byte)(in[i + inOff]\r
9139                     ^ engineState[(engineState[x] + engineState[y]) & 0xff]);\r
9140         }\r
9141     }\r
9142 \r
9143     public void reset()\r
9144     {\r
9145         setKey(workingKey);\r
9146     }\r
9147 \r
9148     // Private implementation\r
9149 \r
9150     private void setKey(byte[] keyBytes)\r
9151     {\r
9152         workingKey = keyBytes;\r
9153 \r
9154         // System.out.println("the key length is ; "+ workingKey.length);\r
9155 \r
9156         x = 0;\r
9157         y = 0;\r
9158 \r
9159         if (engineState == null)\r
9160         {\r
9161             engineState = new byte[STATE_LENGTH];\r
9162         }\r
9163 \r
9164         // reset the state of the engine\r
9165         for (int i=0; i < STATE_LENGTH; i++)\r
9166         {\r
9167             engineState[i] = (byte)i;\r
9168         }\r
9169         \r
9170         int i1 = 0;\r
9171         int i2 = 0;\r
9172 \r
9173         for (int i=0; i < STATE_LENGTH; i++)\r
9174         {\r
9175             i2 = ((keyBytes[i1] & 0xff) + engineState[i] + i2) & 0xff;\r
9176             // do the byte-swap inline\r
9177             byte tmp = engineState[i];\r
9178             engineState[i] = engineState[i2];\r
9179             engineState[i2] = tmp;\r
9180             i1 = (i1+1) % keyBytes.length; \r
9181         }\r
9182     }\r
9183 }\r
9184
9185
9186
9187 /**
9188  * this does your basic RSA algorithm.
9189  */
9190 class RSAEngine
9191     implements AsymmetricBlockCipher
9192 {
9193     private RSAKeyParameters        key;
9194     private boolean                 forEncryption;
9195
9196     /**
9197      * initialise the RSA engine.
9198      *
9199      * @param forEncryption true if we are encrypting, false otherwise.
9200      * @param param the necessary RSA key parameters.
9201      */
9202     public void init(
9203         boolean             forEncryption,
9204         CipherParameters    param)
9205     {
9206         this.key = (RSAKeyParameters)param;
9207         this.forEncryption = forEncryption;
9208     }
9209
9210     /**
9211      * Return the maximum size for an input block to this engine.
9212      * For RSA this is always one byte less than the key size on
9213      * encryption, and the same length as the key size on decryption.
9214      *
9215      * @return maximum size for an input block.
9216      */
9217     public int getInputBlockSize()
9218     {
9219         int     bitSize = key.getModulus().bitLength();
9220
9221         if (forEncryption)
9222         {
9223             return (bitSize + 7) / 8 - 1;
9224         }
9225         else
9226         {
9227             return (bitSize + 7) / 8;
9228         }
9229     }
9230
9231     /**
9232      * Return the maximum size for an output block to this engine.
9233      * For RSA this is always one byte less than the key size on
9234      * decryption, and the same length as the key size on encryption.
9235      *
9236      * @return maximum size for an output block.
9237      */
9238     public int getOutputBlockSize()
9239     {
9240         int     bitSize = key.getModulus().bitLength();
9241
9242         if (forEncryption)
9243         {
9244             return (bitSize + 7) / 8;
9245         }
9246         else
9247         {
9248             return (bitSize + 7) / 8 - 1;
9249         }
9250     }
9251
9252     /**
9253      * Process a single block using the basic RSA algorithm.
9254      *
9255      * @param in the input array.
9256      * @param inOff the offset into the input buffer where the data starts.
9257      * @param inLen the length of the data to be processed.
9258      * @return the result of the RSA process.
9259      * @exception DataLengthException the input block is too large.
9260      */
9261     public byte[] processBlock(
9262         byte[]  in,
9263         int     inOff,
9264         int     inLen)
9265     {
9266         if (inLen > (getInputBlockSize() + 1))
9267         {
9268             throw new DataLengthException("input too large for RSA cipher.\n");
9269         }
9270         else if (inLen == (getInputBlockSize() + 1) && (in[inOff] & 0x80) != 0)
9271         {
9272             throw new DataLengthException("input too large for RSA cipher.\n");
9273         }
9274
9275         byte[]  block;
9276
9277         if (inOff != 0 || inLen != in.length)
9278         {
9279             block = new byte[inLen];
9280
9281             System.arraycopy(in, inOff, block, 0, inLen);
9282         }
9283         else
9284         {
9285             block = in;
9286         }
9287
9288         BigInteger  input = new BigInteger(1, block);
9289         byte[]      output;
9290
9291         if (key instanceof RSAPrivateCrtKeyParameters)
9292         {
9293             //
9294             // we have the extra factors, use the Chinese Remainder Theorem - the author
9295             // wishes to express his thanks to Dirk Bonekaemper at rtsffm.com for 
9296             // advice regarding the expression of this.
9297             //
9298             RSAPrivateCrtKeyParameters crtKey = (RSAPrivateCrtKeyParameters)key;
9299
9300             BigInteger d = crtKey.getExponent();
9301             BigInteger p = crtKey.getP();
9302             BigInteger q = crtKey.getQ();
9303             BigInteger dP = crtKey.getDP();
9304             BigInteger dQ = crtKey.getDQ();
9305             BigInteger qInv = crtKey.getQInv();
9306     
9307             BigInteger mP, mQ, h, m;
9308     
9309             // mP = ((input mod p) ^ dP)) mod p
9310             mP = (input.remainder(p)).modPow(dP, p);
9311     
9312             // mQ = ((input mod q) ^ dQ)) mod q
9313             mQ = (input.remainder(q)).modPow(dQ, q);
9314     
9315             // h = qInv * (mP - mQ) mod p
9316             h = mP.subtract(mQ);
9317             h = h.multiply(qInv);
9318             h = h.mod(p);               // mod (in Java) returns the positive residual
9319     
9320             // m = h * q + mQ
9321             m = h.multiply(q);
9322             m = m.add(mQ);
9323     
9324             output = m.toByteArray();
9325         }
9326         else
9327         {
9328             output = input.modPow(
9329                         key.getExponent(), key.getModulus()).toByteArray();
9330         }
9331
9332         if (forEncryption)
9333         {
9334             if (output[0] == 0 && output.length > getOutputBlockSize())        // have ended up with an extra zero byte, copy down.
9335             {
9336                 byte[]  tmp = new byte[output.length - 1];
9337
9338                 System.arraycopy(output, 1, tmp, 0, tmp.length);
9339
9340                 return tmp;
9341             }
9342
9343             if (output.length < getOutputBlockSize())     // have ended up with less bytes than normal, lengthen
9344             {
9345                 byte[]  tmp = new byte[getOutputBlockSize()];
9346
9347                 System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length);
9348
9349                 return tmp;
9350             }
9351         }
9352         else
9353         {
9354             if (output[0] == 0)        // have ended up with an extra zero byte, copy down.
9355             {
9356                 byte[]  tmp = new byte[output.length - 1];
9357
9358                 System.arraycopy(output, 1, tmp, 0, tmp.length);
9359
9360                 return tmp;
9361             }
9362         }
9363         return output;
9364     }
9365 }
9366
9367 /**
9368  * this exception is thrown whenever we find something we don't expect in a
9369  * message.
9370  */
9371 class InvalidCipherTextException 
9372     extends CryptoException
9373 {
9374     /**
9375      * base constructor.
9376      */
9377     public InvalidCipherTextException()
9378     {
9379     }
9380
9381     /**
9382      * create a InvalidCipherTextException with the given message.
9383      *
9384      * @param message the message to be carried with the exception.
9385      */
9386     public InvalidCipherTextException(
9387         String  message)
9388     {
9389         super(message);
9390     }
9391 }
9392
9393
9394
9395 class DigestInputStream
9396     extends FilterInputStream
9397 {
9398     protected Digest digest;
9399
9400     public DigestInputStream(
9401         InputStream stream,
9402         Digest      digest)
9403     {
9404         super(stream);
9405         this.digest = digest;
9406     }
9407
9408     public int read()
9409         throws IOException
9410     {
9411         int b = in.read();
9412
9413         if (b >= 0)
9414         {
9415             digest.update((byte)b);
9416         }
9417         return b;
9418     }
9419
9420     public int read(
9421         byte[] b,
9422         int off,
9423         int len)
9424         throws IOException
9425     {
9426         int n = in.read(b, off, len);
9427         if (n > 0)
9428         {
9429             digest.update(b, off, n);
9430         }
9431         return n;
9432     }
9433
9434     public Digest getDigest()
9435     {
9436         return digest;
9437     }
9438 }
9439
9440
9441
9442 class DigestOutputStream
9443     extends FilterOutputStream
9444 {
9445     protected Digest digest;
9446
9447     public DigestOutputStream(
9448         OutputStream    stream,
9449         Digest          digest)
9450     {
9451         super(stream);
9452         this.digest = digest;
9453     }
9454
9455     public void write(int b)
9456         throws IOException
9457     {
9458         digest.update((byte)b);
9459         out.write(b);
9460     }
9461
9462     public void write(
9463         byte[] b,
9464         int off,
9465         int len)
9466         throws IOException
9467     {
9468         digest.update(b, off, len);
9469         out.write(b, off, len);
9470     }
9471
9472     public Digest getDigest()
9473     {
9474         return digest;
9475     }
9476 }
9477
9478
9479 /**
9480  * The base class for parameters to key generators.
9481  */
9482 class KeyGenerationParameters
9483 {
9484     private Random    random;
9485     private int             strength;
9486
9487     /**
9488      * initialise the generator with a source of randomness
9489      * and a strength (in bits).
9490      *
9491      * @param random the random byte source.
9492      * @param strength the size, in bits, of the keys we want to produce.
9493      */
9494     public KeyGenerationParameters(
9495         Random    random,
9496         int             strength)
9497     {
9498         this.random = random;
9499         this.strength = strength;
9500     }
9501
9502     /**
9503      * return the random source associated with this
9504      * generator.
9505      *
9506      * @return the generators random source.
9507      */
9508     public Random getRandom()
9509     {
9510         return random;
9511     }
9512
9513     /**
9514      * return the bit strength for keys produced by this generator,
9515      *
9516      * @return the strength of the keys this generator produces (in bits).
9517      */
9518     public int getStrength()
9519     {
9520         return strength;
9521     }
9522 }
9523
9524
9525 class AsymmetricKeyParameter
9526         implements CipherParameters
9527 {
9528     boolean privateKey;
9529
9530     public AsymmetricKeyParameter(
9531         boolean privateKey)
9532     {
9533         this.privateKey = privateKey;
9534     }
9535
9536     public boolean isPrivate()
9537     {
9538         return privateKey;
9539     }
9540 }
9541
9542
9543 class KeyParameter
9544         implements CipherParameters
9545 {
9546     private byte[]  key;
9547
9548     public KeyParameter(
9549         byte[]  key)
9550     {
9551         this(key, 0, key.length);
9552     }
9553
9554     public KeyParameter(
9555         byte[]  key,
9556         int     keyOff,
9557         int     keyLen)
9558     {
9559         this.key = new byte[keyLen];
9560
9561         System.arraycopy(key, keyOff, this.key, 0, keyLen);
9562     }
9563
9564     public byte[] getKey()
9565     {
9566         return key;
9567     }
9568 }
9569
9570
9571
9572 class ParametersWithRandom
9573     implements CipherParameters
9574 {
9575     private Random        random;
9576     private CipherParameters    parameters;
9577
9578     public ParametersWithRandom(
9579         CipherParameters    parameters,
9580         Random        random)
9581     {
9582         this.random = random;
9583         this.parameters = parameters;
9584     }
9585
9586     public ParametersWithRandom(
9587         CipherParameters    parameters)
9588     {
9589         this.random = null;
9590         this.parameters = parameters;
9591     }
9592
9593     public Random getRandom()
9594     {
9595         if (random == null)
9596         {
9597             random = new Random();
9598         }
9599         return random;
9600     }
9601
9602     public CipherParameters getParameters()
9603     {
9604         return parameters;
9605     }
9606 }
9607
9608
9609
9610 class RSAKeyParameters
9611     extends AsymmetricKeyParameter
9612 {
9613     private BigInteger      modulus;
9614     private BigInteger      exponent;
9615
9616     public RSAKeyParameters(
9617         boolean     isPrivate,
9618         BigInteger  modulus,
9619         BigInteger  exponent)
9620     {
9621         super(isPrivate);
9622
9623         this.modulus = modulus;
9624         this.exponent = exponent;
9625     }   
9626
9627     public BigInteger getModulus()
9628     {
9629         return modulus;
9630     }
9631
9632     public BigInteger getExponent()
9633     {
9634         return exponent;
9635     }
9636 }
9637
9638
9639 class RSAPrivateCrtKeyParameters
9640     extends RSAKeyParameters
9641 {
9642     private BigInteger  e;
9643     private BigInteger  p;
9644     private BigInteger  q;
9645     private BigInteger  dP;
9646     private BigInteger  dQ;
9647     private BigInteger  qInv;
9648
9649     /**
9650      * 
9651      */
9652     public RSAPrivateCrtKeyParameters(
9653         BigInteger  modulus,
9654         BigInteger  publicExponent,
9655         BigInteger  privateExponent,
9656         BigInteger  p,
9657         BigInteger  q,
9658         BigInteger  dP,
9659         BigInteger  dQ,
9660         BigInteger  qInv)
9661     {
9662         super(true, modulus, privateExponent);
9663
9664         this.e = publicExponent;
9665         this.p = p;
9666         this.q = q;
9667         this.dP = dP;
9668         this.dQ = dQ;
9669         this.qInv = qInv;
9670     }
9671
9672     public BigInteger getPublicExponent()
9673     {
9674         return e;
9675     }
9676
9677     public BigInteger getP()
9678     {
9679         return p;
9680     }
9681
9682     public BigInteger getQ()
9683     {
9684         return q;
9685     }
9686
9687     public BigInteger getDP()
9688     {
9689         return dP;
9690     }
9691
9692     public BigInteger getDQ()
9693     {
9694         return dQ;
9695     }
9696
9697     public BigInteger getQInv()
9698     {
9699         return qInv;
9700     }
9701 }
9702
9703 /**
9704  * the foundation class for the exceptions thrown by the crypto packages.
9705  */
9706 class RuntimeCryptoException 
9707     extends RuntimeException
9708 {
9709     /**
9710      * base constructor.
9711      */
9712     public RuntimeCryptoException()
9713     {
9714     }
9715
9716     /**
9717      * create a RuntimeCryptoException with the given message.
9718      *
9719      * @param message the message to be carried with the exception.
9720      */
9721     public RuntimeCryptoException(
9722         String  message)
9723     {
9724         super(message);
9725     }
9726 }
9727
9728 /**
9729  * a wrapper for block ciphers with a single byte block size, so that they
9730  * can be treated like stream ciphers.
9731  */
9732 class StreamBlockCipher
9733     implements StreamCipher
9734 {
9735     private BlockCipher  cipher;
9736
9737     private byte[]  oneByte = new byte[1];
9738
9739     /**
9740      * basic constructor.
9741      *
9742      * @param cipher the block cipher to be wrapped.
9743      * @exception IllegalArgumentException if the cipher has a block size other than
9744      * one.
9745      */
9746     public StreamBlockCipher(
9747         BlockCipher cipher)
9748     {
9749         if (cipher.getBlockSize() != 1)
9750         {
9751             throw new IllegalArgumentException("block cipher block size != 1.");
9752         }
9753
9754         this.cipher = cipher;
9755     }
9756
9757     /**
9758      * initialise the underlying cipher.
9759      *
9760      * @param forEncryption true if we are setting up for encryption, false otherwise.
9761      * @param param the necessary parameters for the underlying cipher to be initialised.
9762      */
9763     public void init(
9764         boolean forEncryption,
9765         CipherParameters params)
9766     {
9767         cipher.init(forEncryption, params);
9768     }
9769
9770     /**
9771      * return the name of the algorithm we are wrapping.
9772      *
9773      * @return the name of the algorithm we are wrapping.
9774      */
9775     public String getAlgorithmName()
9776     {
9777         return cipher.getAlgorithmName();
9778     }
9779
9780     /**
9781      * encrypt/decrypt a single byte returning the result.
9782      *
9783      * @param in the byte to be processed.
9784      * @return the result of processing the input byte.
9785      */
9786     public byte returnByte(
9787         byte    in)
9788     {
9789         oneByte[0] = in;
9790
9791         cipher.processBlock(oneByte, 0, oneByte, 0);
9792
9793         return oneByte[0];
9794     }
9795
9796     /**
9797      * process a block of bytes from in putting the result into out.
9798      * 
9799      * @param in the input byte array.
9800      * @param inOff the offset into the in array where the data to be processed starts.
9801      * @param len the number of bytes to be processed.
9802      * @param out the output buffer the processed bytes go into.   
9803      * @param outOff the offset into the output byte array the processed data stars at.
9804      * @exception DataLengthException if the output buffer is too small.
9805      */
9806     public void processBytes(
9807         byte[]  in,
9808         int     inOff,
9809         int     len,
9810         byte[]  out,
9811         int     outOff)
9812         throws DataLengthException
9813     {
9814         if (outOff + len > out.length)
9815         {
9816             throw new DataLengthException("output buffer too small in processBytes()");
9817         }
9818
9819         for (int i = 0; i != len; i++)
9820         {
9821                 cipher.processBlock(in, inOff + i, out, outOff + i);
9822         }
9823     }
9824
9825     /**
9826      * reset the underlying cipher. This leaves it in the same state
9827      * it was at after the last init (if there was one).
9828      */
9829     public void reset()
9830     {
9831         cipher.reset();
9832     }
9833 }
9834
9835 /**
9836  * the interface stream ciphers conform to.
9837  */
9838 interface StreamCipher
9839 {
9840     /**
9841      * Initialise the cipher.
9842      *
9843      * @param forEncryption if true the cipher is initialised for
9844      *  encryption, if false for decryption.
9845      * @param param the key and other data required by the cipher.
9846      * @exception IllegalArgumentException if the params argument is
9847      * inappropriate.
9848      */
9849     public void init(boolean forEncryption, CipherParameters params)
9850         throws IllegalArgumentException;
9851
9852     /**
9853      * Return the name of the algorithm the cipher implements.
9854      *
9855      * @return the name of the algorithm the cipher implements.
9856      */
9857     public String getAlgorithmName();
9858
9859     /**
9860      * encrypt/decrypt a single byte returning the result.
9861      *
9862      * @param in the byte to be processed.
9863      * @return the result of processing the input byte.
9864      */
9865     public byte returnByte(byte in);
9866
9867     /**
9868      * process a block of bytes from in putting the result into out.
9869      *
9870      * @param in the input byte array.
9871      * @param inOff the offset into the in array where the data to be processed starts.
9872      * @param len the number of bytes to be processed.
9873      * @param out the output buffer the processed bytes go into.
9874      * @param outOff the offset into the output byte array the processed data stars at.
9875      * @exception DataLengthException if the output buffer is too small.
9876      */
9877     public void processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
9878         throws DataLengthException;
9879
9880     /**
9881      * reset the cipher. This leaves it in the same state
9882      * it was at after the last init (if there was one).
9883      */
9884     public void reset();
9885 }
9886
9887 class Base64
9888 {
9889         private static final byte[] encodingTable =
9890                 {
9891                     (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
9892             (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
9893             (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
9894             (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
9895                     (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
9896             (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
9897             (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
9898             (byte)'v',
9899                     (byte)'w', (byte)'x', (byte)'y', (byte)'z',
9900                     (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
9901             (byte)'7', (byte)'8', (byte)'9',
9902                     (byte)'+', (byte)'/'
9903                 };
9904
9905         /**
9906          * encode the input data producong a base 64 encoded byte array.
9907          *
9908          * @return a byte array containing the base 64 encoded data.
9909          */
9910         public static byte[] encode(
9911                 byte[]  data)
9912         {
9913                 byte[]  bytes;
9914                 
9915                 int modulus = data.length % 3;
9916                 if (modulus == 0)
9917                 {
9918                         bytes = new byte[4 * data.length / 3];
9919                 }
9920                 else
9921                 {
9922                         bytes = new byte[4 * ((data.length / 3) + 1)];
9923                 }
9924
9925         int dataLength = (data.length - modulus);
9926                 int a1, a2, a3;
9927                 for (int i = 0, j = 0; i < dataLength; i += 3, j += 4)
9928                 {
9929                         a1 = data[i] & 0xff;
9930                         a2 = data[i + 1] & 0xff;
9931                         a3 = data[i + 2] & 0xff;
9932
9933                         bytes[j] = encodingTable[(a1 >>> 2) & 0x3f];
9934                         bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f];
9935                         bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f];
9936                         bytes[j + 3] = encodingTable[a3 & 0x3f];
9937                 }
9938
9939                 /*
9940                  * process the tail end.
9941                  */
9942                 int     b1, b2, b3;
9943                 int     d1, d2;
9944
9945                 switch (modulus)
9946                 {
9947                 case 0:         /* nothing left to do */
9948                         break;
9949                 case 1:
9950                         d1 = data[data.length - 1] & 0xff;
9951                         b1 = (d1 >>> 2) & 0x3f;
9952                         b2 = (d1 << 4) & 0x3f;
9953
9954                         bytes[bytes.length - 4] = encodingTable[b1];
9955                         bytes[bytes.length - 3] = encodingTable[b2];
9956                         bytes[bytes.length - 2] = (byte)'=';
9957                         bytes[bytes.length - 1] = (byte)'=';
9958                         break;
9959                 case 2:
9960                         d1 = data[data.length - 2] & 0xff;
9961                         d2 = data[data.length - 1] & 0xff;
9962
9963                         b1 = (d1 >>> 2) & 0x3f;
9964                         b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
9965                         b3 = (d2 << 2) & 0x3f;
9966
9967                         bytes[bytes.length - 4] = encodingTable[b1];
9968                         bytes[bytes.length - 3] = encodingTable[b2];
9969                         bytes[bytes.length - 2] = encodingTable[b3];
9970                         bytes[bytes.length - 1] = (byte)'=';
9971                         break;
9972                 }
9973
9974                 return bytes;
9975         }
9976
9977         /*
9978          * set up the decoding table.
9979          */
9980         private static final byte[] decodingTable;
9981
9982         static
9983         {
9984                 decodingTable = new byte[128];
9985
9986                 for (int i = 'A'; i <= 'Z'; i++)
9987                 {
9988                         decodingTable[i] = (byte)(i - 'A');
9989                 }
9990
9991                 for (int i = 'a'; i <= 'z'; i++)
9992                 {
9993                         decodingTable[i] = (byte)(i - 'a' + 26);
9994                 }
9995
9996                 for (int i = '0'; i <= '9'; i++)
9997                 {
9998                         decodingTable[i] = (byte)(i - '0' + 52);
9999                 }
10000
10001                 decodingTable['+'] = 62;
10002                 decodingTable['/'] = 63;
10003         }
10004
10005         /**
10006          * decode the base 64 encoded input data.
10007          *
10008          * @return a byte array representing the decoded data.
10009          */
10010         public static byte[] decode(
10011                 byte[]  data)
10012         {
10013                 byte[]  bytes;
10014                 byte    b1, b2, b3, b4;
10015
10016                 if (data[data.length - 2] == '=')
10017                 {
10018                         bytes = new byte[(((data.length / 4) - 1) * 3) + 1];
10019                 }
10020                 else if (data[data.length - 1] == '=')
10021                 {
10022                         bytes = new byte[(((data.length / 4) - 1) * 3) + 2];
10023                 }
10024                 else
10025                 {
10026                         bytes = new byte[((data.length / 4) * 3)];
10027                 }
10028
10029                 for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3)
10030                 {
10031                         b1 = decodingTable[data[i]];
10032                         b2 = decodingTable[data[i + 1]];
10033                         b3 = decodingTable[data[i + 2]];
10034                         b4 = decodingTable[data[i + 3]];
10035
10036                         bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
10037                         bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
10038                         bytes[j + 2] = (byte)((b3 << 6) | b4);
10039                 }
10040
10041                 if (data[data.length - 2] == '=')
10042                 {
10043                         b1 = decodingTable[data[data.length - 4]];
10044                         b2 = decodingTable[data[data.length - 3]];
10045
10046                         bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
10047                 }
10048                 else if (data[data.length - 1] == '=')
10049                 {
10050                         b1 = decodingTable[data[data.length - 4]];
10051                         b2 = decodingTable[data[data.length - 3]];
10052                         b3 = decodingTable[data[data.length - 2]];
10053
10054                         bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
10055                         bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
10056                 }
10057                 else
10058                 {
10059                         b1 = decodingTable[data[data.length - 4]];
10060                         b2 = decodingTable[data[data.length - 3]];
10061                         b3 = decodingTable[data[data.length - 2]];
10062                         b4 = decodingTable[data[data.length - 1]];
10063
10064                         bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
10065                         bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
10066                         bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
10067                 }
10068
10069                 return bytes;
10070         }
10071
10072         /**
10073          * decode the base 64 encoded String data.
10074          *
10075          * @return a byte array representing the decoded data.
10076          */
10077         public static byte[] decode(
10078                 String  data)
10079         {
10080                 byte[]  bytes;
10081                 byte    b1, b2, b3, b4;
10082
10083                 if (data.charAt(data.length() - 2) == '=')
10084                 {
10085                         bytes = new byte[(((data.length() / 4) - 1) * 3) + 1];
10086                 }
10087                 else if (data.charAt(data.length() - 1) == '=')
10088                 {
10089                         bytes = new byte[(((data.length() / 4) - 1) * 3) + 2];
10090                 }
10091                 else
10092                 {
10093                         bytes = new byte[((data.length() / 4) * 3)];
10094                 }
10095
10096                 for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3)
10097                 {
10098                         b1 = decodingTable[data.charAt(i)];
10099                         b2 = decodingTable[data.charAt(i + 1)];
10100                         b3 = decodingTable[data.charAt(i + 2)];
10101                         b4 = decodingTable[data.charAt(i + 3)];
10102
10103                         bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
10104                         bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
10105                         bytes[j + 2] = (byte)((b3 << 6) | b4);
10106                 }
10107
10108                 if (data.charAt(data.length() - 2) == '=')
10109                 {
10110                         b1 = decodingTable[data.charAt(data.length() - 4)];
10111                         b2 = decodingTable[data.charAt(data.length() - 3)];
10112
10113                         bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
10114                 }
10115                 else if (data.charAt(data.length() - 1) == '=')
10116                 {
10117                         b1 = decodingTable[data.charAt(data.length() - 4)];
10118                         b2 = decodingTable[data.charAt(data.length() - 3)];
10119                         b3 = decodingTable[data.charAt(data.length() - 2)];
10120
10121                         bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
10122                         bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
10123                 }
10124                 else
10125                 {
10126                         b1 = decodingTable[data.charAt(data.length() - 4)];
10127                         b2 = decodingTable[data.charAt(data.length() - 3)];
10128                         b3 = decodingTable[data.charAt(data.length() - 2)];
10129                         b4 = decodingTable[data.charAt(data.length() - 1)];
10130
10131                         bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
10132                         bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
10133                         bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
10134                 }
10135
10136                 return bytes;
10137         }
10138 }