diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c8acd3d..c3e487b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,11 @@ Changelog ========= +UNRELEASED +---------- + +* Fix OID encoding/decoding for the first octet according to ITU-T X.690 + 2.7.0 (2023-01-17) ------------------ diff --git a/src/asn1.py b/src/asn1.py index 4d59205..b8b6919 100644 --- a/src/asn1.py +++ b/src/asn1.py @@ -388,7 +388,7 @@ def _encode_object_identifier(self, oid): # type: (str) -> bytes if not self._re_oid.match(oid): raise Error('Illegal object identifier') cmps = list(map(int, oid.split('.'))) - if cmps[0] > 39 or cmps[1] > 39: + if (cmps[0] <= 1 and cmps[1] > 39) or cmps[0] > 2: raise Error('Illegal object identifier') cmps = [40 * cmps[0] + cmps[1]] + cmps[2:] cmps.reverse() @@ -686,9 +686,12 @@ def _decode_object_identifier(bytes_data): # type: (bytes) -> str if not byte & 0x80: result.append(value) value = 0 - if len(result) == 0 or result[0] > 1599: + if len(result) == 0: raise Error('ASN1 syntax error') - result = [result[0] // 40, result[0] % 40] + result[1:] + if result[0] // 40 <= 1: + result = [result[0] // 40, result[0] % 40] + result[1:] + else: + result = [2, result[0] - 80] + result[1:] result = list(map(str, result)) return str('.'.join(result)) diff --git a/tests/test_asn1.py b/tests/test_asn1.py index e5ce2e8..c0134a6 100644 --- a/tests/test_asn1.py +++ b/tests/test_asn1.py @@ -177,10 +177,14 @@ def test_object_identifier(self): def test_long_object_identifier(self): enc = asn1.Encoder() enc.start() - enc.write('39.2.3', asn1.Numbers.ObjectIdentifier) + enc.write('2.1482.3', asn1.Numbers.ObjectIdentifier) res = enc.output() assert res == b'\x06\x03\x8c\x1a\x03' enc.start() + enc.write('2.999.3', asn1.Numbers.ObjectIdentifier) + res = enc.output() + assert res == b'\x06\x03\x88\x37\x03' + enc.start() enc.write('1.39.3', asn1.Numbers.ObjectIdentifier) res = enc.output() assert res == b'\x06\x02\x4f\x03' @@ -341,7 +345,7 @@ def test_error_object_identifier(self): enc = asn1.Encoder() enc.start() pytest.raises(asn1.Error, enc.write, '1', asn1.Numbers.ObjectIdentifier) - pytest.raises(asn1.Error, enc.write, '40.2.3', asn1.Numbers.ObjectIdentifier) + pytest.raises(asn1.Error, enc.write, '3.2.3', asn1.Numbers.ObjectIdentifier) pytest.raises(asn1.Error, enc.write, '1.40.3', asn1.Numbers.ObjectIdentifier) pytest.raises(asn1.Error, enc.write, '1.2.3.', asn1.Numbers.ObjectIdentifier) pytest.raises(asn1.Error, enc.write, '.1.2.3', asn1.Numbers.ObjectIdentifier) @@ -521,7 +525,11 @@ def test_long_object_identifier(self): buf = b'\x06\x03\x8c\x1a\x03' dec.start(buf) tag, val = dec.read() - assert val == u'39.2.3' + assert val == u'2.1482.3' + buf = b'\x06\x03\x88\x37\x03' + dec.start(buf) + tag, val = dec.read() + assert val == u'2.999.3' buf = b'\x06\x02\x4f\x03' dec.start(buf) tag, val = dec.read() @@ -745,13 +753,7 @@ def test_error_non_normalized_negative_integer(self): pytest.raises(asn1.Error, dec.read) def test_error_non_normalised_object_identifier(self): - buf = b'\x06\x02\x80\x01' - dec = asn1.Decoder() - dec.start(buf) - pytest.raises(asn1.Error, dec.read) - - def test_error_object_identifier_with_too_large_first_component(self): - buf = b'\x06\x02\x8c\x40' + buf = b'\x06\x02\x01\x80' dec = asn1.Decoder() dec.start(buf) pytest.raises(asn1.Error, dec.read) @@ -1079,12 +1081,22 @@ def test_octet_string(self): def test_null(self): TestEncoderDecoder.assert_encode_decode(None, asn1.Numbers.Null) - def test_object_identifier(self): + def test_real_object_identifier(self): TestEncoderDecoder.assert_encode_decode( '1.2.840.113554.1.2.1.1', asn1.Numbers.ObjectIdentifier ) + def test_long_object_identifier(self): + for v in \ + ( + '2.60.3', + '2.999.3', + '1.39.3', + '1.2.300000' + ): + TestEncoderDecoder.assert_encode_decode(v, asn1.Numbers.ObjectIdentifier) + def test_enumerated(self): for v in (1, 2, 42): TestEncoderDecoder.assert_encode_decode(v, asn1.Numbers.Enumerated)