dexter has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/pysim/+/38118?usp=email )


Change subject: utils: support alpha identifier in enc/dec_msisdn
......................................................................

utils: support alpha identifier in enc/dec_msisdn

The functions enc_msisdn and dec_msisdn do not support encoding
and decoding of the alpha identifier. Let's extend the functions
accordingly.

Related: OS#5714
Change-Id: I19ec8ba14551ec282fc0cc12ae2f6d528bdfc527
---
M pySim-read.py
M pySim/utils.py
M tests/unittests/test_utils.py
3 files changed, 33 insertions(+), 14 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/18/38118/1

diff --git a/pySim-read.py b/pySim-read.py
index aae5ad4..7af40b2 100755
--- a/pySim-read.py
+++ b/pySim-read.py
@@ -209,7 +209,7 @@
         if sw == '9000':
             # (npi, ton, msisdn) = res
             if res is not None:
-                print("MSISDN (NPI=%d ToN=%d): %s" % res)
+                print("MSISDN (Alpha-Identifier=\"%s\" NPI=%d ToN=%d): %s" % 
res)
             else:
                 print("MSISDN: Not available")
         else:
diff --git a/pySim/utils.py b/pySim/utils.py
index 05ad962..aa69a18 100644
--- a/pySim/utils.py
+++ b/pySim/utils.py
@@ -355,8 +355,9 @@
     if len(ef_msisdn) < 14:
         raise ValueError("EF.MSISDN is too short")

-    # Skip optional Alpha Identifier
+    # Decode and skip optional Alpha Identifier
     xlen = len(ef_msisdn) - 14
+    alpha_id = h2s(b2h(ef_msisdn[0:xlen]))
     msisdn_lhv = ef_msisdn[xlen:]

     # Parse the length (in bytes) of the BCD encoded number
@@ -382,23 +383,28 @@
     if ton == 0x01:
         msisdn = '+' + msisdn

-    return (npi, ton, msisdn)
+    return (alpha_id, npi, ton, msisdn)


-def enc_msisdn(msisdn: str, npi: int = 0x01, ton: int = 0x03) -> Hexstr:
+def enc_msisdn(msisdn: str, npi: int = 0x01, ton: int = 0x03, alpha_id: str = 
"", rec_len: int = 14) -> Hexstr:
     """
     Encode MSISDN as LHV so it can be stored to EF.MSISDN.
-    See 3GPP TS 31.102, section 4.2.26 and 4.4.2.3. (The result
-    will not contain the optional Alpha Identifier at the beginning.)
+    See 3GPP TS 31.102, section 4.2.26 and 4.4.2.3.

     Default NPI / ToN values:
       - NPI: ISDN / telephony numbering plan (E.164 / E.163),
       - ToN: network specific or international number (if starts with '+').
+      - alpha_id: human readable string that serves a label for the MSISDN
+      - rec_len: overall record length of the encoded result (>= 14)
     """

-    # If no MSISDN is supplied then encode the file contents as all "ff"
+    # The resulting record length must have a length of at least 14 bytes.
+    if rec_len < 14:
+        raise ValueError("record length must be at least 14 bytess")
+
+    # If no MSISDN is supplied then encode the record contents as all "ff"
     if msisdn in ["", "+"]:
-        return "ff" * 14
+        return "ff" * rec_len

     # Leading '+' indicates International Number
     if msisdn[0] == '+':
@@ -418,7 +424,14 @@
     npi_ton = (npi & 0x0f) | ((ton & 0x07) << 4) | 0x80
     bcd = rpad(swap_nibbles(msisdn), 10 * 2)  # pad to 10 octets

