euicc: Implement EID checksum verification + computation

Change-Id: I2cb342783137ee7e4b1be3b14e9c3747316f1995
diff --git a/pySim/euicc.py b/pySim/euicc.py
index 96d95d6..e249f4f 100644
--- a/pySim/euicc.py
+++ b/pySim/euicc.py
@@ -32,6 +32,36 @@
 from pySim.utils import Hexstr, SwHexstr
 import pySim.global_platform
 
+def compute_eid_checksum(eid) -> str:
+    """Compute and add/replace check digits of an EID value according to GSMA SGP.29 Section 10."""
+    if type(eid) == str:
+        if len(eid) == 30:
+            # first pad by 2 digits
+            eid += "00"
+        elif len(eid) == 32:
+            # zero the last two digits
+            eid = eid[:-2] + "00"
+        else:
+            raise ValueError("and EID must be 30 or 32 digits")
+        eid_int = int(eid)
+    elif type(eid) == int:
+        eid_int = eid
+        if eid_int % 100:
+            # zero the last two digits
+            eid_int -= eid_int % 100
+    # Using the resulting 32 digits as a decimal integer, compute the remainder of that number on division by
+    # 97, Subtract the remainder from 98, and use the decimal result for the two check digits, if the result
+    # is one digit long, its value SHALL be prefixed by one digit of 0.
+    csum = 98 - (eid_int % 97)
+    eid_int += csum
+    return str(eid_int)
+
+def verify_eid_checksum(eid) -> bool:
+    """Verify the check digits of an EID value according to GSMA SGP.29 Section 10."""
+    # Using the 32 digits as a decimal integer, compute the remainder of that number on division by 97. If the
+    # remainder of the division is 1, the verification is successful; otherwise the EID is invalid.
+    return int(eid) % 97 == 1
+
 class VersionAdapter(Adapter):
     """convert an EUICC Version (3-int array) to a textual representation."""
 
diff --git a/tests/test_euicc.py b/tests/test_euicc.py
new file mode 100755
index 0000000..05d71ed
--- /dev/null
+++ b/tests/test_euicc.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+
+import unittest
+
+from pySim.euicc import *
+
+class TestEid(unittest.TestCase):
+
+    def test_eid_verify(self):
+        for eid in ['89049032123451234512345678901235', '89086030202200000022000023022943',
+                    '89044045116727494800000004479366', 89044045116727494800000004479366]:
+            self.assertTrue(verify_eid_checksum(eid))
+
+    def test_eid_verify_wrong(self):
+        self.assertFalse(verify_eid_checksum('89049032123451234512345678901234'))
+        self.assertFalse(verify_eid_checksum(89049032123451234512345678901234))
+
+    def test_eid_encode_with_32_digits(self):
+        self.assertEquals(compute_eid_checksum('89049032123451234512345678901200'), '89049032123451234512345678901235')
+        self.assertEquals(compute_eid_checksum('89086030202200000022000023022900'), '89086030202200000022000023022943')
+
+    def test_eid_encode_with_30digits(self):
+        self.assertEquals(compute_eid_checksum('890490321234512345123456789012'), '89049032123451234512345678901235')
+
+    def test_eid_encode_with_wrong_csum(self):
+        # input: EID with wrong checksum
+        self.assertEquals(compute_eid_checksum('89049032123451234512345678901299'), '89049032123451234512345678901235')
+        self.assertEquals(compute_eid_checksum(89049032123451234512345678901299), '89049032123451234512345678901235')
+
+if __name__ == "__main__":
+	unittest.main()