1 package org.bouncycastle.asn1;
3 import java.io.FilterInputStream;
5 import java.io.InputStream;
6 import java.io.ByteArrayInputStream;
7 import java.io.IOException;
8 import java.io.EOFException;
11 public class DERInputStream
12 extends FilterInputStream implements DERTags
14 public DERInputStream(
20 protected int readLength()
26 throw new IOException("EOF found when length expected");
31 return -1; // indefinite-length encoding
36 int size = length & 0x7f;
39 for (int i = 0; i < size; i++)
45 throw new IOException("EOF found reading length");
48 length = (length << 8) + next;
55 protected void readFully(
59 int left = bytes.length;
66 while ((left -= read(bytes, bytes.length - left, left)) != 0)
73 * build an object given its tag and a byte stream to construct it
76 protected DERObject buildObject(
85 case SEQUENCE | CONSTRUCTED:
86 ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
87 BERInputStream dIn = new BERInputStream(bIn);
88 DERConstructedSequence seq = new DERConstructedSequence();
94 DERObject obj = dIn.readObject();
99 catch (EOFException ex)
103 case SET | CONSTRUCTED:
104 bIn = new ByteArrayInputStream(bytes);
105 dIn = new BERInputStream(bIn);
107 DEREncodableVector v = new DEREncodableVector();
113 DERObject obj = dIn.readObject();
118 catch (EOFException ex)
120 return new DERConstructedSet(v);
123 return new DERBoolean(bytes);
125 return new DERInteger(bytes);
127 return new DEREnumerated(bytes);
128 case OBJECT_IDENTIFIER:
129 return new DERObjectIdentifier(bytes);
131 int padBits = bytes[0];
132 byte[] data = new byte[bytes.length - 1];
134 System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
136 return new DERBitString(data, padBits);
138 return new DERUTF8String(bytes);
139 case PRINTABLE_STRING:
140 return new DERPrintableString(bytes);
142 return new DERIA5String(bytes);
144 return new DERT61String(bytes);
146 return new DERVisibleString(bytes);
147 case UNIVERSAL_STRING:
148 return new DERUniversalString(bytes);
150 return new DERBMPString(bytes);
152 return new DEROctetString(bytes);
154 return new DERUTCTime(bytes);
155 case GENERALIZED_TIME:
156 return new DERGeneralizedTime(bytes);
159 // with tagged object tag number is bottom 5 bits
161 if ((tag & TAGGED) != 0)
163 if ((tag & 0x1f) == 0x1f)
165 throw new IOException("unsupported high tag encountered");
168 if (bytes.length == 0) // empty tag!
170 return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence());
174 // simple type - implicit... return an octet string
176 if ((tag & CONSTRUCTED) == 0)
178 return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
181 bIn = new ByteArrayInputStream(bytes);
182 dIn = new BERInputStream(bIn);
184 DEREncodable dObj = dIn.readObject();
187 // explicitly tagged (probably!) - if it isn't we'd have to
188 // tell from the context
190 if (dIn.available() == 0)
192 return new DERTaggedObject(tag & 0x1f, dObj);
196 // another implicit object, we'll create a sequence...
198 seq = new DERConstructedSequence();
206 dObj = dIn.readObject();
211 catch (EOFException ex)
216 return new DERTaggedObject(false, tag & 0x1f, seq);
219 return new DERUnknownTag(tag, bytes);
223 public DERObject readObject()
229 throw new EOFException();
232 int length = readLength();
233 byte[] bytes = new byte[length];
237 return buildObject(tag, bytes);