1
package org.bouncycastle.asn1;
3
import java.io.ByteArrayInputStream;
4
import java.io.EOFException;
5
import java.io.FilterInputStream;
6
import java.io.IOException;
7
import java.io.InputStream;
9
public class DERInputStream
10
extends FilterInputStream implements DERTags
12
public DERInputStream(
18
protected int readLength()
24
throw new IOException("EOF found when length expected");
29
return -1; // indefinite-length encoding
34
int size = length & 0x7f;
37
for (int i = 0; i < size; i++)
43
throw new IOException("EOF found reading length");
46
length = (length << 8) + next;
53
protected void readFully(
57
int left = bytes.length;
64
while ((left -= read(bytes, bytes.length - left, left)) != 0)
71
* build an object given its tag and a byte stream to construct it
74
protected DERObject buildObject(
83
case SEQUENCE | CONSTRUCTED:
84
ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
85
BERInputStream dIn = new BERInputStream(bIn);
86
DERConstructedSequence seq = new DERConstructedSequence();
92
DERObject obj = dIn.readObject();
97
catch (EOFException ex)
101
case SET | CONSTRUCTED:
102
bIn = new ByteArrayInputStream(bytes);
103
dIn = new BERInputStream(bIn);
105
DERSet set = new DERSet(dIn.readObject());
111
DERObject obj = dIn.readObject();
116
catch (EOFException ex)
121
return new DERBoolean(bytes);
123
return new DERInteger(bytes);
124
case OBJECT_IDENTIFIER:
125
int head = bytes[0] & 0xff;
126
StringBuffer objId = new StringBuffer();
128
objId.append(head / 40);
130
objId.append(head % 40);
134
for (int i = 1; i != bytes.length; i++)
136
int b = bytes[i] & 0xff;
138
value = value * 128 + (b & 0x7f);
139
if ((b & 128) == 0) // end of number reached
147
return new DERObjectIdentifier(objId.toString());
149
int padBits = bytes[0];
150
byte[] data = new byte[bytes.length - 1];
152
System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
154
return new DERBitString(data, padBits);
155
case PRINTABLE_STRING:
156
return new DERPrintableString(bytes);
158
return new DERIA5String(bytes);
160
return new DERT61String(bytes);
162
return new DERVisibleString(bytes);
164
return new DERBMPString(bytes);
166
return new DEROctetString(bytes);
167
case GENERALIZED_TIME:
168
return new DERGeneralizedTime(new String(bytes, 0));
170
return new DERUTCTime(new String(bytes, 0));
173
// with tagged object tag number is bottom 4 bits
175
if ((tag & (TAGGED | CONSTRUCTED)) != 0)
177
if (bytes.length == 0) // empty tag!
179
return new DERTaggedObject(tag & 0x0f);
183
// simple type - implicit... return an octet string
185
if ((tag & CONSTRUCTED) == 0)
187
return new DERTaggedObject(false, tag & 0x0f, new DEROctetString(bytes));
190
bIn = new ByteArrayInputStream(bytes);
191
dIn = new BERInputStream(bIn);
193
DEREncodable dObj = dIn.readObject();
196
// explicitly tagged (probably!) - if it isn't we'd have to
197
// tell from the context
199
if (dIn.available() == 0)
201
return new DERTaggedObject(tag & 0x0f, dObj);
205
// another implicit object, we'll create a sequence...
207
seq = new DERConstructedSequence();
215
dObj = dIn.readObject();
220
catch (EOFException ex)
225
return new DERTaggedObject(false, tag & 0x0f, seq);
228
return new DERUnknownTag(tag, bytes);
232
public DERObject readObject()
238
throw new EOFException();
241
int length = readLength();
242
byte[] bytes = new byte[length];
246
return buildObject(tag, bytes);