Skip to content

Commit 4cfe8ff

Browse files
committed
added support for decoding constructed Octet Strings
1 parent eb2134c commit 4cfe8ff

3 files changed

Lines changed: 77 additions & 7 deletions

File tree

projects/asn1bean/src/main/java/com/beanit/asn1bean/ber/BerTag.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ public int encode(OutputStream reverseOS) throws IOException {
9999
if (tagBytes == null) {
100100
code();
101101
}
102-
reverseOS.write(tagBytes);
102+
for (int i = (tagBytes.length - 1); i >= 0; i--) {
103+
reverseOS.write(tagBytes[i]);
104+
}
103105
return tagBytes.length;
104106
}
105107

@@ -186,7 +188,9 @@ public int decode(InputStream is, OutputStream os) throws IOException {
186188
* @throws IOException if an exception occurs reading the identifier from the stream.
187189
*/
188190
public int decodeAndCheck(InputStream is) throws IOException {
189-
191+
if (tagBytes == null) {
192+
code();
193+
}
190194
for (byte identifierByte : tagBytes) {
191195
int nextByte = is.read();
192196
if (nextByte == -1) {
@@ -195,9 +199,9 @@ public int decodeAndCheck(InputStream is) throws IOException {
195199

196200
if (nextByte != (identifierByte & 0xff)) {
197201
throw new IOException(
198-
"Identifier does not match, expected: "
202+
"Identifier does not match, expected: 0x"
199203
+ HexString.fromByte(identifierByte)
200-
+ ", received: "
204+
+ ", received: 0x"
201205
+ HexString.fromByte((byte) nextByte));
202206
}
203207
}

projects/asn1bean/src/main/java/com/beanit/asn1bean/ber/types/BerOctetString.java

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.beanit.asn1bean.ber.BerTag;
1818
import com.beanit.asn1bean.ber.internal.Util;
1919
import com.beanit.asn1bean.util.HexString;
20+
import java.io.EOFException;
2021
import java.io.IOException;
2122
import java.io.InputStream;
2223
import java.io.OutputStream;
@@ -61,11 +62,65 @@ public int decode(InputStream is) throws IOException {
6162

6263
public int decode(InputStream is, boolean withTag) throws IOException {
6364

64-
int codeLength = 0;
65-
6665
if (withTag) {
67-
codeLength += tag.decodeAndCheck(is);
66+
int nextByte = is.read();
67+
switch (nextByte) {
68+
case -1:
69+
throw new EOFException("Unexpected end of input stream.");
70+
case 0x04:
71+
return 1 + decodePrimitiveOctetString(is);
72+
case 0x24:
73+
return 1 + decodeConstructedOctetString(is);
74+
default:
75+
throw new IOException(
76+
"Octet String identifier does not match, expected: 0x04 or 0x24, received: 0x"
77+
+ HexString.fromByte((byte) nextByte));
78+
}
79+
}
80+
return decodePrimitiveOctetString(is);
81+
}
82+
83+
private int decodeConstructedOctetString(InputStream is) throws IOException {
84+
85+
BerLength length = new BerLength();
86+
int lengthLength = length.decode(is);
87+
88+
value = new byte[0];
89+
int vLength = 0;
90+
91+
if (length.val < 0) {
92+
BerTag berTag = new BerTag();
93+
vLength += berTag.decode(is);
94+
while (!berTag.equals(0, 0, 0)) {
95+
BerOctetString subOctetString = new BerOctetString();
96+
vLength += subOctetString.decode(is, false);
97+
value = concatenate(value, subOctetString.value);
98+
vLength += berTag.decode(is);
99+
}
100+
vLength += BerLength.readEocByte(is);
101+
} else {
102+
while (vLength < length.val) {
103+
BerOctetString subOctetString = new BerOctetString();
104+
vLength += subOctetString.decode(is);
105+
value = concatenate(value, subOctetString.value);
106+
}
68107
}
108+
return lengthLength + vLength;
109+
}
110+
111+
private byte[] concatenate(byte[] a, byte[] b) {
112+
int aLen = a.length;
113+
int bLen = b.length;
114+
115+
byte[] c = new byte[aLen + bLen];
116+
System.arraycopy(a, 0, c, 0, aLen);
117+
System.arraycopy(b, 0, c, aLen, bLen);
118+
119+
return c;
120+
}
121+
122+
private int decodePrimitiveOctetString(InputStream is) throws IOException {
123+
int codeLength = 0;
69124

70125
BerLength length = new BerLength();
71126
codeLength += length.decode(is);

projects/asn1bean/src/test/java/com/beanit/asn1bean/ber/types/BerOctetStringTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
import static org.junit.jupiter.api.Assertions.assertEquals;
1818

1919
import com.beanit.asn1bean.ber.ReverseByteArrayOutputStream;
20+
import com.beanit.asn1bean.util.HexString;
2021
import java.io.ByteArrayInputStream;
2122
import java.io.IOException;
23+
import java.io.InputStream;
2224
import org.junit.jupiter.api.Test;
2325

2426
public class BerOctetStringTest {
@@ -50,4 +52,13 @@ public void toStringTest() {
5052
BerOctetString octetString = new BerOctetString(new byte[] {1, 2, (byte) 0xa0});
5153
assertEquals("0102A0", octetString.toString());
5254
}
55+
56+
@Test
57+
public void constructedOctetStringDecoding() throws IOException {
58+
InputStream is =
59+
new ByteArrayInputStream(HexString.toBytes("2480040C48656C6C6F20576F726C64210401550000"));
60+
BerOctetString octetString = new BerOctetString();
61+
octetString.decode(is);
62+
assertEquals("48656C6C6F20576F726C642155", octetString.toString());
63+
}
5364
}

0 commit comments

Comments
 (0)