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 <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <[email protected]>
Gerrit-Reviewer: fixeria <[email protected]>
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: osmith <[email protected]>

Reply via email to