KickJava   Java API By Example, From Geeks To Geeks.

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


1
2 package com.ca.commons.security.asn1;
3
4
5 import com.ca.commons.cbutil.CBParse;
6
7 import java.util.Vector JavaDoc;
8 import java.util.Hashtable JavaDoc;
9 import java.io.*;
10
11 /**
12  * This class is an abstract representation of ASN.1 types. It is
13  * the superclass of all classes representing actual ASN.1 types.
14  * It also defines necessary interfaces for its subclasses. For more
15  * information about ASN.1, please refer to:
16  * <pre>CCITT. Recommendation X.208: Specification of Abstract Syntax
17  * Notation One (ASN.1). 1988</pre>
18  * <P> ASN.1 types are encoded using Basic Encoding Rules (BER) and
19  * Distinguished Encoding Rules (DER). For more information about
20  * these rules, please refer to:
21  * <pre>CCITT. Recommendation X.209: Specification of Basic Encoding
22  * Rules for Abstract Notation One (ASN.1). 1988</pre>
23  * <P> To create an ASN1Object of a specific ASN.1 type, the static
24  * method create() is called which takes an ASN1Type object as the
25  * parameter and returns a suitable subclass of ASN1Object.
26  * <P> This class provides a set of methods which converts ASN1Objects
27  * to/from DER encoded byte arrays, Privacy Enhanced Mail (PEM) formatted
28  * files and character strings, etc. It also has a set of methods which
29  * converts ASN1Object to/from encrypted form. For more information about
30  * PEM format and encryption, please refer to com.ca.commons.security.pkcs5.Envelope.
31  * Ref: http://www.rsa.com/rsalabs/pubs/PKCS/
32  *
33  * @author who
34  */

