1 package org.bouncycastle.asn1;
3 import java.math.BigInteger;
6 public class DERInputStream
7 extends FilterInputStream implements DERTags
15 protected int readLength()
21 throw new IOException("EOF found when length expected");
26 return -1; // indefinite-length encoding
31 int size = length & 0x7f;
34 for (int i = 0; i < size; i++)
40 throw new IOException("EOF found reading length");
43 length = (length << 8) + next;
50 protected void readFully(
54 int left = bytes.length;
61 while ((left -= read(bytes, bytes.length - left, left)) != 0)
68 * build an object given its tag and a byte stream to construct it
71 protected DERObject buildObject(
80 case SEQUENCE | CONSTRUCTED:
81 ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
82 BERInputStream dIn = new BERInputStream(bIn);
83 DERConstructedSequence seq = new DERConstructedSequence();
89 DERObject obj = dIn.readObject();
94 catch (EOFException ex)
98 case SET | CONSTRUCTED:
99 bIn = new ByteArrayInputStream(bytes);
100 dIn = new BERInputStream(bIn);
102 DERSet set = new DERSet(dIn.readObject());
108 DERObject obj = dIn.readObject();
113 catch (EOFException ex)
118 return new DERBoolean(bytes);
120 return new DERInteger(bytes);
121 case OBJECT_IDENTIFIER:
122 int head = bytes[0] & 0xff;
123 StringBuffer objId = new StringBuffer();
125 objId.append(Integer.toString(head / 40));
127 objId.append(Integer.toString(head % 40));
131 for (int i = 1; i != bytes.length; i++)
133 int b = bytes[i] & 0xff;
135 value = value * 128 + (b & 0x7f);
136 if ((b & 128) == 0) // end of number reached
139 objId.append(Integer.toString(value));
144 return new DERObjectIdentifier(objId.toString());
146 int padBits = bytes[0];
147 byte[] data = new byte[bytes.length - 1];
149 System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
151 return new DERBitString(data, padBits);
152 case PRINTABLE_STRING:
153 return new DERPrintableString(bytes);
155 return new DERIA5String(bytes);
157 return new DERT61String(bytes);
159 return new DERVisibleString(bytes);
161 return new DERBMPString(bytes);
163 return new DEROctetString(bytes);
165 return new DERUTCTime(new String(bytes));
168 // with tagged object tag number is bottom 4 bits
170 if ((tag & (TAGGED | CONSTRUCTED)) != 0)
172 if (bytes.length == 0) // empty tag!
174 return new DERTaggedObject(tag & 0x0f);
178 // simple type - implicit... return an octet string
180 if ((tag & CONSTRUCTED) == 0)
182 return new DERTaggedObject(false, tag & 0x0f, new DEROctetString(bytes));
185 bIn = new ByteArrayInputStream(bytes);
186 dIn = new BERInputStream(bIn);
188 DEREncodable dObj = dIn.readObject();
191 // explicitly tagged (probably!) - if it isn't we'd have to
192 // tell from the context
194 if (dIn.available() == 0)
196 return new DERTaggedObject(tag & 0x0f, dObj);
200 // another implicit object, we'll create a sequence...
202 seq = new DERConstructedSequence();
210 dObj = dIn.readObject();
215 catch (EOFException ex)
220 return new DERTaggedObject(false, tag & 0x0f, seq);
223 return new DERUnknownTag(tag, bytes);
227 public DERObject readObject()
233 throw new EOFException();
236 int length = readLength();
237 byte[] bytes = new byte[length];
241 return buildObject(tag, bytes);