1 package org.bouncycastle.asn1;
3 import java.math.BigInteger;
4 import java.io.FilterInputStream;
6 import java.io.InputStream;
7 import java.io.ByteArrayInputStream;
8 import java.io.IOException;
9 import java.io.EOFException;
12 public class DERInputStream
13 extends FilterInputStream implements DERTags
15 public DERInputStream(
21 protected int readLength()
27 throw new IOException("EOF found when length expected");
32 return -1; // indefinite-length encoding
37 int size = length & 0x7f;
40 for (int i = 0; i < size; i++)
46 throw new IOException("EOF found reading length");
49 length = (length << 8) + next;
56 protected void readFully(
60 int left = bytes.length;
67 while ((left -= read(bytes, bytes.length - left, left)) != 0)
74 * build an object given its tag and a byte stream to construct it
77 protected DERObject buildObject(
86 case SEQUENCE | CONSTRUCTED:
87 ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
88 BERInputStream dIn = new BERInputStream(bIn);
89 DERConstructedSequence seq = new DERConstructedSequence();
95 DERObject obj = dIn.readObject();
100 catch (EOFException ex)
104 case SET | CONSTRUCTED:
105 bIn = new ByteArrayInputStream(bytes);
106 dIn = new BERInputStream(bIn);
108 DEREncodableVector v = new DEREncodableVector();
114 DERObject obj = dIn.readObject();
119 catch (EOFException ex)
121 return new DERConstructedSet(v);
124 return new DERBoolean(bytes);
126 return new DERInteger(bytes);
128 return new DEREnumerated(bytes);
129 case OBJECT_IDENTIFIER:
130 return new DERObjectIdentifier(bytes);
132 int padBits = bytes[0];
133 byte[] data = new byte[bytes.length - 1];
135 System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
137 return new DERBitString(data, padBits);
139 return new DERUTF8String(bytes);
140 case PRINTABLE_STRING:
141 return new DERPrintableString(bytes);
143 return new DERIA5String(bytes);
145 return new DERT61String(bytes);
147 return new DERVisibleString(bytes);
148 case UNIVERSAL_STRING:
149 return new DERUniversalString(bytes);
151 return new DERBMPString(bytes);
153 return new DEROctetString(bytes);
155 return new DERUTCTime(bytes);
156 case GENERALIZED_TIME:
157 return new DERGeneralizedTime(bytes);
160 // with tagged object tag number is bottom 5 bits
162 if ((tag & TAGGED) != 0)
164 if ((tag & 0x1f) == 0x1f)
166 throw new IOException("unsupported high tag encountered");
169 if (bytes.length == 0) // empty tag!
171 return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence());
175 // simple type - implicit... return an octet string
177 if ((tag & CONSTRUCTED) == 0)
179 return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
182 bIn = new ByteArrayInputStream(bytes);
183 dIn = new BERInputStream(bIn);
185 DEREncodable dObj = dIn.readObject();
188 // explicitly tagged (probably!) - if it isn't we'd have to
189 // tell from the context
191 if (dIn.available() == 0)
193 return new DERTaggedObject(tag & 0x1f, dObj);
197 // another implicit object, we'll create a sequence...
199 seq = new DERConstructedSequence();
207 dObj = dIn.readObject();
212 catch (EOFException ex)
217 return new DERTaggedObject(false, tag & 0x1f, seq);
220 return new DERUnknownTag(tag, bytes);
224 public DERObject readObject()
230 throw new EOFException();
233 int length = readLength();
234 byte[] bytes = new byte[length];
238 return buildObject(tag, bytes);