wstrange / asn1lib

Dart ASN1 Encoder / Decoder
BSD 2-Clause "Simplified" License
30 stars 31 forks source link

Out of range problem in decodeLength #61

Closed obalak closed 1 year ago

obalak commented 2 years ago

Hello,

I experienced a problem when parsing a certificate content as follows:

List<ASN1Object> unmarchal(Uint8List data) {
    var asn1Parser = ASN1Parser(data, relaxedParsing: true);
    List<ASN1Object> objs = <ASN1Object>[];
    while (asn1Parser.hasNext()) {
      var obj = asn1Parser.nextObject();
      objs.add(obj);
    }
    return objs;
  }

In the first object I'm getting the right certificate content. However, in the next call to nextObject, the remaining bytes are 5 and when parsed (after removing tag), the parser have one byte content which is then make the call to decodeLength crashes because of out range index in the line 2 (var length = (encodedBytes[1] & 0x7F)) of the following method:

static ASN1Length decodeLength(Uint8List encodedBytes) {
    var valueStartPosition = 2; //default
    var length = (encodedBytes[1] & 0x7F);
    if (length != encodedBytes[1]) {
      var numLengthBytes = length;

      length = 0;
      for (var i = 0; i < numLengthBytes; i++) {
        length <<= 8;
        length |= (encodedBytes[valueStartPosition++] & 0xFF);
      }
    }

Both cases with and without relaxedParsing are same.

Am I using the parser in a wrong way?

Here is the list content I'm parsing:

[112, 130, 2, 67, 48, 130, 2, 63, 48, 130, 1, 161, 160, 3, 2, 1, 2, 2, 17, 0, 241, 37, 53, 1, 245, 101, 254, 123, 227, 232, 24, 198, 233, 209, 186, 121, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 4, 48, 53, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 81, 83, 97, 102, 101, 32, 82, 111, 111, 116, 32, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 67, 72, 49, 14, 48, 12, 6, 3, 85, 4, 10, 19, 5, 113, 115, 97, 102, 101, 48, 30, 23, 13, 50, 50, 49, 48, 49, 51, 49, 52, 52, 56, 52, 52, 90, 23, 13, 51, 50, 49, 48, 49, 48, 49, 52, 52, 56, 52, 52, 90, 48, 62, 49, 31, 48, 29, 6, 3, 85, 4, 3, 19, 22, 81, 83, 97, 102, 101, 32, 77, 97, 110, 97, 103, 101, 109, 101, 110, 116, 32, 83, 117, 98, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 67, 72, 49, 14, 48, 12, 6, 3, 85, 4, 10, 19, 5, 113, 115, 97, 102, 101, 48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 3, 66, 0, 4, 245, 37, 160, 205, 186, 201, 132, 55, 14, 255, 31, 190, 213, 248, 71, 133, 167, 187, 249, 160, 133, 253, 237, 80, 240, 241, 253, 230, 76, 105, 114, 197, 209, 111, 2, 84, 105, 28, 206, 37, 26, 171, 235, 62, 133, 250, 182, 121, 77, 170, 162, 138, 228, 225, 141, 117, 2, 193, 208, 33, 202, 229, 56, 216, 163, 129, 136, 48, 129, 133, 48, 33, 6, 3, 85, 29, 14, 4, 26, 4, 24, 178, 86, 37, 149, 146, 99, 71, 45, 239, 84, 119, 201, 224, 247, 36, 202, 33, 183, 106, 143, 165, 74, 38, 93, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 23, 6, 3, 85, 29, 17, 4, 16, 48, 14, 129, 12, 113, 109, 115, 64, 113, 115, 97, 102, 101, 46, 99, 104, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 1, 48, 35, 6, 3, 85, 29, 35, 4, 28, 48, 26, 128, 24, 204, 8, 68, 110, 197, 203, 88, 195, 126, 193, 109, 59, 120, 77, 184, 102, 3, 91, 11, 80, 45, 172, 213, 21, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 4, 3, 129, 139, 0, 48, 129, 135, 2, 66, 1, 203, 18, 146, 103, 163, 7, 188, 133, 141, 7, 47, 252, 170, 252, 244, 249, 244, 81, 108, 17, 26, 28, 17, 23, 112, 209, 65, 137, 55, 237, 124, 175, 5, 51, 5, 142, 190, 171, 103, 253, 168, 143, 82, 126, 85, 158, 105, 122, 228, 62, 252, 132, 73, 101, 225, 15, 233, 15, 74, 126, 132, 64, 140, 157, 245, 2, 65, 35, 14, 88, 229, 195, 209, 161, 229, 221, 102, 131, 237, 29, 56, 25, 106, 128, 36, 241, 90, 222, 25, 216, 30, 105, 104, 130, 183, 73, 224, 185, 115, 101, 67, 213, 144, 196, 248, 119, 77, 50, 138, 21, 101, 228, 168, 176, 134, 100, 20, 202, 30, 163, 47, 155, 180, 18, 237, 249, 238, 155, 75, 51, 95, 254, 113, 1, 0, 254, 0]

Hope this will help to find out and fix the problem. Thanks,

wstrange commented 2 years ago

Thanks for the report. Even if the data is bad, decodeLength should not crash - so that needs to be fixed. Are you confident that the data is valid (i.e. does it parse correctly in another tool?)

Just to set expectations, I'm not sure when I will have time to look at this right away.

obalak commented 2 years ago

Thanks Warrens for your feedback. Yes, I'm sure the data is correct because I can read and parse in Go. Below is the Go code I'm using:

 // Decode will unpack a byte array of DER encoded byte arrays into
// asn1.RawValue structs.
func Decode(bytes []byte) ([]asn1.RawValue, error) {
    ret := []asn1.RawValue{}
    for {
        rawData := asn1.RawValue{}
        rest, err := asn1.Unmarshal(bytes, &rawData)
        if err != nil {
            return nil, err
        }
        ret = append(ret, rawData)
        if len(rest) == 0 {
            break
        }
        bytes = rest
    }
    return ret, nil
}

I made change to my Dart code in the same way in Go and I'm still facing the problem. Indeed, [113, 1, 0, 254, 0] these last 5 bytes that are causing the problem. '113' is parsed as tag and the subsequent byte '1' is the length, which will make the next sequence as one byte content '0' and this will cause the crash of the DecodeLenght. It seems for me that the passed encodedBytes is not get correctly because it should be 3 bytes instead of only one (which is the value content).

Hope this can help. Best regards,

wstrange commented 2 years ago

Do you know what those last 5 bytes represent? In Hex, 71 01 00 FE 00.

I think that is a possibly a SET? I'm trying to decode that using an online decoder, and it doesn't seem to be valid asn1?

Is it possible those bytes are meant to be part of the previous message (i.e. the length of previous message should include those bytes). What does the Go code parse that object as?

obalak commented 2 years ago

When parsing using Go, the returned objects are correctly parsed ASN.1 objects as you can see below:

[]encoding/asn1.RawValue len: 3, cap: 4, [
        {
                Class: 1,
                Tag: 16,
                IsCompound: true,
                Bytes: []uint8 len: 579, cap: 584, [48,130,2,63,48,130,1,161,160,3,2,1,2,2,17,0,241,37,53,1,245,101,254,123,227,232,24,198,233,209,186,121,48,10,6,8,42,134,72,206,61,4,3,4,48,53,49,22,48,20,6,3,85,4,3,19,13,81,83,97,102,101,32,82,...+515 more],
                FullBytes: []uint8 len: 583, cap: 588, [112,130,2,67,48,130,2,63,48,130,1,161,160,3,2,1,2,2,17,0,241,37,53,1,245,101,254,123,227,232,24,198,233,209,186,121,48,10,6,8,42,134,72,206,61,4,3,4,48,53,49,22,48,20,6,3,85,4,3,19,13,81,83,97,...+519 more],},
        {
                Class: 1,
                Tag: 17,
                IsCompound: true,
                Bytes: []uint8 len: 1, cap: 3, [0],
                FullBytes: []uint8 len: 3, cap: 5, [113,1,0],},
        {
                Class: 3,
                Tag: 30,
                IsCompound: true,
                Bytes: []uint8 len: 0, cap: 0, [],
                FullBytes: []uint8 len: 2, cap: 2, [254,0],},
]

When debugging in dart, it seems for me that the encoding bytes are overwritten with the value bytes. Here is a test certificate, I'm using:

-----BEGIN CERTIFICATE-----
MIICPzCCAaGgAwIBAgIRAPElNQH1Zf574+gYxunRunkwCgYIKoZIzj0EAwQwNTEW
MBQGA1UEAxMNUVNhZmUgUm9vdCBDQTELMAkGA1UEBhMCQ0gxDjAMBgNVBAoTBXFz
YWZlMB4XDTIyMTAxMzE0NDg0NFoXDTMyMTAxMDE0NDg0NFowPjEfMB0GA1UEAxMW
UVNhZmUgTWFuYWdlbWVudCBTdWJDQTELMAkGA1UEBhMCQ0gxDjAMBgNVBAoTBXFz
YWZlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9SWgzbrJhDcO/x++1fhHhae7
+aCF/e1Q8PH95kxpcsXRbwJUaRzOJRqr6z6F+rZ5TaqiiuThjXUCwdAhyuU42KOB
iDCBhTAhBgNVHQ4EGgQYslYllZJjRy3vVHfJ4PckyiG3ao+lSiZdMA4GA1UdDwEB
/wQEAwIBBjAXBgNVHREEEDAOgQxxbXNAcXNhZmUuY2gwEgYDVR0TAQH/BAgwBgEB
/wIBATAjBgNVHSMEHDAagBjMCERuxctYw37BbTt4TbhmA1sLUC2s1RUwCgYIKoZI
zj0EAwQDgYsAMIGHAkIByxKSZ6MHvIWNBy/8qvz0+fRRbBEaHBEXcNFBiTftfK8F
MwWOvqtn/aiPUn5Vnml65D78hEll4Q/pD0p+hECMnfUCQSMOWOXD0aHl3WaD7R04
GWqAJPFa3hnYHmlogrdJ4LlzZUPVkMT4d00yihVl5KiwhmQUyh6jL5u0Eu357ptL
M1/+
-----END CERTIFICATE-----

The above certificate is correct and should correspond to only the first object since the returned data is coming from PIV slot on HW security key. The second object might be certificate info with lenght 1 which is correct according the NIST specs that I verified.

Hope this can help.

wstrange commented 2 years ago

Hmm. Have you looked at the decodePEM() method in the example/main.dart.

If I paste your example cert into that, I dont get any exceptions. I get a single object back (a sequence) with 579 bytes.

Here is the sample:

import 'dart:typed_data';

import 'package:test/test.dart';
import 'package:asn1lib/asn1lib.dart';

import '../example/main.dart';

main() {
  test('cert test', () {
    var cert = '''
-----BEGIN CERTIFICATE-----
MIICPzCCAaGgAwIBAgIRAPElNQH1Zf574+gYxunRunkwCgYIKoZIzj0EAwQwNTEW
MBQGA1UEAxMNUVNhZmUgUm9vdCBDQTELMAkGA1UEBhMCQ0gxDjAMBgNVBAoTBXFz
YWZlMB4XDTIyMTAxMzE0NDg0NFoXDTMyMTAxMDE0NDg0NFowPjEfMB0GA1UEAxMW
UVNhZmUgTWFuYWdlbWVudCBTdWJDQTELMAkGA1UEBhMCQ0gxDjAMBgNVBAoTBXFz
YWZlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9SWgzbrJhDcO/x++1fhHhae7
+aCF/e1Q8PH95kxpcsXRbwJUaRzOJRqr6z6F+rZ5TaqiiuThjXUCwdAhyuU42KOB
iDCBhTAhBgNVHQ4EGgQYslYllZJjRy3vVHfJ4PckyiG3ao+lSiZdMA4GA1UdDwEB
/wQEAwIBBjAXBgNVHREEEDAOgQxxbXNAcXNhZmUuY2gwEgYDVR0TAQH/BAgwBgEB
/wIBATAjBgNVHSMEHDAagBjMCERuxctYw37BbTt4TbhmA1sLUC2s1RUwCgYIKoZI
zj0EAwQDgYsAMIGHAkIByxKSZ6MHvIWNBy/8qvz0+fRRbBEaHBEXcNFBiTftfK8F
MwWOvqtn/aiPUn5Vnml65D78hEll4Q/pD0p+hECMnfUCQSMOWOXD0aHl3WaD7R04
GWqAJPFa3hnYHmlogrdJ4LlzZUPVkMT4d00yihVl5KiwhmQUyh6jL5u0Eu357ptL
M1/+
-----END CERTIFICATE-----''';

    var bytes = decodePEM(cert);

    var parser = ASN1Parser(bytes);
    while( parser.hasNext() ) {
      var obj = parser.nextObject() as ASN1Sequence;
      print('sequence obj len = ${obj.totalEncodedByteLength}');
      for( var elem in obj.elements ){
        print('nested elem is $elem\n');
      }
    }
  });

}
obalak commented 2 years ago

Yeh, I understand that you do not get any exception when just looking to the certificate content alone. Sorry for misleading you.

In real the above certificate is correct and should correspond to only the first object. However, since the returned data (see first message) is coming from PIV slot on HW security key it should include 3 ASN.1 objects as shown in the Go parsing. The second object might be certificate info with lenght 1 which is correct according to the NIST specs that I verified. And the last one for termination.

Now, if we pass this content to your dart lib, the parsing does not behave in same way as for go parse or other tools.

Hope this help.

wstrange commented 2 years ago

Apologies, I'm not quite sure I grasp the issue. If the cert parses OK, Is it some nested value that is not being decoded correctly? Are you passing additional bytes beyond what is in the cert? (The PIV?)

Can you provide a test case with the minimum sequence of bytes that you think should parse correctly along with the expected asn1 encoding. It's not clear to me where those last 5 bytes [113, 1, 0, 254, 0] are coming from.

That tag looks like an "APPLICATION" tag followed by "PRIVATE" - so it may be that the dart lib is not correctly decoding one of those.

obalak commented 2 years ago

Yes, the PIV container is an ASN.1 object nesting other objects. The first object is the certificate (e.g. the one above) and the two others are the ones with tag 17 and tag 30 (see below the go parser result):

[]encoding/asn1.RawValue len: 3, cap: 4, [
        {
                Class: 1,
                Tag: 16,
                IsCompound: true,
                Bytes: []uint8 len: 579, cap: 584, [48,130,2,63,48,130,1,161,160,3,2,1,2,2,17,0,241,37,53,1,245,101,254,123,227,232,24,198,233,209,186,121,48,10,6,8,42,134,72,206,61,4,3,4,48,53,49,22,48,20,6,3,85,4,3,19,13,81,83,97,102,101,32,82,...+515 more],
                FullBytes: []uint8 len: 583, cap: 588, [112,130,2,67,48,130,2,63,48,130,1,161,160,3,2,1,2,2,17,0,241,37,53,1,245,101,254,123,227,232,24,198,233,209,186,121,48,10,6,8,42,134,72,206,61,4,3,4,48,53,49,22,48,20,6,3,85,4,3,19,13,81,83,97,...+519 more],},
        {
                Class: 1,
                Tag: 17,
                IsCompound: true,
                Bytes: []uint8 len: 1, cap: 3, [0],
                FullBytes: []uint8 len: 3, cap: 5, [113,1,0],},
        {
                Class: 3,
                Tag: 30,
                IsCompound: true,
                Bytes: []uint8 len: 0, cap: 0, [],
                FullBytes: []uint8 len: 2, cap: 2, [254,0],},
]

You are right the other two last tags are Application specific but they are also ASN.1 object that should be parsed correctly.

Here is a dart example with the data I'm getting from the PIV HW key:

import 'dart:typed_data';
import 'package:asn1lib/asn1lib.dart';

main() {

    //@formatter:off
    var bytes = [112, 130, 2, 67, 48, 130, 2, 63, 48, 130, 1, 161, 160, 3, 2, 1, 2, 2, 17, 0, 241, 37, 53, 
    1, 245, 101, 254, 123, 227, 232, 24, 198, 233, 209, 186, 121, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 
    4, 48, 53, 49, 22, 48, 20, 6, 3, 85, 4, 3, 19, 13, 81, 83, 97, 102, 101, 32, 82, 111, 111, 116, 32, 67, 
    65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 67, 72, 49, 14, 48, 12, 6, 3, 85, 4, 10, 19, 5, 113, 115, 97, 
    102, 101, 48, 30, 23, 13, 50, 50, 49, 48, 49, 51, 49, 52, 52, 56, 52, 52, 90, 23, 13, 51, 50, 49, 48, 
    49, 48, 49, 52, 52, 56, 52, 52, 90, 48, 62, 49, 31, 48, 29, 6, 3, 85, 4, 3, 19, 22, 81, 83, 97, 102, 
    101, 32, 77, 97, 110, 97, 103, 101, 109, 101, 110, 116, 32, 83, 117, 98, 67, 65, 49, 11, 48, 9, 6, 3, 
    85, 4, 6, 19, 2, 67, 72, 49, 14, 48, 12, 6, 3, 85, 4, 10, 19, 5, 113, 115, 97, 102, 101, 48, 89, 48, 19,
     6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 3, 66, 0, 4, 245, 37, 160, 205, 
     186, 201, 132, 55, 14, 255, 31, 190, 213, 248, 71, 133, 167, 187, 249, 160, 133, 253, 237, 80, 240, 241, 
     253, 230, 76, 105, 114, 197, 209, 111, 2, 84, 105, 28, 206, 37, 26, 171, 235, 62, 133, 250, 182, 121, 77,
      170, 162, 138, 228, 225, 141, 117, 2, 193, 208, 33, 202, 229, 56, 216, 163, 129, 136, 48, 129, 133, 48,
       33, 6, 3, 85, 29, 14, 4, 26, 4, 24, 178, 86, 37, 149, 146, 99, 71, 45, 239, 84, 119, 201, 224, 247, 36, 
       202, 33, 183, 106, 143, 165, 74, 38, 93, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 23, 
       6, 3, 85, 29, 17, 4, 16, 48, 14, 129, 12, 113, 109, 115, 64, 113, 115, 97, 102, 101, 46, 99, 104, 48, 
       18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2, 1, 1, 48, 35, 6, 3, 85, 29, 35, 4, 28, 48, 
       26, 128, 24, 204, 8, 68, 110, 197, 203, 88, 195, 126, 193, 109, 59, 120, 77, 184, 102, 3, 91, 11, 80, 
       45, 172, 213, 21, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 4, 3, 129, 139, 0, 48, 129, 135, 2, 66, 1, 
       203, 18, 146, 103, 163, 7, 188, 133, 141, 7, 47, 252, 170, 252, 244, 249, 244, 81, 108, 17, 26, 28, 17, 
       23, 112, 209, 65, 137, 55, 237, 124, 175, 5, 51, 5, 142, 190, 171, 103, 253, 168, 143, 82, 126, 85, 158, 
       105, 122, 228, 62, 252, 132, 73, 101, 225, 15, 233, 15, 74, 126, 132, 64, 140, 157, 245, 2, 65, 35, 14, 
       88, 229, 195, 209, 161, 229, 221, 102, 131, 237, 29, 56, 25, 106, 128, 36, 241, 90, 222, 25, 216, 30, 
       105, 104, 130, 183, 73, 224, 185, 115, 101, 67, 213, 144, 196, 248, 119, 77, 50, 138, 21, 101, 228, 168,
        176, 134, 100, 20, 202, 30, 163, 47, 155, 180, 18, 237, 249, 238, 155, 75, 51, 95, 254, 113, 1, 0, 254, 
        0]; //@formatter:on

  List<ASN1Object> objs = <ASN1Object>[];
  var rest = Uint8List.fromList(bytes);
  while (rest.isNotEmpty) {
    var asn1Parser = ASN1Parser(rest, relaxedParsing: true);
    var obj = asn1Parser.nextObject();
    objs.add(obj);

    if (objs.isNotEmpty && objs[0].valueBytes().isNotEmpty) {
    // We can parse then first element objs[0] as Certificate ...
    // This works fine.
  }
    rest = rest.sublist(obj.encodedBytes.length);
  }
}

The result is:

Unhandled exception: RangeError (index): Index out of range: index should be less than 1: 1

0 Uint8List.[] (dart:typed_data-patch/typed_data_patch.dart:2244:7)

1 ASN1Length.decodeLength (package:asn1lib/asn1length.dart:68:31)

2 ASN1Parser.nextObject (package:asn1lib/asn1parser.dart:38:29)

3 ASN1Sequence._decodeSeq (package:asn1lib/asn1sequence.dart:73:27)

4 new ASN1Sequence.fromBytes (package:asn1lib/asn1sequence.dart:23:5)

5 ASN1Parser.nextObject (package:asn1lib/asn1parser.dart:56:26)

6 main (file:///Users/obelakhdar/workspace/qsafe.ch/apps/dtest/bin/dtest.dart:601:26)

7 _delayEntrypointInvocation. (dart:isolate-patch/isolate_patch.dart:297:19)

8 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)

wstrange commented 2 years ago

My head is spinning reading ASN.1 documentation. [113,01,00] looks like a an APPLICATION SET that contains a single byte value of 00.

The problem is the set encoding does not look like it is legit BER. 0 isn't a valid object to embed in a set, but the application tag must modify the BER rules to allow this.

I can alter the parser code to not try to create a ASN1Set - just return it is a plain old ASN1Object. This works (I tested it) - but it breaks asn1_parser_test.dart that tests for alternate sequence encodings. I'm concerned I'll break someone else's code if I change this.

I need to think more on this

ASN1 really sucks

obalak commented 2 years ago

I understand. Thanks for your effort. At this stage, I'm not blocked since I can read the certificate and use it by forcing to get just the first object. However, I would like to avoid this. I will ask the key provider about this case and what is in there exactly. The PIV NIST documentation specifies clearly that you can have a tag 0x71 followed by 0x00 or 0x01 for certificate Info.

wstrange commented 2 years ago

I just published 1.2.0. I think it will address your problem. In short, there is a new optional flag added to the parser:

    var parser = ASN1Parser(bytes, encodeApplicationTagsAsObject: true);

If that flag is true, anytime it encounters an APPLICATION or PRIVATE tag it will simply encode it as a ASN1Object, instead of attempting to construct a sequence.

The default value of the optional flag is false, so as to preserve the existing behavior.

LMK if this works for your use case.

obalak commented 2 years ago

I tested the new version and both cases are working fine for me. Appreciate your active support. Many thanks.

wstrange commented 2 years ago

I may need to look at this again.

The recent changes I made to the APPLICATION parsing broke the dartdap LDAP library, which uses many APPLICATION tags with the "constructed" bit set. Those are expected to be a sequence

In the sequence you provide above, it's the last 5 bytes in the stream that cause issues.

      var pivBytes = Uint8List.fromList([113, 1, 0, 254, 0]); //  base64: cQEA/gA=

If you paste those bytes into the online javascript decoder, it doesnt like them either. Try

Narrowing it down further, it's the first of those two objects that are not valid. The 113, 1, 0 does not parse correctly. The last two bytes seem OK. 254,0 parses correctly as a PRIVATE class of length 0.

Try: https://lapo.it/asn1js/#cQEA

It gives essentially the same error, namely the length does not seem to decode properly. It could be that library also has a bug, but I do wonder if those PIV bytes need special handling. If you know in advance that they are coming in the stream, you can handle them without parsing by doing something like:

     var piv1 = Uint8List.fromList([113, 1, 0]);
     // This works and will not throw an exception since we avoid trying to
    // interpret as a sequence
      var obj1 = ASN1Application.fromBytes(piv1);

     // This parses ok as a PRIVATE class
      var piv2 = Uint8List.fromList([254, 0]);
      var p = ASN1Parser(piv2);
      var parsedPiv2 = p.nextObject();
      expect(parsedPiv2 , isA<ASN1Private>());
      expect(parsedPiv2.valueBytes().length, equals(0));

Is the Go code you are using doing something like the above?

I'm going to commit a fix to the asn1 library to fix the LDAP issue - so this may break your code. I'll reopen this issue until I hear from you.

obalak commented 2 years ago

Thanks Warren. I will check this during next week when back to office. I will let you know asap.