001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.geronimo.crypto.asn1;
019
020 import java.io.ByteArrayOutputStream;
021 import java.io.IOException;
022 import java.io.OutputStream;
023
024 public class DERObjectIdentifier
025 extends DERObject
026 {
027 String identifier;
028
029 /**
030 * return an OID from the passed in object
031 *
032 * @exception IllegalArgumentException if the object cannot be converted.
033 */
034 public static DERObjectIdentifier getInstance(
035 Object obj)
036 {
037 if (obj == null || obj instanceof DERObjectIdentifier)
038 {
039 return (DERObjectIdentifier)obj;
040 }
041
042 if (obj instanceof ASN1OctetString)
043 {
044 return new DERObjectIdentifier(((ASN1OctetString)obj).getOctets());
045 }
046
047 if (obj instanceof ASN1TaggedObject)
048 {
049 return getInstance(((ASN1TaggedObject)obj).getObject());
050 }
051
052 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
053 }
054
055 /**
056 * return an Object Identifier from a tagged object.
057 *
058 * @param obj the tagged object holding the object we want
059 * @param explicit true if the object is meant to be explicitly
060 * tagged false otherwise.
061 * @exception IllegalArgumentException if the tagged object cannot
062 * be converted.
063 */
064 public static DERObjectIdentifier getInstance(
065 ASN1TaggedObject obj,
066 boolean explicit)
067 {
068 return getInstance(obj.getObject());
069 }
070
071
072 DERObjectIdentifier(
073 byte[] bytes)
074 {
075 StringBuffer objId = new StringBuffer();
076 long value = 0;
077 boolean first = true;
078
079 for (int i = 0; i != bytes.length; i++)
080 {
081 int b = bytes[i] & 0xff;
082
083 value = value * 128 + (b & 0x7f);
084 if ((b & 0x80) == 0) // end of number reached
085 {
086 if (first)
087 {
088 switch ((int)value / 40)
089 {
090 case 0:
091 objId.append('0');
092 break;
093 case 1:
094 objId.append('1');
095 value -= 40;
096 break;
097 default:
098 objId.append('2');
099 value -= 80;
100 }
101 first = false;
102 }
103
104 objId.append('.');
105 objId.append(Long.toString(value));
106 value = 0;
107 }
108 }
109
110 this.identifier = objId.toString();
111 }
112
113 public DERObjectIdentifier(
114 String identifier)
115 {
116 for (int i = identifier.length() - 1; i >= 0; i--)
117 {
118 char ch = identifier.charAt(i);
119
120 if ('0' <= ch && ch <= '9')
121 {
122 continue;
123 }
124
125 if (ch == '.')
126 {
127 continue;
128 }
129
130 throw new IllegalArgumentException("string " + identifier + " not an OID");
131 }
132
133 this.identifier = identifier;
134 }
135
136 public String getId()
137 {
138 return identifier;
139 }
140
141 private void writeField(
142 OutputStream out,
143 long fieldValue)
144 throws IOException
145 {
146 if (fieldValue >= (1 << 7))
147 {
148 if (fieldValue >= (1 << 14))
149 {
150 if (fieldValue >= (1 << 21))
151 {
152 if (fieldValue >= (1 << 28))
153 {
154 if (fieldValue >= (1 << 35))
155 {
156 if (fieldValue >= (1 << 42))
157 {
158 if (fieldValue >= (1 << 49))
159 {
160 if (fieldValue >= (1 << 56))
161 {
162 out.write((int)(fieldValue >> 56) | 0x80);
163 }
164 out.write((int)(fieldValue >> 49) | 0x80);
165 }
166 out.write((int)(fieldValue >> 42) | 0x80);
167 }
168 out.write((int)(fieldValue >> 35) | 0x80);
169 }
170 out.write((int)(fieldValue >> 28) | 0x80);
171 }
172 out.write((int)(fieldValue >> 21) | 0x80);
173 }
174 out.write((int)(fieldValue >> 14) | 0x80);
175 }
176 out.write((int)(fieldValue >> 7) | 0x80);
177 }
178 out.write((int)fieldValue & 0x7f);
179 }
180
181 void encode(
182 DEROutputStream out)
183 throws IOException
184 {
185 OIDTokenizer tok = new OIDTokenizer(identifier);
186 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
187 DEROutputStream dOut = new DEROutputStream(bOut);
188
189 writeField(bOut,
190 Integer.parseInt(tok.nextToken()) * 40
191 + Integer.parseInt(tok.nextToken()));
192
193 while (tok.hasMoreTokens())
194 {
195 writeField(bOut, Long.parseLong(tok.nextToken()));
196 }
197
198 dOut.close();
199
200 byte[] bytes = bOut.toByteArray();
201
202 out.writeEncoded(OBJECT_IDENTIFIER, bytes);
203 }
204
205 public int hashCode()
206 {
207 return identifier.hashCode();
208 }
209
210 public boolean equals(
211 Object o)
212 {
213 if ((o == null) || !(o instanceof DERObjectIdentifier))
214 {
215 return false;
216 }
217
218 return identifier.equals(((DERObjectIdentifier)o).identifier);
219 }
220
221 public String toString()
222 {
223 return getId();
224 }
225 }