1 /*
2  * @(#) $Id: ASN1Oid.java,v 1.3 2003/07/08 08:13:52 pankaj Exp $
3  *
4  * Copyright (c) 2002-03 by Pankaj Kumar (http://www.pankaj-k.net). 
5  * All rights reserved.
6  *
7  * The license governing the use of this file can be found in the 
8  * root directory of the containing software.
9  */
10package org.jstk.asn1;
11
12import java.io.ByteArrayOutputStream;
13
14/* From: A Layman's Guide to a Subset of ASN.1, BER, and DER
15 * Encoding of object identifier.
16 * BER encoding. Primitive. Contents octets are as follows, where value1, ...,
17 * valuen denote the integer values of the components in the complete object
18 * identifier:
19 *
20 * 1. The first octet has value 40 * value1 + value2. (This is unambiguous,
21 *    since value1 is limited to values 0, 1, and 2; value2 is limited to
22 *    the range 0 to 39 when value1 is 0 or 1; and, according to X.208, n
23 *    is always at least 2.)
24 * 2. The following octets, if any, encode value3, ..., valuen. Each value
25 *    is encoded base 128, most significant digit first, with as few digits
26 *    as possible, and the most significant bit of each octet except the last
27 *    in the value's encoding set to "1."
28 *
29 * Example: The first octet of the BER encoding of RSA Data Security, Inc.'s
30 * object identifier is 40 * 1 + 2 = 42 = 2a16. The encoding of 840 = 6 * 128
31 * + 4816 is 86 48 and the encoding of 113549 = 6 * 1282 + 7716 * 128 + d16 is
32 * 86 f7 0d. This leads to the following BER encoding:
33 *   06 06 2a 86 48 86 f7 0d
34 */
35
36
37public class ASN1Oid extends ASN1Type {
38    public ASN1Oid(){
39        super(UNIVERSAL, NONE, OID, OID);
40    }
41    public void setOid(String oid){
42        String[] components = oid.split("\\.");
43        int value1 = Integer.parseInt(components[0]);
44        int value2 = Integer.parseInt(components[1]);
45        ByteArrayOutputStream baos = new ByteArrayOutputStream();
46        baos.write(value1*40 + value2);
47        int index = 2;
48        while (index < components.length){
49            int valuei = Integer.parseInt(components[index]);
50            while (valuei > 0){
51                int octetValue = valuei;
52                int d = 1;
53                while (octetValue >= 128){
54                    d = 128*d;
55                    octetValue = octetValue/128;
56                }
57                valuei = valuei%d;
58                // Write the octet to byte stream
59                if (valuei != 0)
60                    baos.write(octetValue | 0x80);
61                else
62                    baos.write(octetValue);
63            }
64            ++index;
65        }
66        this.value = baos.toByteArray();
67        this.length = this.value.length;
68    }
69    public String toString(){
70        if (value == null)
71            return null;
72
73        StringBuffer sb = new StringBuffer();
74        int firstOctet = (int)value[0];
75        int value1 = firstOctet/40;
76        int value2 = firstOctet%40;
77        sb.append(value1).append('.').append(value2);
78        int index = 1;
79        while (index < value.length){
80            int valuei = 0;
81            do {
82                valuei = valuei*128 + (value[index] & 0x7f);
83            } while ((value[index++] & 0x80) == 0x80);
84            sb.append('.').append(valuei);
85        }
86        return sb.toString();
87    }
88
89    public static void main(String[] args){
90        byte[] bytes = { (byte)0x2a, (byte)0x86, 0x48, (byte)0x86, (byte)0xf7, 0x0d };
91        ASN1Oid oid = new ASN1Oid();
92        oid.setValue(bytes);
93        System.out.println(oid.toString());
94        oid.setOid("1.5.8");
95        System.out.println(oid.toString());
96        oid.setOid("1.2.840.113549.1");
97        System.out.println(oid.toString());
98        oid.setOid("2.5.4.6");
99        System.out.println(oid.toString());
00        oid.setOid("2.5.4.3");
01        System.out.println(oid.toString());
02    }
03}