def test_derive_icc_mk_a_no_psn(pan: Union[bytes, str]) -> None: """ Verify ICC MK derivation method A with a zero PSN. Master Key Derivation = Option A ARQC verification using Common Session Key Derivation ARPC generation using ICC Master Key ARPC Method = 1 """ # 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_a(iss_mk, pan) # 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() == "3F4F" # ARQC validation using Session Key cipher_text = bytes.fromhex("0123456789ABCDEF0123456789ABCDEF") arqc = ac.generate_ac(sk_ac, cipher_text) assert arqc.hex().upper() == "8698A7319324FD93" # ARPC Method 1 using ICC Master Key arpc_rc = bytes.fromhex("0000") arpc = ac.generate_arpc_1(icc_mk, arqc, arpc_rc) assert arpc.hex().upper() == "BEA11C8F4A47EF6F"
def test_derive_icc_mk_a_psn(pan: Union[bytes, str], psn: Union[bytes, str]) -> None: """ Verify ICC MK derivation method A with non-zero PSN. Master Key Derivation = Option A ARQC verification using Common Session Key Derivation ARPC generation using ICC Master Key ARPC Method = 1 """ # 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_a(iss_mk, pan, psn) assert tools.key_check_digits(icc_mk, 2).hex().upper() == "FF08" # 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() == "DF82" # ARQC validation using Session Key cipher_text = bytes.fromhex("0123456789ABCDEF0123456789ABCDEF") arqc = ac.generate_ac(sk_ac, cipher_text) assert arqc.hex().upper() == "19C1FBC83EBDC0D5" # ARPC Method 1 using ICC Master Key arpc_rc = bytes.fromhex("0000") arpc = ac.generate_arpc_1(icc_mk, arqc, arpc_rc) assert arpc.hex().upper() == "78A372523FA35A03"
def test_generate_ac_visa_aprc1() -> None: r""" Test generate AC with Visa padding (\x00 padding). Master Key Derivation = Option A ARQC verification using Common Session Key Derivation ARPC generation using ICC Master Key ARPC Method = 1 """ # 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("0123456789ABCDEF0123456789ABCDEF01") arqc = ac.generate_ac(sk_ac, cipher_text, ac.PaddingType.VISA) assert arqc.hex().upper() == "2E141C6BC4A20DA8" # ARPC Method 1 using ICC Master Key arpc_rc = bytes.fromhex("0000") arpc = ac.generate_arpc_1(icc_mk, arqc, arpc_rc) assert arpc.hex().upper() == "16A49AAB314B9262"
def test_generate_ac_default_emv_arpc1() -> None: r""" Test generate AC with default EMV padding (\x80 padding). Master Key Derivation = Option A ARQC verification using Common Session Key Derivation ARPC generation using ICC Master Key ARPC Method = 1 """ # 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) assert arqc.hex().upper() == "4B46013359B7A58B" # ARPC Method 1 using ICC Master Key arpc_rc = bytes.fromhex("0000") arpc = ac.generate_arpc_1(icc_mk, arqc, arpc_rc) assert arpc.hex().upper() == "F8C9CECAABD55AD1"
def test_generate_ac_visa_aprc1_no_padding_required() -> None: r""" Test generate AC with Visa padding (\x00 padding). However, no padding is required. The data is already multiple of 8. Master Key Derivation = Option A ARQC verification using Common Session Key Derivation ARPC generation using ICC Master Key ARPC Method = 1 """ # 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.VISA) assert arqc.hex().upper() == "922F3E83125EB46B" # ARPC Method 1 using ICC Master Key arpc_rc = bytes.fromhex("0000") arpc = ac.generate_arpc_1(icc_mk, arqc, arpc_rc) assert arpc.hex().upper() == "8AE6E836084B0E80"
def test_derive_common_sk() -> None: """ Verify common session key derivation using algorithm type where both ARQC and ARPC are verified using derived session key. Master Key Derivation = Option A ARQC verification using Common Session Key Derivation ARPC generation using Common Session Key Derivation ARPC Method = 1 """ # 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 = "12345678901234567" psn = "45" icc_mk = kd.derive_icc_mk_a(iss_mk, pan, psn) assert tools.key_check_digits(icc_mk, 2).hex().upper() == "FF08" # 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() == "DF82" # ARQC validation using Session Key cipher_text = bytes.fromhex("0123456789ABCDEF0123456789ABCDEF") arqc = ac.generate_ac(sk_ac, cipher_text) assert arqc.hex().upper() == "19C1FBC83EBDC0D5" # ARPC Method 1 using Session Key arpc_rc = bytes.fromhex("0000") arpc = ac.generate_arpc_1(sk_ac, arqc, arpc_rc) assert arpc.hex().upper() == "C3620580668E5B65"
def test_generate_arpc_1_exception() -> None: # SK < 16 bytes with pytest.raises( ValueError, match="Session Key must be a double length DES key", ): ac.generate_arpc_1( sk_ac=bytes.fromhex("AAAAAAAAAAAAAAAA"), arqc=bytes.fromhex("12345678"), arpc_rc=bytes.fromhex("0000"), ) # SK > 16 bytes with pytest.raises( ValueError, match="Session Key must be a double length DES key", ): ac.generate_arpc_1( sk_ac=bytes.fromhex( "AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC"), arqc=bytes.fromhex("12345678"), arpc_rc=bytes.fromhex("0000"), ) # ARQC < 8 bytes with pytest.raises( ValueError, match="ARQC must be 8 bytes long", ): ac.generate_arpc_1( sk_ac=bytes.fromhex("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB"), arqc=bytes.fromhex("12345678"), arpc_rc=bytes.fromhex("0000"), ) # ARQC > 16 bytes with pytest.raises( ValueError, match="ARQC must be 8 bytes long", ): ac.generate_arpc_1( sk_ac=bytes.fromhex("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB"), arqc=bytes.fromhex("1234567890ABCDEF12"), arpc_rc=bytes.fromhex("0000"), ) # ARPC-RC < 2 bytes with pytest.raises( ValueError, match="ARPC-RC must be 2 bytes long", ): ac.generate_arpc_1( sk_ac=bytes.fromhex("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB"), arqc=bytes.fromhex("1234567890123456"), arpc_rc=bytes.fromhex("00"), ) # ARPC-RC > 2 bytes with pytest.raises( ValueError, match="ARPC-RC must be 2 bytes long", ): ac.generate_arpc_1( sk_ac=bytes.fromhex("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB"), arqc=bytes.fromhex("1234567890123456"), arpc_rc=bytes.fromhex("001122"), )