-    return ('%02x' % bcd_len) + ('%02x' % npi_ton) + bcd + ("ff" * 2)
+    # Encode Alpha identifier
+    alpha_id_enc = s2h(alpha_id)
+    alpha_id_padding_len = rec_len - 14 - len(alpha_id)
+    if alpha_id_padding_len < 0:
+        raise ValueError("alpha_id too long, increase rec_len")
+    alpha_id_padding = "ff" * alpha_id_padding_len
+
+    return alpha_id_enc + alpha_id_padding + ('%02x' % bcd_len) + ('%02x' % 
npi_ton) + bcd + ("ff" * 2)


 def sanitize_pin_adm(pin_adm, pin_adm_hex=None) -> Hexstr:
diff --git a/tests/unittests/test_utils.py b/tests/unittests/test_utils.py
index 0e61a61..ed22a73 100755
--- a/tests/unittests/test_utils.py
+++ b/tests/unittests/test_utils.py
@@ -157,20 +157,26 @@
                self.assertEqual(msisdn_encoded, "ffffffffffffffffffffffffffff")
                msisdn_encoded = utils.enc_msisdn("+", npi=0x01, ton=0x03)
                self.assertEqual(msisdn_encoded, "ffffffffffffffffffffffffffff")
+               msisdn_encoded = utils.enc_msisdn("+4917279119183", npi=0x01, 
ton=0x01, alpha_id="Eigene Rufnummer", rec_len=34)
+               self.assertEqual(msisdn_encoded, 
"456967656e65205275666e756d6d6572ffffffff0891947172199181f3ffffffffff")

        def testDec_msisdn(self):
                msisdn_decoded = 
utils.dec_msisdn("0891946110325476f8ffffffffff")
-               self.assertEqual(msisdn_decoded, (1, 1, "+4916012345678"))
+               self.assertEqual(msisdn_decoded, ("", 1, 1, "+4916012345678"))
                msisdn_decoded = 
utils.dec_msisdn("04b1214365ffffffffffffffffff")
-               self.assertEqual(msisdn_decoded, (1, 3, "123456"))
+               self.assertEqual(msisdn_decoded, ("", 1, 3, "123456"))
                msisdn_decoded = 
utils.dec_msisdn("0bb121436587092143658709ffff")
-               self.assertEqual(msisdn_decoded, (1, 3, "12345678901234567890"))
+               self.assertEqual(msisdn_decoded, ("", 1, 3, 
"12345678901234567890"))
                msisdn_decoded = 
utils.dec_msisdn("ffffffffffffffffffffffffffff")
                self.assertEqual(msisdn_decoded, None)
                msisdn_decoded = 
utils.dec_msisdn("00112233445566778899AABBCCDDEEFF001122330bb121436587092143658709ffff")
-               self.assertEqual(msisdn_decoded, (1, 3, "12345678901234567890"))
+               self.assertEqual(msisdn_decoded, 
('\x00\x11"3DUfw\x88\x99ª»ÌÝî\x00\x11"3', 1, 3, "12345678901234567890"))
                msisdn_decoded = 
utils.dec_msisdn("ffffffffffffffffffffffffffffffffffffffff0bb121436587092143658709ffff")
-               self.assertEqual(msisdn_decoded, (1, 3, "12345678901234567890"))
+               self.assertEqual(msisdn_decoded, ("", 1, 3, 
"12345678901234567890"))
+               msisdn_decoded = 
utils.dec_msisdn("456967656e65205275666e756d6d6572ffffffff0891947172199181f3ffffffffff")
+               self.assertEqual(msisdn_decoded, ( "Eigene Rufnummer", 1, 1, 
"+4917279119183" ))
+               msisdn_decoded = 
utils.dec_msisdn("456967656e65205275666e756d6d65720891947172199181f3ffffffffff")
+               self.assertEqual(msisdn_decoded, ( "Eigene Rufnummer", 1, 1, 
"+4917279119183" ))

 class TestLuhn(unittest.TestCase):
     def test_verify(self):

--
To view, visit https://gerrit.osmocom.org/c/pysim/+/38118?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I19ec8ba14551ec282fc0cc12ae2f6d528bdfc527
Gerrit-Change-Number: 38118
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <[email protected]>

Reply via email to