1:
38:
39: package ;
40:
41: import ;
42: import ;
43:
44:
53: public class BERDecoder
54: {
55:
56: private byte[] buffer;
57: private int offset;
58: private int type;
59: private int len;
60: private boolean control;
61: private boolean utf8;
62:
63: public BERDecoder(byte[] data, boolean utf8)
64: {
65: buffer = data;
66: offset = 0;
67: control = true;
68: this.utf8 = utf8;
69: }
70:
71:
75: public int parseType()
76: throws BERException
77: {
78: if (offset >= buffer.length)
79: {
80: return -1;
81: }
82: type = byteToInt(buffer[offset++]);
83: len = byteToInt(buffer[offset++]);
84: if ((len & 0x80) != 0)
85: {
86: int lsize = len - 0x80;
87: if (lsize > 4)
88: {
89: throw new BERException("Data too long: " + lsize);
90: }
91: if (buffer.length - offset < lsize)
92: {
93: throw new BERException("Insufficient data");
94: }
95: len = 0;
96: for (int i = 0; i < lsize; i++)
97: {
98: len = (len << 8) + byteToInt(buffer[offset++]);
99: }
100: if (buffer.length - offset < len)
101: {
102: throw new BERException("Insufficient data");
103: }
104: }
105: control = false;
106: return type;
107: }
108:
109: static int byteToInt(byte b)
110: {
111: int ret = (int) b;
112: if (ret < 0)
113: {
114: ret += 0x100;
115: }
116: return ret;
117: }
118:
119: int getLength()
120: {
121: return len;
122: }
123:
124: public boolean available()
125: {
126: return (offset < buffer.length);
127: }
128:
129: public void skip()
130: {
131: offset += len;
132: control = true;
133: }
134:
135: public boolean parseBoolean()
136: throws BERException
137: {
138: if (control)
139: {
140: parseType();
141: }
142: if (type != BERConstants.BOOLEAN)
143: {
144: throw new BERException("Unexpected type: " + type);
145: }
146: int c = (int) buffer[offset++];
147: control = true;
148: return (c != 0);
149: }
150:
151: public int parseInt()
152: throws BERException
153: {
154: if (control)
155: {
156: parseType();
157: }
158: if (type != BERConstants.INTEGER && type != BERConstants.ENUMERATED)
159: {
160: throw new BERException("Unexpected type: " + type);
161: }
162: byte c = buffer[offset++];
163: int val = ((int) c) & 0x7f;
164: for (int i = 1; i < len; i++)
165: {
166: val <<= 0x08;
167: val |= ((int) buffer[offset++]) & 0xff;
168: }
169: if ((c & 0x80) != 0)
170: {
171: val = -val;
172: }
173: control = true;
174: return val;
175: }
176:
177: public String parseString()
178: throws BERException
179: {
180: if (control)
181: {
182: parseType();
183: }
184: if (len == 0)
185: {
186: control = true;
187: return "";
188: }
189: if (type != BERConstants.UTF8_STRING && type != BERConstants.OCTET_STRING)
190: {
191: throw new BERException("Unexpected type: " + type);
192: }
193: String encoding = (type == BERConstants.UTF8_STRING) ? "UTF-8" :
194: "ISO-8859-1";
195: try
196: {
197: String ret = new String(buffer, offset, len, encoding);
198: offset += len;
199: control = true;
200: return ret;
201: }
202: catch(UnsupportedEncodingException e)
203: {
204: throw new BERException("JVM does not support " + encoding);
205: }
206: }
207:
208: public byte[] parseOctetString()
209: throws BERException
210: {
211: if (control)
212: {
213: parseType();
214: }
215: if (type != BERConstants.OCTET_STRING)
216: {
217: throw new BERException("Unexpected type: " + type);
218: }
219: byte[] ret = new byte[len];
220: System.arraycopy(buffer, offset, ret, 0, len);
221: offset += len;
222: control = true;
223: return ret;
224: }
225:
226: public BERDecoder parseSequence()
227: throws BERException
228: {
229: return parseSequence(BERConstants.SEQUENCE);
230: }
231:
232: public BERDecoder parseSequence(int code)
233: throws BERException
234: {
235: if (control)
236: {
237: parseType();
238: }
239: if (code != -1 && type != code)
240: {
241: throw new BERException("Unexpected type: " + type);
242: }
243: byte[] ret = new byte[len];
244: System.arraycopy(buffer, offset, ret, 0, len);
245: offset += len;
246: control = true;
247: return new BERDecoder(ret, utf8);
248: }
249:
250: public BERDecoder parseSet()
251: throws BERException
252: {
253: return parseSet(BERConstants.SET);
254: }
255:
256: public BERDecoder parseSet(int code)
257: throws BERException
258: {
259: return parseSequence(code);
260: }
261:
262: public static void main(String[] args)
263: {
264: try
265: {
266: ByteArrayOutputStream out = new ByteArrayOutputStream();
267: for (int c = System.in.read(); c != -1; c = System.in.read())
268: {
269: out.write(c);
270: }
271: byte[] code = out.toByteArray();
272: BERDecoder decoder = new BERDecoder(code, true);
273: debug(decoder, 0);
274: }
275: catch (Exception e)
276: {
277: e.printStackTrace(System.err);
278: }
279: }
280:
281: private static void debug(BERDecoder decoder, int depth)
282: throws BERException
283: {
284: for (int t = decoder.parseType(); t != -1; t = decoder.parseType())
285: {
286: for (int i = 0; i < depth; i++)
287: {
288: System.out.print('\t');
289: }
290: switch (t)
291: {
292: case BERConstants.BOOLEAN:
293: System.out.println("BOOLEAN: " + decoder.parseBoolean());
294: break;
295: case BERConstants.INTEGER:
296: System.out.println("INTEGER: " + decoder.parseInt());
297: break;
298: case BERConstants.ENUMERATED:
299: System.out.println("ENUMERATED: " + decoder.parseInt());
300: break;
301: case BERConstants.OCTET_STRING:
302: System.out.println("OCTET-STRING: " +
303: toString(decoder.parseOctetString()));
304: break;
305: case BERConstants.UTF8_STRING:
306: System.out.println("STRING: \"" + decoder.parseString() + "\"");
307: break;
308: default:
309: System.out.println("SEQUENCE " + t + "(0x" +
310: Integer.toHexString(t) + "): " +
311: decoder.getLength());
312: BERDecoder sequence = decoder.parseSequence(t);
313: debug(sequence, depth + 1);
314: break;
315: }
316: }
317: }
318:
319: private static String toString(byte[] bytes)
320: {
321: try
322: {
323: return "\"" + new String(bytes, "UTF-8") + "\"";
324: }
325: catch (UnsupportedEncodingException e)
326: {
327: return bytes.toString();
328: }
329: }
330:
331: }