KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ca > commons > security > asn1 > DERCoder


1
2 package com.ca.commons.security.asn1;
3
4 import java.math.BigInteger JavaDoc;
5 import java.util.StringTokenizer JavaDoc;
6
7 /**
8  * This class provides the facilities of encoding and decoding ASN1Objects
9  * using Distinguished Encoding Rules (DER). The class is only used in this
10  * package.
11  * @see iss.security.asn1.ASN1Object
12  */

13 public class DERCoder implements java.io.Serializable JavaDoc
14 {
15
16     /**
17      * Default constructor.
18      */

19     public DERCoder()
20     {}
21     
22     /********************************/
23     /* DER Encoding */
24     /********************************/
25     
26     /**
27      * DER encoding -- encodes an ASN1Object to a byte array
28      * @param input the ASN1Object to be encoded
29      * @return the encoded byte array
30      * @exception iss.security.asn1.ASN1Exception if any error
31      * occurred in the encoding process
32      */

33     public byte [] encode(ASN1Object input) throws ASN1Exception
34     {
35         int length;
36         byte [] buffer = new byte[8192];
37         try
38         {
39             length = encode(input, buffer, 0);
40         }
41         catch(ArrayIndexOutOfBoundsException JavaDoc e)
42         {
43             throw new ASN1Exception("ASN.1 Object too big");
44         }
45         byte [] result = new byte[length];
46         for (int i = 0; i < length; i++)
47         {
48             result[length-i-1] = buffer[i];
49         }
50         return result;
51     }
52     
53     /**
54      * DER encoding -- encodes an ASN1Object to a byte array
55      * @param input the ASN1Object to be encoded
56      * @param buffer the buffer to hold the encoded byte array
57      * @param offset the starting index of the buffer
58      * @return the length of the encoded bytes
59      * @exception iss.security.asn1.ASN1Exception if any error
60      * occurred in the encoding process
61      */

62     public int encode(ASN1Object input, byte [] buffer, int offset)
63     throws ASN1Exception
64     {
65         /* call different method for different ASN.1 type */
66         int tag = input.getASN1Type().getTag();
67         switch (tag)
68         {
69         case 1:
70             return encodeBOOLEAN(input, buffer, offset);
71         case 2:
72             return encodeINTEGER(input, buffer, offset);
73         case 3:
74             return encodeBITSTRING(input, buffer, offset);
75         case 4:
76             return encodeOCTETSTRING(input, buffer, offset);
77         case 5:
78             return encodeNULL(input, buffer, offset);
79         case 6:
80             return encodeOBJECTID(input, buffer, offset);
81         case 10:
82             return encodeENUMERATED(input,buffer,offset);
83         case 19:
84             return encodePrintableString(input, buffer, offset);
85         case 20:
86             // case 20: return encodeT61String(input, buffer, offset);
87
case 22:
88             return encodeIA5String(input, buffer, offset);
89         case 23:
90             return encodeUTCTime(input, buffer, offset);
91         case 24:
92             return encodeGeneralizedTime(input, buffer, offset);
93         case 28:
94             return encodeUniversalString(input, buffer, offset);
95         case 30:
96             return encodeBMPSTRING(input, buffer, offset);
97         case 48:
98         case 49:
99             return encodeSEQUENCE((Sequence)input, buffer, offset);
100             // case 49: return encodeSET(input, buffer, offset);
101
case 128:
102             return encodeCONTEXT(input, buffer, offset);
103         }
104         throw new ASN1Exception(input.getASN1Type().toString() +
105                                 " -- Unknown type");
106     }
107     
108     /**
109      * Encodes the length.
110      */

111     private int encodeLength(int length, byte [] stream, int offset)
112     {
113         if (length >= 0 && length <= 127)
114         {
115             stream[offset++] = (byte) length;
116         }
117         else
118         {
119             int count = 0;
120             while (length != 0)
121             {
122                 stream[offset++] = (byte) length;
123                 length >>>= 8;
124                 count++;
125             }
126             stream[offset++] = (byte) ((count)|0x80);
127         }
128         return offset;
129     }
130     
131     /**
132      * Encodes BOOLEAN.
133      */

134     private int encodeBOOLEAN(ASN1Object o, byte [] stream, int offset)
135     {
136         boolean v = ((Boolean JavaDoc) o.getValue()).booleanValue();
137         stream[offset++] = (byte) (v?1:0);
138         stream[offset++] = 1;
139         stream[offset++] = (byte) o.getASN1Type().getTag();
140         return offset;
141     }
142     
143     /**
144      * Encodes INTEGER.
145      */

146     private int encodeINTEGER(ASN1Object o, byte [] stream, int offset)
147     {
148         BigInteger JavaDoc v = (BigInteger JavaDoc) (o.getValue());
149         byte [] content = v.toByteArray();
150         for (int i = content.length - 1; i >= 0; i--)
151         {
152             stream[offset++] = content[i];
153         }
154         offset = encodeLength(content.length, stream, offset);
155         stream[offset++] = (byte) o.getASN1Type().getTag();
156         return offset;
157     }
158     
159     /**
160     * Encodes ENUMERATED
161     */

162     private int encodeENUMERATED(ASN1Object o, byte [] stream, int offset)
163     {
164         BigInteger JavaDoc v = (BigInteger JavaDoc) (o.getValue());
165         byte [] content = v.toByteArray();
166         for (int i = content.length - 1; i >= 0; i--)
167         {
168             stream[offset++] = content[i];
169         }
170         offset = encodeLength(content.length, stream, offset);
171         stream[offset++] = (byte) o.getASN1Type().getTag();
172         return offset;
173     }
174     
175     /**
176      * Encodes SEQUENCE.
177      */

178     private int encodeSEQUENCE(ASN1Object o, byte [] stream, int offset)
179     throws ASN1Exception
180     {
181         int start = offset;
182         for (int i = o.size() - 1; i >= 0; i--)
183         {
184             offset = encode(o.getComponent(i), stream, offset);
185         }
186         offset = encodeLength(offset - start, stream, offset);
187         stream[offset++] = (byte) (o.getASN1Type().getTag());
188         return offset;
189     }
190     
191     /**
192      * Encodes BITSTRING.
193      */

194     private int encodeBITSTRING(ASN1Object o, byte [] stream, int offset)
195     {
196         byte [] content = (byte []) (o.getValue());
197         for (int i = content.length - 1; i >= 0; i--)
198         {
199             stream[offset++] = content[i];
200         }
201         stream[offset++] = 0;
202         offset = encodeLength(content.length + 1, stream, offset);
203         stream[offset++] = (byte) (o.getASN1Type().getTag());
204         return offset;
205     }
206     
207     /**
208      * Encodes OCTETSTRING.
209      */

210     private int encodeOCTETSTRING(ASN1Object o, byte [] stream, int offset)
211     {
212         byte [] content = (byte []) (o.getValue());
213         for (int i = content.length - 1; i >= 0;i--)
214         {
215             stream[offset++] = content[i];
216         }
217         offset = encodeLength(content.length, stream, offset);
218         stream[offset++] = (byte) (o.getASN1Type().getTag());
219         return offset;
220     }
221     
222     /**
223      * Encodes UniversalString.
224      */

225     private int encodeUniversalString(ASN1Object o, byte [] stream, int offset)
226     {
227         byte [] content = (byte []) (o.getValue());
228         for (int i = content.length - 1; i >= 0;i--)
229         {
230             stream[offset++] = content[i];
231         }
232         offset = encodeLength(content.length, stream, offset);
233         stream[offset++] = (byte) (o.getASN1Type().getTag());
234         return offset;
235     }
236     
237     /**
238      * Encodes BMPSTRING.
239      */

240     private int encodeBMPSTRING(ASN1Object o, byte [] stream, int offset)
241     {
242         byte [] content = (byte []) (o.getValue());
243         for (int i = content.length - 1; i >= 0;i--)
244         {
245             stream[offset++] = content[i];
246         }
247         offset = encodeLength(content.length, stream, offset);
248         stream[offset++] = (byte) (o.getASN1Type().getTag());
249         return offset;
250     }
251     
252     /**
253      * Encodes OBJECT IDENTIFIER. OID is represented as string of fields
254      * seperated by space.
255      */

256     private int encodeOBJECTID(ASN1Object o, byte [] stream, int offset)
257     {
258         String JavaDoc id = (String JavaDoc) (o.getValue());
259         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(id, " ");
260         String JavaDoc [] subid = new String JavaDoc[st.countTokens()];
261         int start = offset;
262         
263         for (int i = 0; i < subid.length; i++)
264         {
265             subid[i] = st.nextToken();
266         }
267         for (int i = subid.length - 1; i > 1; i--)
268         {
269             long s = Long.parseLong(subid[i]);
270             stream[offset++] = (byte) (s & 0x7f);
271             s >>>= 7;
272             while (s != 0)
273             {
274                 stream[offset++] = (byte) (s | 0x80);
275                 s >>>= 7;
276             }
277         }
278         
279         long l = Long.parseLong(subid[0]) * 40 + Long.parseLong(subid[1]);
280         stream[offset++] = (byte) l;
281         offset = encodeLength(offset - start, stream, offset);
282         stream[offset++] = (byte) o.getASN1Type().getTag();
283         return offset;
284     }
285     
286     /**
287      * Encodes UTCTime.
288      */

289     private int encodeUTCTime(ASN1Object o, byte [] stream, int offset)
290     {
291         String JavaDoc time = (String JavaDoc) (o.getValue());
292         byte [] t = time.getBytes();
293         for (int i = t.length - 1; i >= 0; i--)
294         {
295             stream[offset++] = t[i];
296         }
297         offset = encodeLength(t.length, stream, offset);
298         stream[offset++] = (byte) o.getASN1Type().getTag();
299         return offset;
300     }
301     
302     /**
303      * Encodes GeneralizedTime.
304      */

305     private int encodeGeneralizedTime(ASN1Object o, byte[] stream, int offset)
306     {
307     
308         String JavaDoc time = (String JavaDoc) (o.getValue());
309         byte [] t = time.getBytes();
310         for (int i = t.length - 1; i >= 0; i--)
311         {
312             stream[offset++] = t[i];
313         }
314         offset = encodeLength(t.length, stream, offset);
315         stream[offset++] = (byte) o.getASN1Type().getTag();
316         return offset;
317     }
318     
319     /**
320      * Encodes PrintableString.
321      */

322     private int encodePrintableString(ASN1Object o, byte [] stream,
323                                       int offset)
324     {
325         String JavaDoc s = (String JavaDoc) (o.getValue());
326         byte [] content = s.getBytes();
327         for (int i = content.length - 1; i >= 0; i--)
328         {
329             stream[offset++] = content[i];
330         }
331         offset = encodeLength(content.length, stream, offset);
332         stream[offset++] = (byte) o.getASN1Type().getTag();
333         return offset;
334     }
335     
336     /**
337      * Encodes IA5String.
338      */

339     private int encodeIA5String(ASN1Object o, byte [] stream,
340                                 int offset)
341     {
342         String JavaDoc s = (String JavaDoc) (o.getValue());
343         byte [] content = s.getBytes();
344         for (int i = content.length - 1; i >= 0; i--)
345         {
346             stream[offset++] = content[i];
347         }
348         offset = encodeLength(content.length, stream, offset);
349         stream[offset++] = (byte) o.getASN1Type().getTag();
350         return offset;
351     }
352     
353     /**
354      * Encodes NULL.
355      */

356     private int encodeNULL(ASN1Object o, byte [] stream, int offset)
357     {
358         stream[offset++] = 0;
359         stream[offset++] = (byte) o.getASN1Type().getTag();
360         return offset;
361     }
362     
363     /**
364      * Encodes ContextSpecific.
365      */

366     private int encodeCONTEXT(ASN1Object o, byte [] stream, int offset)
367     throws ASN1Exception
368     {
369     
370         ASN1Object v = (ASN1Object) (o.getValue());
371         int start = offset;
372         
373         //System.out.println("TYPE:" + v.getASN1Type().getName());
374

375         if (o.implicit())
376         {
377         
378             if ((o.getTag() & 0x20) == 0)
379             {
380             
381                 byte[] data = null;
382                 
383                 if ( v.getASN1Type().equals(ASN1Type.BOOLEAN))
384                 {
385                 
386                     boolean b = ((Boolean JavaDoc) v.getValue()).booleanValue();
387                     stream[offset++] = (byte) (b?1:0);
388                     stream[offset++] = 1;
389                 }
390                 
391                 if ( v.getASN1Type().equals(ASN1Type.OCTET_STRING))
392                 {
393                 
394                     data = (byte []) (v.getValue());
395                     
396                     for (int i = data.length - 1; i >= 0; i--)
397                     {
398                         stream[offset++] = data[i];
399                     }
400                     offset = encodeLength(data.length, stream, offset);
401                 }
402                 
403                 if ( v.getASN1Type().equals(ASN1Type.IA5String))
404                 {
405                 
406                     String JavaDoc s = (String JavaDoc) (v.getValue());
407                     data = s.getBytes();
408                     for (int i = data.length - 1; i >= 0; i--)
409                     {
410                         stream[offset++] = data[i];
411                     }
412                     offset = encodeLength(data.length, stream, offset);
413                 }
414                 
415                 if ( v.getASN1Type().equals(ASN1Type.INTEGER))
416                 {
417                     BigInteger JavaDoc tmp = (BigInteger JavaDoc) v.getValue();
418                     data = tmp.toByteArray();
419                     
420                     for (int i = data.length - 1; i >= 0; i--)
421                     {
422                         stream[offset++] = data[i];
423                     }
424                     offset = encodeLength(data.length, stream, offset);
425                 }
426                 
427                 if (v.getASN1Type().equals(ASN1Type.UTCTime))
428                 {
429                 
430                     String JavaDoc time = (String JavaDoc) (v.getValue());
431                     //System.out.println("time:" + time);
432

433                     byte [] t = time.getBytes();
434                     for (int i = t.length - 1; i >= 0; i--)
435                     {
436                         stream[offset++] = t[i];
437                     }
438                     
439                     offset = encodeLength(t.length, stream, offset);
440                 } // End of IF ... UTCTime
441

442                 if ( v.getASN1Type().equals(ASN1Type.GENERALIZEDTIME))
443                 {
444                 
445                     String JavaDoc time = (String JavaDoc) (v.getValue());
446                     //System.out.println("time:" + time);
447

448                     byte [] t = time.getBytes();
449                     for (int i = t.length - 1; i >= 0; i--)
450                     {
451                         stream[offset++] = t[i];
452                     }
453                     
454                     offset = encodeLength(t.length, stream, offset);
455                 }
456                 
457                 if ( v.getASN1Type().equals(ASN1Type.BIT_STRING))
458                 {
459                 
460                     byte [] content = (byte []) (v.getValue());
461                     for (int i = content.length - 1; i >= 0; i--)
462                     {
463                         stream[offset++] = content[i];
464                     }
465                     stream[offset++] = 0;
466                     offset = encodeLength(content.length + 1, stream, offset);
467                 }
468                 
469                 if ( v.getASN1Type().equals(ASN1Type.ENUMERATED))
470                 {
471                     BigInteger JavaDoc tmp = (BigInteger JavaDoc) v.getValue();
472                     data = tmp.toByteArray();
473                     
474                     for (int i = data.length - 1; i >= 0; i--)
475                     {
476                         stream[offset++] = data[i];
477                     }
478                     offset = encodeLength(data.length, stream, offset);
479                 }
480                 
481                 if ( v.getASN1Type().equals(ASN1Type.OBJECT_ID))
482                 {
483                 
484                     String JavaDoc id = (String JavaDoc) (v.getValue());
485                     StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(id, " ");
486                     String JavaDoc [] subid = new String JavaDoc[st.countTokens()];
487                     //start = offset;
488

489                     for (int i = 0; i < subid.length; i++)
490                     {
491                         subid[i] = st.nextToken();
492                     }
493                     for (int i = subid.length - 1; i > 1; i--)
494                     {
495                         long s = Long.parseLong(subid[i]);
496                         stream[offset++] = (byte) (s & 0x7f);
497                         s >>>= 7;
498                         
499                         while (s != 0)
500                         {
501                             stream[offset++] = (byte) (s | 0x80);
502                             s >>>= 7;
503                         }
504                     }
505                     
506                     long l = Long.parseLong(subid[0]) * 40 + Long.parseLong(subid[1]);
507                     stream[offset++] = (byte) l;
508                     offset = encodeLength(offset - start, stream, offset);
509                     //stream[offset++] = (byte) o.getASN1Type().getTag();
510
//return offset;
511
}
512                 
513                 if ( (v.getASN1Type().equals(ASN1Type.SEQUENCE)== true) ||
514                         ( v.getASN1Type().equals(ASN1Type.SET) == true) )
515                 {
516                 
517                     start = offset;
518                     //System.out.println("SIZE:" + v.size());
519
for (int i = v.size() - 1; i >= 0; i--)
520                     {
521                         offset = encode(v.getComponent(i), stream, offset);
522                     }
523                     
524                     offset = encodeLength(offset - start, stream, offset);
525                     stream[offset++] = (byte) (0xa0 | o.getTag());
526                     return offset;
527                 } // End of IF ... sequence
528

529                 stream[offset++] = (byte) (0x80 | o.getTag()); // For all other types
530

531             }
532             else
533             {
534             
535                 offset = encode(v, stream, offset);
536                 stream[offset - 1] = (byte) (0xa0 | o.getTag());
537             }
538         }
539         else
540         {
541         
542             offset = encode(v, stream, offset);
543             offset = encodeLength(offset - start, stream, offset);
544             stream[offset++] = (byte) (0xa0 | o.getTag());
545         }
546         return offset;
547     }
548     
549     
550     /********************************/
551     /* DER Decoding */
552     /********************************/
553     
554     /**
555      * DER decoding -- decodes a byte array to an ASN1Object
556      * @param buffer the byte array to be decoded
557      * @return the decoded ASN1Object
558      * @exception iss.security.asn1.ASN1Exception if any error
559      * occurred in the decoding process
560      */

561     public ASN1Object decode(byte [] buffer)
562     throws ASN1Exception
563     {
564         int [] offset = new int [1];
565         offset[0] = 0;
566         return decode(buffer, offset);
567     }
568     
569     /**
570      * DER decoding -- decodes a byte array to an ASN1Object
571      * @param buffer the byte array to be decoded
572      * @param offset the starting index of the buffer
573      * @return the decoded ASN1Object
574      * @exception iss.security.asn1.ASN1Exception if any error
575      * occurred in the decoding process
576      */

577     public ASN1Object decode(byte [] buffer, int [] offset)
578     throws ASN1Exception
579     {
580         int start = offset[0];
581         int tag = buffer[offset[0]++];
582         int oldTag = 0;
583         if ((tag & 0x80) != 0 && (tag & 0x40) == 0)
584         {// context-specific tag
585
oldTag = tag;
586             tag = 0x80;
587         }
588         
589         ASN1Type type = new ASN1Type(tag);
590         ASN1Object object = ASN1Object.create(type);
591         int length = decodeLength(buffer, offset);
592         if (length < 0 && length != -1)
593         {
594             throw new ASN1Exception(
595                 "Invalid object length (" + length + ")");
596         }
597         switch (tag)
598         {
599         case 1:
600             decodeBOOLEAN(object, buffer, offset, length);
601             break;
602         case 2:
603             decodeINTEGER(object, buffer, offset, length);
604             break;
605         case 3:
606             decodeBITSTRING(object, buffer, offset, length);
607             break;
608         case 4:
609             decodeOCTETSTRING(object, buffer, offset, length);
610             break;
611         case 5:
612             decodeNULL(object, buffer, offset, length);
613             break;
614         case 6:
615             decodeOBJECTID(object, buffer, offset, length);
616             break;
617         case 10:
618             decodeENUMERATED(object, buffer, offset, length);
619             break;
620         case 19:
621             decodePrintableString(object, buffer, offset, length);
622             break;
623         case 20:
624             // case 20: decodeT61String(object, buffer, offset, length);
625
// break;
626
case 22:
627             decodeIA5String(object, buffer, offset, length);
628             break;
629         case 23:
630             decodeUTCTime(object, buffer, offset, length);
631             break;
632         case 24:
633             decodeGeneralizedTime(object, buffer, offset, length);
634             break;
635         case 28:
636             decodeUniversalString(object, buffer, offset, length);
637             break;
638         case 30:
639             decodeBMPSTRING(object, buffer, offset, length);
640             break;
641         case 48:
642         case 49:
643             decodeSEQUENCE(object, buffer, offset, length);
644             break;
645             // case 49: decodeSET(object, buffer, offset, length);
646
// break;
647
case 128:
648             decodeCONTEXT(object, buffer, offset, length, oldTag);
649             break;
650         default:
651             throw new ASN1Exception("Unknow ASN.1 tag --" + tag);
652         }
653         
654         // offset[0] = offset[0] + length;
655
byte [] der = new byte[offset[0]-start];
656         System.arraycopy(buffer, start, der, 0, offset[0] - start);
657         object.setByteArray(der);
658         return object;
659     }
660     
661     /**
662      * Decodes the length.
663      */

664     private int decodeLength(byte [] stream, int [] offset)
665     throws ASN1Exception
666     {
667         int length = stream[offset[0]++] & 0xff;
668         if ((length & 0x80) != 0)
669         {
670             int count = length & 0x7f;
671             if (count > 4)
672             {
673                 throw new ASN1Exception("ASN.1 Object too large");
674             }
675             if (count == 0)
676             { // indefinite length
677
return -1;
678             }
679             length = stream[offset[0]++] & 0xff;
680             for (int i = 1; i < count; i++)
681             {
682                 length <<= 8;
683                 length |= (stream[offset[0]++] & 0xff);
684             }
685         }
686         return length;
687     }
688     
689     /**
690      * Decodes BOOLEAN. Definite-length only.
691      */

692     private void decodeBOOLEAN(ASN1Object o, byte [] stream, int [] offset,
693                                int length) throws ASN1Exception
694     {
695         if (length != 1)
696         {
697             throw new ASN1Exception("Wrong data (BOOLEAN) length");
698         }
699         boolean v = (stream[offset[0]] == 0) ? false : true;
700         o.setValue(new Boolean JavaDoc(v));
701         offset[0]++;
702     }
703     
704     /**
705      * Decodes INTEGER. Definite-length only.
706      */

707     private void decodeINTEGER(ASN1Object o, byte [] stream, int [] offset,
708                                int length) throws ASN1Exception
709     {
710         if (length < 1)
711         {
712             throw new ASN1Exception("Wrong data (INTEGER) length");
713         }
714         byte [] content = new byte[length];
715         System.arraycopy(stream, offset[0], content, 0, length);
716         BigInteger JavaDoc v = new BigInteger JavaDoc(content);
717         o.setValue(v);
718         offset[0] += length;
719     }
720     
721     /**
722      * Decodes ENUMERATED. Definite-length only.
723      */

724     private void decodeENUMERATED(ASN1Object o, byte [] stream, int [] offset,
725                                   int length) throws ASN1Exception
726     {
727         if (length < 1)
728         {
729             throw new ASN1Exception("Wrong data (INTEGER) length");
730         }
731         byte [] content = new byte[length];
732         System.arraycopy(stream, offset[0], content, 0, length);
733         BigInteger JavaDoc v = new BigInteger JavaDoc(content);
734         o.setValue(v);
735         offset[0] += length;
736     }
737     
738     /**
739      * Decodes SEQUENCE.
740      */

741     private void decodeSEQUENCE(ASN1Object o, byte [] stream, int [] offset,
742                                 int length) throws ASN1Exception
743     {
744         int start = offset[0];
745         if (length == -1)
746         { // indefinite length
747
while (true)
748             {
749                 if (stream[offset[0]] == 0
750                         && stream[offset[0]+1] == 0)
751                 {
752                     offset[0] += 2;
753                     break;
754                 }
755                 o.addComponent(decode(stream, offset));
756             }
757         }
758         else
759         {
760             while (offset[0] < start + length)
761             {
762                 o.addComponent(decode(stream, offset));
763             }
764             if (offset[0] != start + length)
765             {
766                 throw new ASN1Exception("Wrong data (SEQUENCE) length");
767             }
768         }
769     }
770     
771     /**
772      * Decodes BITSTRING. Assume definite-length only.
773      */

774     private void decodeBITSTRING(ASN1Object o, byte [] stream, int [] offset,
775                                  int length) throws ASN1Exception
776     {
777         if (length == -1)
778         {
779             // not implemented
780
}
781         else
782         {
783             if (length < 1)
784             {
785                 throw new ASN1Exception("Wrong data (BIT STRING) length");
786             }
787             byte [] content = new byte[length];
788             System.arraycopy(stream, offset[0], content, 0, length);
789             o.setValue(content);
790             offset[0] += length;
791         }
792     }
793     
794     /**
795      * Decodes OCTETSTRING. Assume definite-length only.
796      */

797     private void decodeOCTETSTRING(ASN1Object o, byte [] stream,
798                                    int [] offset, int length)
799     {
800         if (length == -1)
801         {
802             // not implemented
803
}
804         else
805         {
806             byte [] content = new byte[length];
807             System.arraycopy(stream, offset[0], content, 0, length);
808             o.setValue(content);
809             offset[0] += length;
810         }
811     }
812     
813     /**
814     * Decodes UniversalSTRING. Assume definite-length only.
815     */

816     private void decodeUniversalString(ASN1Object o, byte [] stream,
817                                        int [] offset, int length)
818     {
819         if (length == -1)
820         {
821             // not implemented
822
}
823         else
824         {
825             byte [] content = new byte[length];
826             System.arraycopy(stream, offset[0], content, 0, length);
827             o.setValue(content);
828             offset[0] += length;
829         }
830     }
831     
832     /**
833     * Decodes BMPSTRING. Assume definite-length only.
834     */

835     private void decodeBMPSTRING(ASN1Object o, byte [] stream,
836                                  int [] offset, int length)
837     {
838         if (length == -1)
839         {
840             // not implemented
841
}
842         else
843         {
844             byte [] content = new byte[length];
845             System.arraycopy(stream, offset[0], content, 0, length);
846             o.setValue(content);
847             offset[0] += length;
848         }
849     }
850     
851     /**
852      * Decodes OBJECT IDENTIFIER. Definite-length only.
853      */

854     private void decodeOBJECTID(ASN1Object o, byte [] stream, int [] offset,
855                                 int length) throws ASN1Exception
856     {
857         if (length < 1)
858         { // at least two components
859
throw new ASN1Exception("Wrong data (OBJECT ID) length");
860         }
861         int end = offset[0] + length;
862         int v = stream[offset[0]++];
863         String JavaDoc content = Integer.toString(v/40) + " ";
864         content += Integer.toString(v%40) + " ";
865         
866         while (offset[0] < end)
867         {
868             long l = 0;
869             while ((stream[offset[0]] & 0x80) != 0)
870             {
871                 l |= 0x7f & stream[offset[0]++];
872                 l <<= 7;
873             }
874             l |= 0x7f & stream[offset[0]++];
875             content += Long.toString(l) + " ";
876         }
877         if (offset[0] != end)
878         {
879             throw new ASN1Exception("Wrong data (OBJECT ID) length");
880         }
881         o.setValue(content.trim());
882     }
883     
884     /**
885      * Decodes UTCTime. Assume definite-length only.
886      */

887     private void decodeUTCTime(ASN1Object o, byte [] stream, int [] offset,
888                                int length) throws ASN1Exception
889     {
890         if (length == -1)
891         {
892             // not implemented
893
}
894         else
895         {
896             if (length < 11)
897             { // at least 11 ASCII characters
898
throw new ASN1Exception("Wrong data (UTCTime) length");
899             }
900             o.setValue(new String JavaDoc(stream, offset[0], length));
901             offset[0] += length;
902         }
903     }
904     
905     /**
906      * Decodes GeneralizedTime. Assume definite-length only.
907      */

908     private void decodeGeneralizedTime(ASN1Object o, byte [] stream, int [] offset,
909                                        int length) throws ASN1Exception
910     {
911         if (length == -1)
912         {
913             // not implemented
914
}
915         else
916         {
917             if (length < 11)
918             { // at least 13 ASCII characters
919
throw new ASN1Exception("Wrong data (UTCTime) length");
920             }
921             o.setValue(new String JavaDoc(stream, offset[0], length));
922             offset[0] += length;
923         }
924     }
925     
926     /**
927      * Decodes PrintableString. Assume definite-length only.
928      */

929     private void decodePrintableString(ASN1Object o, byte [] stream,
930                                        int [] offset, int length)
931     {
932         if (length == -1)
933         {
934             // not implemented
935
}
936         else
937         {
938             o.setValue(new String JavaDoc(stream, offset[0], length));
939             offset[0] += length;
940         }
941     }
942     
943     /**
944      * Decodes IA5String. Assume definite-length only.
945      */

946     private void decodeIA5String(ASN1Object o, byte [] stream,
947                                  int [] offset, int length)
948     {
949         if (length == -1)
950         {
951             // not implemented
952
}
953         else
954         {
955             o.setValue(new String JavaDoc(stream, offset[0], length));
956             offset[0] += length;
957         }
958     }
959     
960     /**
961      * Decodes NULL. Definite-length only.
962      */

963     private void decodeNULL(ASN1Object o, byte [] stream, int [] offset,
964                             int length) throws ASN1Exception
965     {
966         if (length != 0)
967         {
968             throw new ASN1Exception("Wrong data (NULL) length");
969         }
970         o.setValue("");
971     }
972     
973     /**
974      * Decodes ContextSpecific.
975      */

976     private void decodeCONTEXT(ASN1Object o, byte [] stream, int [] offset,
977                                int length, int tag) throws ASN1Exception
978     {
979         Context obj = null;
980         int start = offset[0];
981         tag = tag & 0x3f;
982         
983         if ((tag & 0x20) == 0)
984         { //primitive type
985
if (length < 0)
986             {
987                 throw new ASN1Exception("Wrong length(ContextSpecific)");
988             }
989             byte [] data = new byte[length];
990             System.arraycopy(stream, offset[0], data, 0, length);
991             obj = new Context(tag, true,
992                               ASN1Object.create(ASN1Type.OCTET_STRING, data));
993             offset[0] += length;
994         }
995         else
996         {
997             try
998             {
999                 ASN1Object v = decode(stream, offset);
1000                if (length == -1)
1001                {
1002                    if (stream[offset[0]] == 0
1003                            && stream[offset[0]+1] == 0)
1004                    {
1005                        offset[0] += 2;
1006                    }
1007                    else
1008                    {
1009                        // System.out.println(offset[0]);
1010
throw new ASN1Exception(
1011                            "wrong indefinite-length decoding");
1012                    }
1013                }
1014                else
1015                {
1016                    if (offset[0] != start + length)
1017                    {
1018                        throw new ASN1Exception(
1019                            "wrong definite-length decoding");
1020                    }
1021                }
1022                obj = new Context(tag, false, v);
1023            }
1024            catch(ASN1Exception e)
1025            {
1026                // e.printStackTrace(System.out);
1027
offset[0] = start;
1028                ASN1Object v = ASN1Object.create(ASN1Type.SEQUENCE);
1029                decodeSEQUENCE(v, stream, offset, length);
1030                obj = new Context(tag, true, v);
1031            }
1032        }
1033        o.setValue(obj);
1034    }
1035}
1036
Popular Tags