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_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_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_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_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_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_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_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_generate_command_mac(): """ Test generation of script command data MAC Master Key Derivation = Option A SMI using Common Session Key Derivation (EMV SU-46) MAC generation script command is padded with 0x80 """ # Verify issuer master key check digits iss_mk_smi = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210") assert tools.key_check_digits(iss_mk_smi, 2).hex().upper() == "08D7" # Derive ICC master key pan = b"1234567890123456" psn = b"01" icc_mk_smi = kd.derive_icc_mk_a(iss_mk_smi, pan, psn) assert tools.key_check_digits(icc_mk_smi, 2).hex().upper() == "0239" # Verify SMI session key # Common Session Key Derivation Option r = bytes.fromhex("ABCDEF1234567890") sk_smi = kd.derive_common_sk(icc_mk_smi, r) assert tools.key_check_digits(sk_smi, 2).hex().upper() == "F088" # Script MAC generated using Session Key script_command = bytes.fromhex("8424000008") mac = sm.generate_command_mac(sk_smi, script_command) assert mac.hex().upper() == "CF323F09A0F6AB9E"
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_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_vis_change_current_pin_12(): """ Test generation of offline PIN script with VIS PIN block with current PIN Both PINs are 12 digits long. Master Key Derivation = Option A SMI/SMC using Visa Session Key Derivation PIN encipherment with mandatory Visa padding """ # Verify issuer master key check digits iss_mk_ac = bytes.fromhex("FEDCBA98765432100123456789ABCDEF") assert tools.key_check_digits(iss_mk_ac, 3).hex().upper() == "7B8358" iss_mk_smc = bytes.fromhex("11111111111111112222222222222222") assert tools.key_check_digits(iss_mk_smc, 3).hex().upper() == "D2B91C" iss_mk_smi = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210") assert tools.key_check_digits(iss_mk_smi, 3).hex().upper() == "08D7B4" # Derive ICC master keys pan = b"1234567890123456" psn = b"01" icc_mk_ac = kd.derive_icc_mk_a(iss_mk_ac, pan, psn) assert tools.key_check_digits(icc_mk_ac, 3).hex().upper() == "C5CACD" icc_mk_smc = kd.derive_icc_mk_a(iss_mk_smc, pan, psn) assert tools.key_check_digits(icc_mk_smc, 3).hex().upper() == "6B0F76" icc_mk_smi = kd.derive_icc_mk_a(iss_mk_smi, pan, psn) assert tools.key_check_digits(icc_mk_smi, 3).hex().upper() == "02396B" # Verify SMC/SMI session key # Common Session Key Derivation Option r = bytes.fromhex("FFFF") sk_smc = kd.derive_visa_sm_sk(icc_mk_smc, r) assert tools.key_check_digits(sk_smc, 3).hex().upper() == "BD7C46" sk_smi = kd.derive_visa_sm_sk(icc_mk_smi, r) assert tools.key_check_digits(sk_smi, 3).hex().upper() == "A41D47" # Encrypt new PIN pin_block = sm.format_vis_pin_block(icc_mk_ac, b"999999999999", b"888888888888") assert pin_block.hex().upper() == "841111112A5E67F1" command_data = sm.encrypt_command_data(sk_smc, pin_block, sm.EncryptionType.VISA) assert command_data.hex().upper() == "622066A74F1E974AEE671384F0D3A7B9" # Script MAC generated using Session Key command_header = bytes.fromhex("8424000110") mac = sm.generate_command_mac(sk_smi, command_header + command_data) assert mac.hex().upper() == "829AC5DE4B88074D"
def test_vis_change_change_current_pin(pin: Union[bytes, str], current_pin: Union[bytes, str]) -> None: """ Test generation of offline PIN script with VIS PIN block with current PIN Master Key Derivation = Option A SMI/SMC using Visa Session Key Derivation PIN encipherment with mandatory Visa padding """ # Verify issuer master key check digits iss_mk_ac = bytes.fromhex("FEDCBA98765432100123456789ABCDEF") assert tools.key_check_digits(iss_mk_ac, 3).hex().upper() == "7B8358" iss_mk_smc = bytes.fromhex("11111111111111112222222222222222") assert tools.key_check_digits(iss_mk_smc, 3).hex().upper() == "D2B91C" iss_mk_smi = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210") assert tools.key_check_digits(iss_mk_smi, 3).hex().upper() == "08D7B4" # Derive ICC master keys pan = "1234567890123456" psn = "01" icc_mk_ac = kd.derive_icc_mk_a(iss_mk_ac, pan, psn) assert tools.key_check_digits(icc_mk_ac, 3).hex().upper() == "C5CACD" icc_mk_smc = kd.derive_icc_mk_a(iss_mk_smc, pan, psn) assert tools.key_check_digits(icc_mk_smc, 3).hex().upper() == "6B0F76" icc_mk_smi = kd.derive_icc_mk_a(iss_mk_smi, pan, psn) assert tools.key_check_digits(icc_mk_smi, 3).hex().upper() == "02396B" # Verify SMC/SMI session key # Common Session Key Derivation Option r = bytes.fromhex("FFFF") sk_smc = kd.derive_visa_sm_sk(icc_mk_smc, r) assert tools.key_check_digits(sk_smc, 3).hex().upper() == "BD7C46" sk_smi = kd.derive_visa_sm_sk(icc_mk_smi, r) assert tools.key_check_digits(sk_smi, 3).hex().upper() == "A41D47" # Encrypt new PIN pin_block = sm.format_vis_pin_block(icc_mk_ac, pin, current_pin) assert pin_block.hex().upper() == "8C1199FFC4B001F1" command_data = sm.encrypt_command_data(sk_smc, pin_block, sm.EncryptionType.VISA) assert command_data.hex().upper() == "C29371CC36BA70C1EE671384F0D3A7B9" # Script MAC generated using Session Key command_header = bytes.fromhex("8424000110") mac = sm.generate_command_mac(sk_smi, command_header + command_data) assert mac.hex().upper() == "6AB3AD15D8B0621A"
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_derive_visa_sm_sk() -> None: """ Verify visa session key derivation for secure messaging. """ # Verify issuer master key check digits iss_mk = bytes.fromhex("FEDCBA98765432100123456789ABCDEF") assert tools.key_check_digits(iss_mk, 2).hex().upper() == "7B83" # 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() == "F010" # Verify AC session key atc = bytes.fromhex("001C") arqc = bytes.fromhex("29CCA15AE665FA2E") sk_sm = kd.derive_visa_sm_sk(icc_mk, atc) assert tools.key_check_digits(sk_sm, 2).hex().upper() == "DB10" # Command MAC generation using Session Key command_header = bytes.fromhex("8418000008") mac = sm.generate_command_mac(sk_sm, command_header + atc + arqc) assert mac.hex().upper() == "DB56BA60087CEFD3"
def test_mastercard_pin_change_12(): """ Test generation of offline PIN script with ISO format 2 PIN block PIN is 12 digits long. Master Key Derivation = Option A SMI/SMC using Common Session Key Derivation (EMV SU-46) PIN encipherment with optional padding when block is not multiple of 8. However, no padding takes place because PIN block is 8 bytes long. """ # Verify issuer master key check digits iss_mk_smc = bytes.fromhex("11111111111111112222222222222222") assert tools.key_check_digits(iss_mk_smc, 3).hex().upper() == "D2B91C" iss_mk_smi = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210") assert tools.key_check_digits(iss_mk_smi, 3).hex().upper() == "08D7B4" # Derive ICC master keys pan = b"1234567890123456" psn = b"01" icc_mk_smc = kd.derive_icc_mk_a(iss_mk_smc, pan, psn) assert tools.key_check_digits(icc_mk_smc, 3).hex().upper() == "6B0F76" icc_mk_smi = kd.derive_icc_mk_a(iss_mk_smi, pan, psn) assert tools.key_check_digits(icc_mk_smi, 3).hex().upper() == "02396B" # Verify SMC/SMI session key # Common Session Key Derivation Option r = bytes.fromhex("ABCDEF1234567890") sk_smc = kd.derive_common_sk(icc_mk_smc, r) assert tools.key_check_digits(sk_smc, 3).hex().upper() == "D694B8" sk_smi = kd.derive_common_sk(icc_mk_smi, r) assert tools.key_check_digits(sk_smi, 3).hex().upper() == "F088F8" # Encrypt new PIN pin_block = sm.format_iso9564_2_pin_block(b"999999999999") assert pin_block.hex().upper() == "2C999999999999FF" command_data = sm.encrypt_command_data(sk_smc, pin_block, sm.EncryptionType.MASTERCARD) assert command_data.hex().upper() == "99AD3AF9EB3ECF0C" # Script MAC generated using Session Key command_header = bytes.fromhex("8424000210") mac = sm.generate_command_mac(sk_smi, command_header + command_data) assert mac.hex().upper() == "1471D88C6393BE21"
def test_ccd_pin_change(pin: Union[bytes, str]) -> None: """ Test generation of offline PIN script with ISO format 2 PIN block' Common Core Definition. Mandatory padding. Master Key Derivation = Option A SMI/SMC using Common Session Key Derivation (EMV SU-46) PIN encipherment with optional padding when block is not multiple of 8. However, no padding takes place because PIN block is 8 bytes long. """ # Verify issuer master key check digits iss_mk_smc = bytes.fromhex("11111111111111112222222222222222") assert tools.key_check_digits(iss_mk_smc, 3).hex().upper() == "D2B91C" iss_mk_smi = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210") assert tools.key_check_digits(iss_mk_smi, 3).hex().upper() == "08D7B4" # Derive ICC master keys pan = "1234567890123456" psn = "01" icc_mk_smc = kd.derive_icc_mk_a(iss_mk_smc, pan, psn) assert tools.key_check_digits(icc_mk_smc, 3).hex().upper() == "6B0F76" icc_mk_smi = kd.derive_icc_mk_a(iss_mk_smi, pan, psn) assert tools.key_check_digits(icc_mk_smi, 3).hex().upper() == "02396B" # Verify SMC/SMI session key # Common Session Key Derivation Option r = bytes.fromhex("ABCDEF1234567890") sk_smc = kd.derive_common_sk(icc_mk_smc, r) assert tools.key_check_digits(sk_smc, 3).hex().upper() == "D694B8" sk_smi = kd.derive_common_sk(icc_mk_smi, r) assert tools.key_check_digits(sk_smi, 3).hex().upper() == "F088F8" # Encrypt new PIN pin_block = sm.format_iso9564_2_pin_block(pin) assert pin_block.hex().upper() == "249999FFFFFFFFFF" command_data = sm.encrypt_command_data(sk_smc, pin_block, sm.EncryptionType.EMV) assert command_data.hex().upper() == "28367E05DE3381C29D30A6055A8DEB86" # Script MAC generated using Session Key command_header = bytes.fromhex("8424000210") mac = sm.generate_command_mac(sk_smi, command_header + command_data) assert mac.hex().upper() == "69DA1EE208823022"
def test_mastercard_cvn16(): """MasterCard CVN 16""" cvn16 = cvn.MasterCardCVN16( iss_mk_ac=bytes.fromhex("0123456789ABCDEFFEDCBA9876543210"), iss_mk_smi=bytes.fromhex("FEDCBA98765432100123456789ABCDEF"), iss_mk_smc=bytes.fromhex("89ABCDEF0123456776543210FEDCBA98"), pan=b"1234567890123456", psn=b"00", ) # Derive ICC Master Keys assert key_check_digits(cvn16.icc_mk_ac).hex().upper() == "BAB0" assert key_check_digits(cvn16.icc_mk_smi).hex().upper() == "F010" assert key_check_digits(cvn16.icc_mk_smc).hex().upper() == "B154" # ARQC and its session key atc = bytes.fromhex("001C") un = bytes.fromhex("ABCDEF12") arqc = cvn16.generate_ac( tag_9f02=bytes.fromhex("000000009999"), tag_9f03=bytes.fromhex("000000000000"), tag_9f1a=bytes.fromhex("0124"), tag_95=bytes.fromhex("8000000000"), tag_5f2a=bytes.fromhex("0124"), tag_9a=bytes.fromhex("209906"), tag_9c=bytes.fromhex("00"), tag_9f37=un, tag_82=bytes.fromhex("1800"), tag_9f36=atc, cvr=bytes.fromhex( "A00003220000"), # 9F10: 0110A00003220000000000000000000000FF ) assert arqc.hex().upper() == "24CCF3DEE3158C70" assert (key_check_digits(cvn16._derive_sk_ac_mastercard( atc, un)).hex().upper() == "2FD5") # ARPC and its session key (no session key, uses ICC MK AC) arpc = cvn16.generate_arpc(tag_9f26=arqc, arpc_rc=bytes.fromhex("0010")) assert arpc.hex().upper() == "73F6BBF389A6586C" assert key_check_digits( cvn16._derive_sk_arpc_none()).hex().upper() == "BAB0" # MAC PIN unblock command and its session key # 72169F180400000000860D8424000008ED0AB162BAB1DE61 mac = cvn16.generate_command_mac(bytes.fromhex("8424000008"), tag_9f26=arqc, tag_9f36=atc) assert mac.hex().upper() == "ED0AB162BAB1DE61" assert (key_check_digits(cvn16._derive_sk_sm_common( cvn16.icc_mk_smi, arqc)).hex().upper() == "FFA0") # PIN change without current PIN and its session keys # 721E9F1804000000008615842400021000859B8FE53F316DED0AB162BAB1DE61 pin_command = cvn16.generate_pin_change_command(b"9999", tag_9f26=arqc, tag_9f36=atc) assert pin_command.hex().upper( ) == "842400021000859B8FE53F316DEB4B64C36BF88E39" assert (key_check_digits(cvn16._derive_sk_sm_common( cvn16.icc_mk_smc, arqc)).hex().upper() == "0BCA") assert (key_check_digits(cvn16._derive_sk_sm_common( cvn16.icc_mk_smi, arqc)).hex().upper() == "FFA0")
def test_mastercard_cvn17(): """MasterCard CVN 17""" cvn17 = cvn.MasterCardCVN17( iss_mk_ac=bytes.fromhex("0123456789ABCDEFFEDCBA9876543210"), iss_mk_smi=bytes.fromhex("FEDCBA98765432100123456789ABCDEF"), iss_mk_smc=bytes.fromhex("89ABCDEF0123456776543210FEDCBA98"), pan=b"1234567890123456", psn=b"00", ) # Derive ICC Master Keys assert key_check_digits(cvn17.icc_mk_ac).hex().upper() == "BAB0" assert key_check_digits(cvn17.icc_mk_smi).hex().upper() == "F010" assert key_check_digits(cvn17.icc_mk_smc).hex().upper() == "B154" # ARQC and its session key atc = bytes.fromhex("001C") un = bytes.fromhex("ABCDEF12") arqc = cvn17.generate_ac( tag_9f02=bytes.fromhex("000000009999"), tag_9f03=bytes.fromhex("000000000000"), tag_9f1a=bytes.fromhex("0124"), tag_95=bytes.fromhex("8000000000"), tag_5f2a=bytes.fromhex("0124"), tag_9a=bytes.fromhex("209906"), tag_9c=bytes.fromhex("00"), tag_9f37=un, tag_82=bytes.fromhex("1800"), tag_9f36=atc, cvr=bytes.fromhex( "A00003220000"), # 9F10: 0111A00003220000000000000000000322FF counters=bytes.fromhex("00000000000322FF"), ) assert arqc.hex().upper() == "EAE8A620A75648D8" assert (key_check_digits(cvn17._derive_sk_ac_mastercard( atc, un)).hex().upper() == "2FD5") # ARPC and its session key (no session key, uses ICC MK AC) arpc = cvn17.generate_arpc(tag_9f26=arqc, arpc_rc=bytes.fromhex("0010")) assert arpc.hex().upper() == "29CF11FBDB9CA650" assert key_check_digits( cvn17._derive_sk_arpc_none()).hex().upper() == "BAB0" # MAC PIN unblock command and its session key # 72169F180400000000860D84240000084D1858456CD0F22A mac = cvn17.generate_command_mac(bytes.fromhex("8424000008"), tag_9f26=arqc, tag_9f36=atc) assert mac.hex().upper() == "4D1858456CD0F22A" assert (key_check_digits(cvn17._derive_sk_sm_common( cvn17.icc_mk_smi, arqc)).hex().upper() == "6CAF") # PIN change without current PIN and its session keys # 721E9F180400000000861584240002108661C474E4940A4378390C64CB96756E pin_command = cvn17.generate_pin_change_command(b"9999", tag_9f26=arqc, tag_9f36=atc) assert pin_command.hex().upper( ) == "84240002108661C474E4940A4378390C64CB96756E" assert (key_check_digits(cvn17._derive_sk_sm_common( cvn17.icc_mk_smc, arqc)).hex().upper() == "3D99") assert (key_check_digits(cvn17._derive_sk_sm_common( cvn17.icc_mk_smi, arqc)).hex().upper() == "6CAF")
def test_mastercard_cvn20(): """MasterCard CVN 20""" cvn20 = cvn.MasterCardCVN20( iss_mk_ac=bytes.fromhex("0123456789ABCDEFFEDCBA9876543210"), iss_mk_smi=bytes.fromhex("FEDCBA98765432100123456789ABCDEF"), iss_mk_smc=bytes.fromhex("89ABCDEF0123456776543210FEDCBA98"), pan=b"1234567890123456", psn=b"00", ) # Derive ICC Master Keys assert key_check_digits(cvn20.icc_mk_ac).hex().upper() == "BAB0" assert key_check_digits(cvn20.icc_mk_smi).hex().upper() == "F010" assert key_check_digits(cvn20.icc_mk_smc).hex().upper() == "B154" # ARQC and its session key atc = bytes.fromhex("001C") un = bytes.fromhex("ABCDEF12") arqc = cvn20.generate_ac( tag_9f02=bytes.fromhex("000000009999"), tag_9f03=bytes.fromhex("000000000000"), tag_9f1a=bytes.fromhex("0124"), tag_95=bytes.fromhex("8000000000"), tag_5f2a=bytes.fromhex("0124"), tag_9a=bytes.fromhex("209906"), tag_9c=bytes.fromhex("00"), tag_9f37=un, tag_82=bytes.fromhex("1800"), tag_9f36=atc, cvr=bytes.fromhex( "A00003220000"), # 9F10: 0110A00003220000000000000000000000FF ) assert arqc.hex().upper() == "CD29615D6452E70E" assert key_check_digits( cvn20._derive_sk_ac_common(atc)).hex().upper() == "22C8" # ARPC and its session key arpc = cvn20.generate_arpc(tag_9f26=arqc, tag_9f36=atc, arpc_rc=bytes.fromhex("0010")) assert arpc.hex().upper() == "DFD0956606B68D64" assert key_check_digits( cvn20._derive_sk_ac_common(atc)).hex().upper() == "22C8" # MAC PIN unblock command and its session key # 72169F180400000000860D842400000801C0F0DFBF6AA230 mac = cvn20.generate_command_mac(bytes.fromhex("8424000008"), tag_9f26=arqc, tag_9f36=atc) assert mac.hex().upper() == "01C0F0DFBF6AA230" assert (key_check_digits(cvn20._derive_sk_sm_common( cvn20.icc_mk_smi, arqc)).hex().upper() == "9240") # PIN change without current PIN and its session keys # 721E9F1804000000008615842400021000859B8FE53F316DED0AB162BAB1DE61 pin_command = cvn20.generate_pin_change_command(b"9999", tag_9f26=arqc, tag_9f36=atc) assert pin_command.hex().upper( ) == "84240002107647E71F85AA6A35AE4B4E838666773D" assert (key_check_digits(cvn20._derive_sk_sm_common( cvn20.icc_mk_smc, arqc)).hex().upper() == "B087") assert (key_check_digits(cvn20._derive_sk_sm_common( cvn20.icc_mk_smi, arqc)).hex().upper() == "9240")
def test_visa_cvn10(): """Visa CVN 10""" cvn10 = cvn.VisaCVN10( iss_mk_ac=bytes.fromhex("0123456789ABCDEFFEDCBA9876543210"), iss_mk_smi=bytes.fromhex("FEDCBA98765432100123456789ABCDEF"), iss_mk_smc=bytes.fromhex("89ABCDEF0123456776543210FEDCBA98"), pan=b"1234567890123456", psn=b"00", ) # Check ICC Master Keys assert key_check_digits(cvn10.icc_mk_ac).hex().upper() == "BAB0" assert key_check_digits(cvn10.icc_mk_smi).hex().upper() == "F010" assert key_check_digits(cvn10.icc_mk_smc).hex().upper() == "B154" # ARQC and its session key atc = bytes.fromhex("001C") arqc = cvn10.generate_ac( tag_9f02=bytes.fromhex("000000004000"), tag_9f03=bytes.fromhex("000000000000"), tag_9f1a=bytes.fromhex("0124"), tag_95=bytes.fromhex("8000048000"), tag_5f2a=bytes.fromhex("0124"), tag_9a=bytes.fromhex("191105"), tag_9c=bytes.fromhex("01"), tag_9f37=bytes.fromhex("52BF4585"), tag_82=bytes.fromhex("1800"), tag_9f36=atc, cvr=bytes.fromhex("03A06010"), ) assert arqc.hex().upper() == "29CCA15AE665FA2E" assert key_check_digits(cvn10._derive_sk_ac_none()).hex().upper() == "BAB0" # ARPC and its session key arpc = cvn10.generate_arpc(tag_9f26=arqc, arpc_rc=bytes.fromhex("3030")) assert arpc.hex().upper() == "28993816AFAE4AEB" assert key_check_digits(cvn10._derive_sk_ac_none()).hex().upper() == "BAB0" # MAC application unblock command and its session key mac = cvn10.generate_command_mac( bytes.fromhex("8418000008"), tag_9f26=arqc, tag_9f36=atc, ) assert mac.hex().upper() == "DB56BA60087CEFD3" assert (key_check_digits(cvn10._derive_sk_sm_visa( cvn10.icc_mk_smi, atc)).hex().upper() == "DB10") # PIN change without current PIN and its session keys pin_command = cvn10.generate_pin_change_command(b"9999", tag_9f26=arqc, tag_9f36=atc) assert (pin_command.hex().upper() == "8424000218BB221AF527377A2811D2B6EBC396A9391A965A5CB2CE62DA") assert (key_check_digits(cvn10._derive_sk_sm_visa( cvn10.icc_mk_smc, atc)).hex().upper() == "6D04") assert (key_check_digits(cvn10._derive_sk_sm_visa( cvn10.icc_mk_smi, atc)).hex().upper() == "DB10") # PIN change with current PIN and its session keys pin_command = cvn10.generate_pin_change_command(b"9999", tag_9f26=arqc, tag_9f36=atc, current_pin=b"8888") assert (pin_command.hex().upper() == "84240001182EE025E554BCD87E11D2B6EBC396A939C4A8393B57DD2F3F") assert (key_check_digits(cvn10._derive_sk_sm_visa( cvn10.icc_mk_smc, atc)).hex().upper() == "6D04") assert (key_check_digits(cvn10._derive_sk_sm_visa( cvn10.icc_mk_smi, atc)).hex().upper() == "DB10")
def test_mastercard_cvn21(): """MasterCard CVN 21""" cvn21 = cvn.MasterCardCVN21( iss_mk_ac=bytes.fromhex("0123456789ABCDEFFEDCBA9876543210"), iss_mk_smi=bytes.fromhex("FEDCBA98765432100123456789ABCDEF"), iss_mk_smc=bytes.fromhex("89ABCDEF0123456776543210FEDCBA98"), pan=b"1234567890123456", psn=b"00", ) # Derive ICC Master Keys assert key_check_digits(cvn21.icc_mk_ac).hex().upper() == "BAB0" assert key_check_digits(cvn21.icc_mk_smi).hex().upper() == "F010" assert key_check_digits(cvn21.icc_mk_smc).hex().upper() == "B154" # ARQC and its session key atc = bytes.fromhex("001C") un = bytes.fromhex("ABCDEF12") arqc = cvn21.generate_ac( tag_9f02=bytes.fromhex("000000009999"), tag_9f03=bytes.fromhex("000000000000"), tag_9f1a=bytes.fromhex("0124"), tag_95=bytes.fromhex("8000000000"), tag_5f2a=bytes.fromhex("0124"), tag_9a=bytes.fromhex("209906"), tag_9c=bytes.fromhex("00"), tag_9f37=un, tag_82=bytes.fromhex("1800"), tag_9f36=atc, cvr=bytes.fromhex( "A00003220000"), # 9F10: 0115A00003220000000000000000000322FF counters=bytes.fromhex("00000000000322FF"), ) assert arqc.hex().upper() == "C30E54BE496CF5E5" assert key_check_digits( cvn21._derive_sk_ac_common(atc)).hex().upper() == "22C8" # ARPC and its session key arpc = cvn21.generate_arpc(tag_9f26=arqc, tag_9f36=atc, arpc_rc=bytes.fromhex("0010")) assert arpc.hex().upper() == "4F51F9CC63CE8B3C" assert key_check_digits( cvn21._derive_sk_ac_common(atc)).hex().upper() == "22C8" # MAC PIN unblock command and its session key # 72169F180400000000860D84240000085E89E990C51CEE94 mac = cvn21.generate_command_mac(bytes.fromhex("8424000008"), tag_9f26=arqc, tag_9f36=atc) assert mac.hex().upper() == "5E89E990C51CEE94" assert (key_check_digits(cvn21._derive_sk_sm_common( cvn21.icc_mk_smi, arqc)).hex().upper() == "F4C4") # PIN change without current PIN and its session keys # 721E9F18040000000086158424000210D9F5896BE8E283C682264E1D32DF1D51 pin_command = cvn21.generate_pin_change_command(b"9999", tag_9f26=arqc, tag_9f36=atc) assert pin_command.hex().upper( ) == "8424000210D9F5896BE8E283C682264E1D32DF1D51" assert (key_check_digits(cvn21._derive_sk_sm_common( cvn21.icc_mk_smc, arqc)).hex().upper() == "BB95") assert (key_check_digits(cvn21._derive_sk_sm_common( cvn21.icc_mk_smi, arqc)).hex().upper() == "F4C4")
def test_visa_cvn18(): """Visa CVN 18""" cvn18 = cvn.VisaCVN18( iss_mk_ac=bytes.fromhex("0123456789ABCDEFFEDCBA9876543210"), iss_mk_smi=bytes.fromhex("FEDCBA98765432100123456789ABCDEF"), iss_mk_smc=bytes.fromhex("89ABCDEF0123456776543210FEDCBA98"), pan=b"1234567890123456", psn=b"00", ) # Check ICC Master Keys assert key_check_digits(cvn18.icc_mk_ac).hex().upper() == "BAB0" assert key_check_digits(cvn18.icc_mk_smi).hex().upper() == "F010" assert key_check_digits(cvn18.icc_mk_smc).hex().upper() == "B154" # ARQC and its session key atc = bytes.fromhex("001C") arqc = cvn18.generate_ac( tag_9f02=bytes.fromhex("000000004000"), tag_9f03=bytes.fromhex("000000000000"), tag_9f1a=bytes.fromhex("0124"), tag_95=bytes.fromhex("8000048000"), tag_5f2a=bytes.fromhex("0124"), tag_9a=bytes.fromhex("191105"), tag_9c=bytes.fromhex("01"), tag_9f37=bytes.fromhex("52BF4585"), tag_82=bytes.fromhex("1800"), tag_9f36=atc, tag_9f10=bytes.fromhex("06011203A0B800"), ) assert arqc.hex().upper() == "7A788EA6B8A3E733" assert key_check_digits( cvn18._derive_sk_ac_common(atc)).hex().upper() == "22C8" # ARPC and its session key arpc = cvn18.generate_arpc(tag_9f26=arqc, tag_9f36=atc, csu=bytes.fromhex("00000000")) assert arpc.hex().upper() == "9AF514C1" assert key_check_digits( cvn18._derive_sk_ac_common(atc)).hex().upper() == "22C8" # MAC application unblock command and its session key mac = cvn18.generate_command_mac( bytes.fromhex("8418000008"), tag_9f26=arqc, tag_9f36=atc, ) assert mac.hex().upper() == "04EDE90BC24CC35E" assert (key_check_digits(cvn18._derive_sk_sm_visa( cvn18.icc_mk_smi, atc)).hex().upper() == "DB10") # PIN change without current PIN and its session keys pin_command = cvn18.generate_pin_change_command(b"9999", tag_9f26=arqc, tag_9f36=atc) assert (pin_command.hex().upper() == "8424000218BB221AF527377A2811D2B6EBC396A9391A22B480EF312F40") assert (key_check_digits(cvn18._derive_sk_sm_visa( cvn18.icc_mk_smc, atc)).hex().upper() == "6D04") assert (key_check_digits(cvn18._derive_sk_sm_visa( cvn18.icc_mk_smi, atc)).hex().upper() == "DB10") # PIN change with current PIN and its session keys pin_command = cvn18.generate_pin_change_command(b"9999", tag_9f26=arqc, tag_9f36=atc, current_pin=b"8888") assert (pin_command.hex().upper() == "84240001182EE025E554BCD87E11D2B6EBC396A9390FB94A4E4EC10F41") assert (key_check_digits(cvn18._derive_sk_sm_visa( cvn18.icc_mk_smc, atc)).hex().upper() == "6D04") assert (key_check_digits(cvn18._derive_sk_sm_visa( cvn18.icc_mk_smi, atc)).hex().upper() == "DB10")
def test_interac_cvn133(): """Interac CVN 133""" cvn133 = cvn.InteracCVN133( iss_mk_ac=bytes.fromhex("0123456789ABCDEFFEDCBA9876543210"), iss_mk_smi=bytes.fromhex("FEDCBA98765432100123456789ABCDEF"), iss_mk_smc=bytes.fromhex("89ABCDEF0123456776543210FEDCBA98"), pan=b"1234567890123456", psn=b"00", ) # Derive ICC Master Keys assert key_check_digits(cvn133.icc_mk_ac).hex().upper() == "BAB0" assert key_check_digits(cvn133.icc_mk_smi).hex().upper() == "F010" assert key_check_digits(cvn133.icc_mk_smc).hex().upper() == "B154" # ARQC and its session key atc = bytes.fromhex("001C") un = bytes.fromhex("ABCDEF12") arqc = cvn133.generate_ac( tag_9f02=bytes.fromhex("000000009999"), tag_9f03=bytes.fromhex("000000000000"), tag_9f1a=bytes.fromhex("0124"), tag_95=bytes.fromhex("8000000000"), tag_5f2a=bytes.fromhex("0124"), tag_9a=bytes.fromhex("209906"), tag_9c=bytes.fromhex("00"), tag_9f37=un, tag_82=bytes.fromhex("1800"), tag_9f36=atc, tag_9f10=bytes.fromhex("1501850440B100000000B00000000000000000000000"), ) assert arqc.hex().upper() == "18932FECA2D84326" assert (key_check_digits(cvn133._derive_sk_ac_mastercard( atc, un)).hex().upper() == "2FD5") # ARPC and its session key arpc = cvn133.generate_arpc(tag_9f26=arqc, tag_9f37=un, tag_9f36=atc, arpc_rc=bytes.fromhex("0000")) assert arpc.hex().upper() == "4DF171A49396C363" assert (key_check_digits(cvn133._derive_sk_ac_mastercard( atc, un)).hex().upper() == "2FD5") # MAC PIN unblock command and its session key mac = cvn133.generate_command_mac(bytes.fromhex("8424000008"), tag_9f26=arqc) assert mac.hex().upper() == "B574ABB0A485A330" assert (key_check_digits( cvn133._derive_sk_sm_common(cvn133.icc_mk_smi, arqc)).hex().upper() == "08DF") # PIN change without current PIN and its session keys pin_command = cvn133.generate_pin_change_command(b"9999", tag_9f26=arqc) assert pin_command.hex().upper( ) == "8424000210382F36D5920D23915CC7573F770298C9" assert (key_check_digits( cvn133._derive_sk_sm_common(cvn133.icc_mk_smc, arqc)).hex().upper() == "748D") assert (key_check_digits( cvn133._derive_sk_sm_common(cvn133.icc_mk_smi, arqc)).hex().upper() == "08DF")