laforge has submitted this change. (
https://gerrit.osmocom.org/c/python/pyosmocom/+/38272?usp=email )
Change subject: osmocom.construct.Asn1DerInteger
......................................................................
osmocom.construct.Asn1DerInteger
This is a 'construct' type which can be used for encoding/decoding
integer values according to ASN.1 DER encoding rules.
Related: SYS#7094
Change-Id: I0cfe97daf957919de86453d6d44f9c99ab3075ac
---
M src/osmocom/construct.py
M tests/test_construct.py
2 files changed, 73 insertions(+), 0 deletions(-)
Approvals:
laforge: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/src/osmocom/construct.py b/src/osmocom/construct.py
index 7c0f034..5a78246 100644
--- a/src/osmocom/construct.py
+++ b/src/osmocom/construct.py
@@ -600,6 +600,19 @@
stream_write(stream, data, length, path)
return obj
+class Asn1DerInteger(Construct):
+ """A signed integer value using ASN.1 DER encoding rules (see also
ITU-T X.690 8.3)"""
+ def _parse(self, stream, context, path):
+ data = stream_read_entire(stream, path)
+ return int.from_bytes(data, byteorder='big', signed=True)
+
+ def _build(self, obj, stream, context, path):
+ if not isinstance(obj, integertypes):
+ raise IntegerError(f"value {obj} is not an integer", path=path)
+ val = obj.to_bytes(int_bytes_required(obj, signed=True), byteorder='big',
signed=True)
+ stream_write(stream, val, len(val), path)
+ return obj
+
# merged definitions of 24.008 + 23.040
TypeOfNumber = Enum(BitsInteger(3), unknown=0, international=1, national=2,
network_specific=3,
short_code=4, alphanumeric=5, abbreviated=6,
reserved_for_extension=7)
diff --git a/tests/test_construct.py b/tests/test_construct.py
index c2aeece..ba4f8f4 100755
--- a/tests/test_construct.py
+++ b/tests/test_construct.py
@@ -114,6 +114,66 @@
self.assertEqual(re_enc, enc)
+class TestAsn1DerInteger(unittest.TestCase):
+
+ tests = [
+ # positive numbers
+ ( b'\x00', 0 ),
+ ( b'\x01', 1 ),
+ ( b'\x02', 2 ),
+ ( b'\x7f', 127 ),
+ ( b'\x00\x80', 128 ),
+ ( b'\x00\x81', 129 ),
+ ( b'\x00\xfe', 254 ),
+ ( b'\x01\x00', 256 ),
+ ( b'\x01\x01', 257 ),
+ ( b'\x7f\xff', 32767 ),
+ ( b'\x00\x80\x00', 32768 ),
+ ( b'\x00\x80\x01', 32769 ),
+ ( b'\x00\xff\xfe', 65534 ),
+ ( b'\x00\xff\xff', 65535 ),
+ ( b'\x01\x00\x00', 65536 ),
+
+ # negative numbers
+ ( b'\x00', -0 ),
+ ( b'\xff', -1 ),
+ ( b'\xfe', -2 ),
+ ( b'\x81', -127 ),
+ ( b'\x80', -128 ),
+ ( b'\xff\x7f', -129 ),
+ ( b'\xff\x02', -254 ),
+ ( b'\xff\x00', -256 ),
+ ( b'\xfe\xff', -257 ),
+ ( b'\x80\x01', -32767 ),
+ ( b'\x80\x00', -32768 ),
+ ( b'\xff\x7f\xff', -32769 ),
+ ( b'\xff\x00\x02', -65534 ),
+ ( b'\xff\x00\x01', -65535 ),
+ ( b'\xff\x00\x00', -65536 ),
+ ]
+
+ def test_encode(self):
+ adi = Asn1DerInteger()
+
+ # Verfiy with chosen numbers
+ for t in self.tests:
+ self.assertEqual(t[0], adi.build(t[1]))
+
+ # Verify that ITU-T X.690 8.3.2 is always complied with (for standard two's
+ # complement that should always be the case)
+ for i in range(-100000,100000):
+ res = adi.build(i)
+ if len(res) > 1:
+ self.assertFalse(int(res[0]) == 0xff and int(res[1]) & 0x80 == 0x80)
+ self.assertFalse(int(res[0]) == 0x00 and int(res[1]) & 0x80 == 0x00)
+
+ def test_decode(self):
+ adi = Asn1DerInteger()
+
+ # Verfiy with chosen numbers
+ for t in self.tests:
+ self.assertEqual(t[1], adi.parse(t[0]))
+
if __name__ == "__main__":
unittest.main()
--
To view, visit
https://gerrit.osmocom.org/c/python/pyosmocom/+/38272?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: python/pyosmocom
Gerrit-Branch: master
Gerrit-Change-Id: I0cfe97daf957919de86453d6d44f9c99ab3075ac
Gerrit-Change-Number: 38272
Gerrit-PatchSet: 8
Gerrit-Owner: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>