def test_derive_icc_mk_b_pan18() -> None: """ Verify ICC MK derivation method B using 18 digit PAN. Master Key Derivation = Option B ARQC verification using Common Session Key Derivation ARPC generation using Common Session Key Derivation ARPC Method = 2 """ # Verify issuer master key check digits iss_mk = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210") assert tools.key_check_digits(iss_mk, 2).hex().upper() == "08D7" # Derive ICC master key pan = "123456789012345679" psn = "00" icc_mk = kd.derive_icc_mk_b(iss_mk, pan, psn) assert tools.key_check_digits(icc_mk, 2).hex().upper() == "C2F3" # Verify AC session key # Common Session Key Derivation Option r = bytes.fromhex("1234567890123456") sk_ac = kd.derive_common_sk(icc_mk, r) assert tools.key_check_digits(sk_ac, 2).hex().upper() == "7C35" # ARQC validation using Session Key cipher_text = bytes.fromhex("0123456789ABCDEF0123456789ABCDEF") arqc = ac.generate_ac(sk_ac, cipher_text) assert arqc.hex().upper() == "DC95BCE3EBBE0296" # ARPC Method 2 using Session Key csu = bytes.fromhex("00000000") arpc = ac.generate_arpc_2(sk_ac, arqc, csu) assert arpc.hex().upper() == "ECCA0C4B"
def test_derive_icc_mk_b_pan17_no_psn(pan: Union[bytes, str]) -> None: """ Verify ICC MK derivation method B using 17 digit PAN. Master Key Derivation = Option B ARQC verification using Common Session Key Derivation ARPC generation using Common Session Key Derivation ARPC Method = 2 """ # Verify issuer master key check digits iss_mk = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210") assert tools.key_check_digits(iss_mk, 2).hex().upper() == "08D7" # Derive ICC master key icc_mk = kd.derive_icc_mk_b(iss_mk, pan) assert tools.key_check_digits(icc_mk, 2).hex().upper() == "4626" # Verify AC session key # Common Session Key Derivation Option r = bytes.fromhex("1234567890123456") sk_ac = kd.derive_common_sk(icc_mk, r) assert tools.key_check_digits(sk_ac, 2).hex().upper() == "7F36" # ARQC validation using Session Key cipher_text = bytes.fromhex("0123456789ABCDEF0123456789ABCDEF") arqc = ac.generate_ac(sk_ac, cipher_text) assert arqc.hex().upper() == "0BAA251EA8989442" # ARPC Method 2 using Session Key csu = bytes.fromhex("00000000") arpc = ac.generate_arpc_2(sk_ac, arqc, csu) assert arpc.hex().upper() == "C1C41F3A"
def test_derive_icc_mk_b_pan16() -> None: """ Verify ICC MK derivation method B using incompatible PAN length. Method B is applicable only if PAN is 17-19 digits long. Master Key Derivation = Option B ARQC verification using Common Session Key Derivation ARPC generation using Common Session Key Derivation ARPC Method = 2 """ # Verify issuer master key check digits iss_mk = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210") assert tools.key_check_digits(iss_mk, 2).hex().upper() == "08D7" # Derive ICC master key pan = "1234567890123456" icc_mk = kd.derive_icc_mk_b(iss_mk, pan) assert tools.key_check_digits(icc_mk, 2).hex().upper() == "BAB0" # Verify AC session key # Common Session Key Derivation Option r = bytes.fromhex("1234567890123456") sk_ac = kd.derive_common_sk(icc_mk, r) assert tools.key_check_digits(sk_ac, 2).hex().upper() == "BC19" # ARQC validation using Session Key cipher_text = bytes.fromhex("0123456789ABCDEF0123456789ABCDEF") arqc = ac.generate_ac(sk_ac, cipher_text) assert arqc.hex().upper() == "0CE77D211CB5459A" # ARPC Method 2 using Session Key csu = bytes.fromhex("00000000") arpc = ac.generate_arpc_2(sk_ac, arqc, csu) assert arpc.hex().upper() == "8CD9AA5D"
def test_generate_arpc2_no_prop_auth_data() -> None: r""" Test generate ARPC using method 2 without prop auth data. Master Key Derivation = Option A ARQC verification using Common Session Key Derivation ARPC generation using Common Session Key ARPC Method = 2 """ # Verify issuer master key check digits iss_mk = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210") assert tools.key_check_digits(iss_mk, 2).hex().upper() == "08D7" # Derive ICC master key pan = "9901234567890123" psn = "45" icc_mk = kd.derive_icc_mk_a(iss_mk, pan, psn) assert tools.key_check_digits(icc_mk, 2).hex().upper() == "1DA5" # Verify AC session key # Common Session Key Derivation Option r = bytes.fromhex("1234567890123456") sk_ac = kd.derive_common_sk(icc_mk, r) assert tools.key_check_digits(sk_ac, 2).hex().upper() == "0995" # ARQC validation using Session Key cipher_text = bytes.fromhex("0123456789ABCDEF0123456789ABCDEF") arqc = ac.generate_ac(sk_ac, cipher_text, ac.PaddingType.EMV) assert arqc.hex().upper() == "4B46013359B7A58B" # ARPC Method 2 using ICC Master Key csu = bytes.fromhex("00000000") arpc = ac.generate_arpc_2(sk_ac, arqc, csu) assert arpc.hex().upper() == "7DFB1188"
def test_derive_icc_mk_b_pan17_psn(): """ Verify ICC MK derivation method B using 17 digit PAN. Master Key Derivation = Option B ARQC verification using Common Session Key Derivation ARPC generation using Common Session Key Derivation ARPC Method = 2 """ # Verify issuer master key check digits iss_mk = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210") assert tools.key_check_digits(iss_mk, 2).hex().upper() == "08D7" # Derive ICC master key pan = b"12345678901234567" psn = b"45" icc_mk = kd.derive_icc_mk_b(iss_mk, pan, psn) assert tools.key_check_digits(icc_mk, 2).hex().upper() == "0BAF" # Verify AC session key # Common Session Key Derivation Option r = bytes.fromhex("1234567890123456") sk_ac = kd.derive_common_sk(icc_mk, r) assert tools.key_check_digits(sk_ac, 2).hex().upper() == "4262" # ARQC validation using Session Key cipher_text = bytes.fromhex("0123456789ABCDEF0123456789ABCDEF") arqc = ac.generate_ac(sk_ac, cipher_text) assert arqc.hex().upper() == "5760EE07B4FA65D1" # ARPC Method 2 using Session Key csu = bytes.fromhex("00000000") arpc = ac.generate_arpc_2(sk_ac, arqc, csu) assert arpc.hex().upper() == "106B81D9"
def test_derive_icc_mk_b_sha_pad() -> None: """ Verify ICC MK derivation method B where the algorithm is forced to convert sha digest letters into numbers. Master Key Derivation = Option B ARQC verification using Common Session Key Derivation ARPC generation using Common Session Key Derivation ARPC Method = 2 Note: in this test sha1 does not produce 16 digits. Use decimalisation table to convert hexchars to digits. e -> 4 """ # Verify issuer master key check digits iss_mk = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210") assert tools.key_check_digits(iss_mk, 2).hex().upper() == "08D7" # Derive ICC master key pan = "000000000000000005" psn = "23" icc_mk = kd.derive_icc_mk_b(iss_mk, pan, psn) assert tools.key_check_digits(icc_mk, 2).hex().upper() == "DD73" # Verify AC session key # Common Session Key Derivation Option r = bytes.fromhex("001C000000000000") sk_ac = kd.derive_common_sk(icc_mk, r) assert tools.key_check_digits(sk_ac, 2).hex().upper() == "04F8" # ARQC validation using Session Key cipher_text = bytes.fromhex("00000000400000000000000001248000048000012" "41911050152BF45851800001C06011203A0B800") arqc = ac.generate_ac(sk_ac, cipher_text) assert arqc.hex().upper() == "8CAD6F2489C640B1" # ARPC Method 2 using Session Key arqc = bytes.fromhex("8CAD6F2489C640B1") csu = bytes.fromhex("00000000") prop_auth_data = bytes.fromhex("12345678") arpc = ac.generate_arpc_2(sk_ac, arqc, csu, prop_auth_data) assert arpc.hex().upper() == "E39F1876"
def test_generate_arpc_2_exception() -> None: # SK < 16 bytes with pytest.raises( ValueError, match="Session Key must be a double length DES key", ): ac.generate_arpc_2( sk_ac=bytes.fromhex("AAAAAAAAAAAAAAAA"), arqc=bytes.fromhex("12345678901214"), csu=bytes.fromhex("12345678"), prop_auth_data=bytes.fromhex("1234567890123456"), ) # SK > 16 bytes with pytest.raises( ValueError, match="Session Key must be a double length DES key", ): ac.generate_arpc_2( sk_ac=bytes.fromhex( "AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC"), arqc=bytes.fromhex("12345678901214"), csu=bytes.fromhex("12345678"), prop_auth_data=bytes.fromhex("1234567890123456"), ) # ARQC < 8 bytes with pytest.raises( ValueError, match="ARQC must be 8 bytes long", ): ac.generate_arpc_2( sk_ac=bytes.fromhex("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB"), arqc=bytes.fromhex("12345678901214"), csu=bytes.fromhex("12345678"), prop_auth_data=bytes.fromhex("1234567890123456"), ) # ARQC > 16 bytes with pytest.raises( ValueError, match="ARQC must be 8 bytes long", ): ac.generate_arpc_2( sk_ac=bytes.fromhex("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB"), arqc=bytes.fromhex("1234567890ABCDEF12"), csu=bytes.fromhex("12345678"), prop_auth_data=bytes.fromhex("1234567890123456"), ) # CSU < 4 bytes with pytest.raises( ValueError, match="CSU must be 4 bytes long", ): ac.generate_arpc_2( sk_ac=bytes.fromhex("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB"), arqc=bytes.fromhex("1234567890121456"), csu=bytes.fromhex("123456"), prop_auth_data=bytes.fromhex("1234567890123456"), ) # CSU > 4 bytes with pytest.raises( ValueError, match="CSU must be 4 bytes long", ): ac.generate_arpc_2( sk_ac=bytes.fromhex("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB"), arqc=bytes.fromhex("1234567890121456"), csu=bytes.fromhex("1234567890"), prop_auth_data=bytes.fromhex("1234567890123456"), ) # PAD > 8 bytes with pytest.raises( ValueError, match="Proprietary Authentication Data must be 0-8 bytes long", ): ac.generate_arpc_2( sk_ac=bytes.fromhex("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB"), arqc=bytes.fromhex("1234567890121456"), csu=bytes.fromhex("12345678"), prop_auth_data=bytes.fromhex("123456789012345678"), )