I am working on a decoder for ASN.1 encrypted file, and getting
java.io.IOException: DER length more than 4 bytes: 63
I want to understand why bouncy castle is throwing this exception.
If someone can provide me their 2 cent would be much appreciated!
Code Snippet
ASN1InputStream bIn = null; try { byte[] bFile = encoded; InputStream input = new ByteArrayInputStream(bFile); bIn = new ASN1InputStream(input); Object temp = null; // logger.info("Decoding and emitting file : "); System.out.println("Decoding and emitting file : "); while ((temp = bIn.readObject()) != null){ if (temp instanceof DERTaggedObject) { DERTaggedObject octs = (DERTaggedObject) temp; ASN1Set instance = ASN1Set.getInstance(octs, false); The Error is being thrown at
bIn.readObject() I have tracked the exception to ASN1InputStream class readLength() method.
static int readLength(InputStream s, int limit) 283 throws IOException 284 { 285 int length = s.read(); 286 if (length < 0) 287 { 288 throw new EOFException("EOF found when length expected"); 289 } 290 291 if (length == 0x80) 292 { 293 return -1; // indefinite-length encoding 294 } 295 296 if (length > 127) 297 { 298 int size = length & 0x7f; 299 300 if (size > 4) 301 { 302 throw new IOException("DER length more than 4 bytes"); 303 } 304 305 length = 0; 306 for (int i = 0; i < size; i++) 307 { 308 int next = s.read(); 309 310 if (next < 0) 311 { 312 throw new EOFException("EOF found reading length"); 313 } 314 315 length = (length << 8) + next; 316 } 317 318 if (length < 0) 319 { 320 throw new IOException("corrupted stream - negative length found"); 321 } 322 323 if (length >= limit) // after all we must have read at least 1 byte 324 { 325 throw new IOException("corrupted stream - out of bounds length found"); 326 } 327 } 328 329 return length; 330 } Any help to help understand why this exception is being thrown is very appreciated!
Thank You!
52 Answers
Possibly you are getting this error because you are passing whole stream of your file so at the time of encoding / decoding you need to pass a block / part of byte stream and encode then add to byte array then finally write into a file.
As of your previous post i feel your are encoding a CDRs file, so you should be aware of record length. let me assume you have n number of record of indefinite length and we need to encode it. For example Consider a block of 2048 bytes (you can consider more than avg size of your record) which holds minimum one or more number of record(s).
Add the byte stream of every record into a 2048 byte block, while adding if block is full or having some space but non of the records can store then add filler bytes (i.e. 0xFF so that you can easily figure it out the number of blocks ) then pass to ASN1InputStream to get DERTaggedObject then encode the stream and store it in separate variable and after encoding everything just write stored stream into a .dat or any file system.
You can refer this link for better understanding od encode / decoding process
By the "ITU-T Recommendation X.690" also known as "ISO/IEC 8825-1" BER Length can be encoded in two forms:
- definite form as implemented in your source.
- indefinite form - not covered this source.
Definite form
If Value length <128 (i.e hexadecimal 0x00 to 0x7F) it is encoded in short form - in one byte.
For length more than 127 it is encoded in long form. The length octets shall consist of an initial octet and one or more subsequent octets. In this case:
- bit 8 in first Byte (initial octet) should be one. (source code line 296)
- bits 7 to 1 in Byte 1 shall encode the number of subsequent octets(Bytes) in the length octets, i.e. followed after this byte. (source code line 298 get the size)
- the value 11111111 (0xFF) shall not be used for initial octet - This restriction is introduced for possible future extension.
In the original ASN.1 I see no limitations for long form subsequent octets size, but other specifications can apply own rules for it.
For sample ISO 7816 can use lengths up to 5 bytes (including initial octet/byte). In other words initial octet value could be 0x81, 0x82, 0x83 or 0x84.
You can exclude or change the size checking at lines 300 to 303 if you want to cover other length sizes. In this case additional implementation for Value size resolution will be required due to int length number limitation. Changing length to long type allows to use up to 8 subsequent octets(Bytes).
But probably your input data and it's length is not feet ASN.1 BER/DER TLV encoding rules.
7