35 public class ASN1Object implements java.io.Serializable JavaDoc
36 {
37
38     /** The ASN.1 type of the ASN1Object. */
39     protected ASN1Type asn1Type;
40
41     /** DER encoded byte array representation of the ASN1Object. */
42     protected byte [] byteArray;
43
44     /** The mapping table of ASN.1 type and implementation class. */
45     private static Hashtable JavaDoc asn1ToJava = new Hashtable JavaDoc(27);
46
47     static{
48         Class JavaDoc p = (new Primitive()).getClass();
49         register(ASN1Type.BOOLEAN, p);
50         register(ASN1Type.INTEGER, p);
51         register(ASN1Type.OCTET_STRING, p);
52         register(ASN1Type.NULL, p);
53         register(ASN1Type.OBJECT_ID, p);
54         register(ASN1Type.BIT_STRING, p);
55         register(ASN1Type.IA5String, p);
56         register(ASN1Type.T61String, p);
57         register(ASN1Type.PrintableString, p);
58         register(ASN1Type.UTCTime, p);
59
60         register(ASN1Type.GENERALIZEDTIME,p);
61         register(ASN1Type.ENUMERATED,p);
62         register(ASN1Type.UniversalString, p);
63         register(ASN1Type.BMPString, p);
64
65         Class JavaDoc s = (new Sequence()).getClass();
66         register(ASN1Type.SEQUENCE, s);
67         register(ASN1Type.SET, s);
68
69         Class JavaDoc c = new Context().getClass();
70         register(ASN1Type.ContextSpecific, c);
71     }
72
73     /**
74      * Constructs an empty ASN1Object.
75      */

76     public ASN1Object()
77     {}
78
79     /**
80      * Initializes the ASN1Object with a specific ASN1Type.
81      */

82     protected void init(ASN1Type type)
83     {
84         asn1Type = type;
85         byteArray = null;
86     }
87
88     /**
89      * Gets the ASN1Type of the ASN1Object.
90      */

91     public ASN1Type getASN1Type()
92     {
93         return asn1Type;
94     }
95
96     /**
97      * Gets the DER encoded byte array of the ASN1Object.
98      */

99     public byte [] getByteArray()
100     {
101         return byteArray;
102     }
103
104     /**
105      * Sets the DER encoded byte array of the ASN1Object.
106      * @param b the DER encoded byte array.
107      */

108     void setByteArray(byte [] b)
109     {
110         byteArray = b;
111     }
112
113     /**
114      * Checks the type of this ASN1Object against the given ASN1Type.
115      */

116     public boolean isASN1Type(ASN1Type type)
117     {
118         return asn1Type.equals(type);
119     }
120
121     /**
122      * Compares the 'len' byte sequences of 2 arrays, x and y starting at
123      * offsets 'xoff' and 'yoff' respectively.
124      */

125     public boolean compByteArray(byte [] x, int xoff, byte [] y,
126                                  int yoff, int len)
127     {
128         if (len <= 0 || x == null || xoff < 0 || x.length < xoff + len
129                 || y == null || yoff < 0 || y.length < yoff + len)
130         {
131             return false;
132         }
133         for (int i = 0; i < len; i++)
134         {
135             if (x[xoff+i] != y[yoff+i])
136             {
137                 return false;
138             }
139         }
140         return true;
141     }
142
143     /**
144      * Compares byte sequences of 2 arrays, x and y.
145      */

146     public boolean compByteArray(byte [] x, byte [] y)
147     {
148         if (x == null || y == null || x.length != y.length)
149         {
150             return false;
151         }
152         return compByteArray(x, 0, y, 0, x.length);
153     }
154
155     /**
156      * Returns whether two ASN1Objects are equal.
157      */

158     public boolean equals(Object JavaDoc o)
159     {
160         if (!(o instanceof com.ca.commons.security.asn1.ASN1Object))
161         {
162             return false;
163         }
164         try
165         {
166             byte [] der = ASN1Util.toByteArrayDER(this);
167             byte [] der1 = ASN1Util.toByteArrayDER((ASN1Object) o);
168             return compByteArray(der, der1);
169         }
170         catch(ASN1Exception asn1e)
171         {
172             asn1e.printStackTrace(System.out);
173             return false;
174         }
175     }
176
177     /**
178      * Returns a string representation of the ASN1Object.
179      */

180     public String JavaDoc toString()
181     {
182         return asn1Type.toString();
183     }
184
185
186     /* interface for primitive and context specific ASN.1 types */
187
188     private Object JavaDoc o = null;
189
190     /**
191      * Returns the actual value of the ASN1Object. The ASN1Object cannot
192      * be of a constructed ASN.1 type.
193      * Subclasses should overwrite this method.
194      */

195     public Object JavaDoc getValue()
196     {
197         return o;
198         // throw new IllegalArgumentException("method not supported");
199
}
200
201     /**
202      * Sets the value of the ASN1Object. The ASN1Object cannot be of a
203      * constructed ASN.1 type.
204      * Subclass should overwrite this method.
205      */

206     public void setValue(Object JavaDoc o)
207     {
208         this.o = o;
209         // throw new IllegalArgumentException("method not supported");
210
}
211
212
213     /* interface for composite ASN.1 classes */
214
215     Vector JavaDoc comps = new Vector JavaDoc();
216
217     /**
218      * Adds a component to the ASN1Object. The ASN1Object must be of a
219      * constructed ASN.1 type.
220      * Subclass should overwrite this method.
221      */

222     public void addComponent(ASN1Object o)
223     {
224         comps.addElement(o);
225         // throw new IllegalArgumentException("method not supported");
226
}
227
228     /**
229      * Adds a component to the ASN1Object at a given index. The ASN1Object
230      * must be of a constructed ASN.1 type.
231      * Subclass should overwrite this method.
232      */

233     public void addComponent(ASN1Object o, int index)
234     {
235         throw new IllegalArgumentException JavaDoc("method not supported");
236     }
237
238     /**
239      * Gets a component from the ASN1Object. The ASN1Object must be of a
240      * constructed ASN.1 type to allow this operation.
241      * Subclass should overwrite this method.
242      */

243     public ASN1Object getComponent()
244     {
245         throw new IllegalArgumentException JavaDoc("method not supported");
246     }
247
248     /**
249      * Gets a component from the ASN1Object at the given index. The
250      * ASN1Object must be of a constructed ASN.1 type.
251      * Subclass should overwrite this method.
252      */

253     public ASN1Object getComponent(int index)
254     {
255         return (ASN1Object) comps.elementAt(index);
256         // throw new IllegalArgumentException("method not supported");
257
}
258
259     /**
260      * Returns the number of components in the ASN1Object. The ASN1Object
261      * must be of a constructed ASN.1 type.
262      * Subclass should overwrite this method.
263      */

264     public int size()
265     {
266         return comps.size();
267         // throw new IllegalArgumentException("method not supported");
268
}
269
270
271     /* interface for context specific ASN.1 class */
272
273     /**
274      * Returns whether the ASN1Object is using implicit ASN.1 tagging.
275      * The ASN1Object must be of the context specific ASN.1 type.
276      * Subclass should overwrite this method.
277      */

278     public boolean implicit()
279     {
280         throw new IllegalArgumentException JavaDoc("method not supported");
281     }
282
283     /**
284      * Returns the context specific tag of the ASN1Object. The ASN1Object
285      * must be of the context specific ASN.1 type.
286      * Subclass should overwrite this method.
287      */

288     public int getTag()
289     {
290         if (asn1Type != null)
291             return asn1Type.getTag();
292         else
293             throw new IllegalArgumentException JavaDoc("Object not initialised, does not have a type");
294     }
295
296
297     /* class methods */
298
299     /**
300      * Registers the implementation class of the ASN1Type.
301      */

302     private static void register(ASN1Type type, Class JavaDoc c)
303     {
304         asn1ToJava.put(type, c);
305     }
306
307     /**
308      * This is the main method of creating an ASN1Object of the given
309      * ASN1Type, without assigning it any initial value.
310      * @exception com.ca.commons.security.asn1.ASN1Exception if no implementation
311      * class of the ASN1Type is available or cannot create an instance of
312      * the implementation class.
313      */

314     public static ASN1Object create(ASN1Type type)
315     throws ASN1Exception
316     {
317         Class JavaDoc impl = null;
318         try
319         {
320             ASN1Object o;
321             impl = (Class JavaDoc) asn1ToJava.get(type);
322             if (impl == null)
323             {
324                 throw new ASN1Exception(type.toString()+
325                                         " : no implementation class available");
326             }
327             o = (ASN1Object) impl.newInstance();
328             o.init(type);
329             return o;
330         }
331         catch (InstantiationException JavaDoc e)
332         {
333             throw new ASN1Exception("Cannot create instance for " +
334                                     type.toString() + "\n" + e.toString());
335         }
336         catch (IllegalAccessException JavaDoc e)
337         {
338             throw new ASN1Exception("Cannot create instance for " +
339                                     type.toString() + "\n" + e.toString());
340         }
341     }
342
343     /**
344      * Same as the method create(ASN1Type), except that this method assigns
345      * the created ASN1Object an initial value.
346      * @param v the object to be assigned to the ASN1Object as its value.
347      */

348     public static ASN1Object create(ASN1Type type, Object JavaDoc v)
349     throws ASN1Exception
350     {
351         ASN1Object o = create(type);
352         o.setValue(v);
353         return o;
354     }
355
356
357     /*
358      * Conversion methods:
359      * The following section contains methods that convert ASN1Objects
360      * to/from various forms, like byte array, character string, file,
361      * encrypted form, etc.
362      */

363
364     /**
365      * Initializes the DER encoded byte array of the ASN1Object.
366      */

367     public void initByteArray()
368     {
369         try
370         {
371             byte [] buf = ASN1Util.toByteArrayDER(this);
372             setByteArray(buf);
373         }
374         catch(ASN1Exception asn1e)
375         {
376             asn1e.printStackTrace(System.out);
377             setByteArray(null);
378         }
379     }
380
381     /**
382      * Converts to a DER byte array.
383      */

384     public byte [] toDERBytes()
385     {
386         try
387         {
388             return ASN1Util.toByteArrayDER(this);
389         }
390         catch(ASN1Exception asn1e)
391         {
392             asn1e.printStackTrace(System.out);
393             return null;
394         }
395     }
396
397     /*
398      * Converts to an encrypted DER byte array. - *** Not used ***
399      * @param cipher the encryption algorithm.
400      * @param iv 8-byte array which will be filled up with IV bytes.
401      * @param pw the Password object to get an encrypion password.
402      * @exception com.ca.commons.security.pkcs5.PasswordException if error occured
403      * when get a new password from 'pw'.
404      *
405     public byte [] toDERBytes(String cipher, byte [] iv, Password pw)
406     throws PasswordException {
407         byte [] buf = toPEMBytes(cipher, iv, pw);
408         return Base64Coder.decode(buf);
409 }
410     */

411
412     /**
413      * Converts to a DER file (in binary format).
414      */

415     public boolean toDERFile(File file)
416     throws IOException
417     {
418         try
419         {
420             ASN1Util.saveDER(this, file);
421             return true;
422         }
423         catch(ASN1Exception asn1e)
424         {
425             asn1e.printStackTrace(System.out);
426             return false;
427         }
428     }
429
430     /**
431      * Converts to a base64 encoded byte array.
432      */

433     public byte [] toBase64()
434     {
435         try
436         {
437             return ASN1Util.toByteArrayPEM(this);
438         }
439         catch(ASN1Exception asn1e)
440         {
441             asn1e.printStackTrace(System.out);
442             return null;
443         }
444     }
445
446     /*
447      * Converts to an encrypted PEM byte array. - *** Not used ***
448      * @param cipher the encryption algorithm.
449      * @param iv 8-byte array which will be filled up with IV bytes.
450      * @param pw the Password object to get an encrypion password.
451      * @exception com.ca.commons.security.pkcs5.PasswordException if error occured
452      * when get a new password from 'pw'.
453      *
454     private byte [] toPEMBytes(String cipher, byte [] iv, Password pw)
455     throws PasswordException {
456     // cannot see any chance to use it directly at the moment
457         byte [] buf = toDERBytes();
458         byte [] tmp = new byte[8];
459         byte [] enc = Envelope.writeEncByteArray(buf, cipher, tmp, 0, pw);
460         if (iv != null && iv.length >= 8) {
461             System.arraycopy(tmp, 0, iv, 0, 8);
462         }
463         return enc;
464 }
465     */

466
467     /**
468      * Converts to a PEM file.
469      * @param name the object type/name.
470      */

471     public boolean toPEMFile(File file, String JavaDoc name)
472     throws IOException
473     {
474         try
475         {
476             ASN1Util.savePEM(this, file, name);
477             return true;
478         }
479         catch(ASN1Exception asn1e)
480         {
481             asn1e.printStackTrace(System.out);
482             return false;
483         }
484     }
485
486     /*
487      * Converts to an encrypted PEM file. - *** Not used ***
488      * @param name the object type/name.
489      * @param cipher the encryption algorithm.
490      * @param pw the Password object to get an encrypion password.
491      * @exception com.ca.commons.security.pkcs5.PasswordException if error occured
492      * when get a new password from 'pw'.
493      *
494     public boolean toPEMFile(File file, String name,
495     String cipher, Password pw) throws IOException, PasswordException {
496         byte [] buf = toDERBytes();
497         return Envelope.writeEncFile(file, buf, name, cipher, 0, pw);
498 }
499     */

500
501     /*
502      * Converts to a PEM String. - *** Not used ***
503      * @param name the object type/name.
504      *
505     public String toPEMString(String name) {
506         try {
507             return toPEMString(name, null, null);
508         } catch(PasswordException pe) {
509             return null;
510         }
511 }
512
513     /*
514      * Converts to an encrypted PEM String. - *** Not used ***
515      * @param name the object type/name.
516      * @param cipher the encryption algorithm.
517      * @param pw the Password object to get an encrypion password.
518      * @exception com.ca.commons.security.pkcs5.PasswordException if error occured
519      * when get a new password from 'pw'.
520      *
521     public String toPEMString(String name, String cipher,
522     Password pw) throws PasswordException {
523         byte [] buf = toDERBytes();
524         try {
525             return Envelope.writeEncFile(buf, name, cipher, 0, pw);
526         } catch(IOException ioe) {
527             return null;
528         }
529 }
530     */

531
532
533     /*
534      * from other objects to ASN1Object
535      */

536
537     /* - *** Not used ***
538      * Converts from a byte array. The byte array can be either
539      * base64 encoded or not, and can be encrypted or not.
540      * @param cipher the encryption algorithm.
541      * @param iv the Initial Vector.
542      * @param pw the Password object to get an encrypion password.
543      * @exception com.ca.commons.security.pkcs5.PasswordException if cannot get the
544      * password or the password is wrong.
545      *
546     public static ASN1Object fromBytes(byte [] data, String cipher,
547     byte [] iv, Password pw) throws PasswordException {
548         if (data == null)
549             throw new NullPointerException();
550         byte [] buf = Envelope.readEncByteArray(data, cipher, iv, pw);
551         try {
552             return ASN1Util.fromByteArray(buf);
553         } catch(ASN1Exception asn1e) {
554             asn1e.printStackTrace(System.out);
555             return null;
556         }
557 }
558     */

559
560     /**
561      * Converts from a byte array. The byte array can be either
562      * base64 encoded or not, but is assumed not encrypted.
563      */

564     public static ASN1Object fromBytes(byte [] data)
565     {
566         try
567         {
568             // return fromBytes(data, null, null, null);
569
// } catch(PasswordException pe) {
570
return ASN1Util.fromByteArray(data);
571         }
572         catch(ASN1Exception asn1e)
573         {
574             System.out.println(CBParse.bytes2Hex(data));
575             asn1e.printStackTrace(System.out);
576             return null;
577         }
578     }
579
580     /**
581      * Converts from a DER or PEM file which is not encrypted.
582      */

583     public static ASN1Object fromFile(File file)
584     throws IOException
585     {
586         /*
587               ASN1Object o = null;
588                 try { - *** Not used ***
589                     o = fromFile(file, null);
590                 } catch(PasswordException pe) {
591                     if (pe.getCode() == PasswordException.PASSWORD_REQUIRED) {
592                         throw new IllegalArgumentException("expect a passphrase");
593                     }
594                 }
595                 if (o == null) { */

596         try
597         {
598             return ASN1Util.fromFile(file);
599         }
600         catch(ASN1Exception asn1e)
601         {
602             asn1e.printStackTrace(System.out);
603             return null;
604         }
605         // }
606
// return o;
607
}
608
609     /* - *** Not used ***
610      * Converts from a PEM file which is either encrypted or not.
611      * @param pw the Password object to get an encrypion password.
612      * @exception com.ca.commons.security.pkcs5.PasswordException if cannot get the
613      * password or the password is wrong.
614      *
615     public static ASN1Object fromFile(File file, Password pw)
616     throws IOException, PasswordException {
617         byte [] buf = Envelope.readEncFile(file, pw);
618         try {
619             return ASN1Util.fromByteArray(buf);
620         } catch(ASN1Exception asn1e) {
621             asn1e.printStackTrace(System.out);
622             return null;
623         }
624 }
625     */

626
627     /* - *** Not used ***
628      * Converts from a String which is actually a PEM file in String form.
629      * The PEM file can be either encrypted or not.
630      * @param pw the Password object to get an encrypion password.
631      * @exception com.ca.commons.security.pkcs5.PasswordException if cannot get the
632      * password or the password is wrong.
633      *
634     public static ASN1Object fromString(String s, Password pw)
635     throws PasswordException {
636         byte [] buf = null;
637         try {
638             buf = Envelope.readEncFile(s, pw);
639         } catch(IOException ioe) {
640             return null;
641         }
642         try {
643             return ASN1Util.fromByteArray(buf);
644         } catch(ASN1Exception asn1e) {
645             asn1e.printStackTrace(System.out);
646             return null;
647         }
648 }
649
650     /** - *** Not used ***
651      * Converts from a String which is actually a PEM file in String form.
652      * The PEM file is not encrypted.
653      *
654     public static ASN1Object fromString(String s) {
655         try {
656             return fromString(s, null);
657         } catch(PasswordException pe) {
658             if (pe.getCode() == PasswordException.PASSWORD_REQUIRED) {
659                 throw new IllegalArgumentException("expect a passphrase");
660             }
661             return null;
662         }
663 }
664     */

665 }
666
Popular Tags