コード例 #1
0
def test_mac_iso9797_3() -> None:
    # SK < 16 bytes
    with pytest.raises(
        ValueError,
        match="pecify valid padding method: 1, 2 or 3.",
    ):
        mac.mac_iso9797_3(
            bytes.fromhex("AAAAAAAAAAAAAAAA"),
            bytes.fromhex("BBBBBBBBBBBBBBBB"),
            b"hello world",
            4,
        )

    _mac = (
        mac.mac_iso9797_3(
            bytes.fromhex("AAAAAAAAAAAAAAAA"),
            bytes.fromhex("BBBBBBBBBBBBBBBB"),
            b"hello world",
            1,
        )
        .hex()
        .upper()
    )
    assert _mac == "78DA3D3DEB48FD4D"

    _mac = (
        mac.mac_iso9797_3(
            bytes.fromhex("AAAAAAAAAAAAAAAA"),
            bytes.fromhex("BBBBBBBBBBBBBBBB"),
            b"hello world",
            2,
        )
        .hex()
        .upper()
    )
    assert _mac == "2BC2D9EDE0CF31F6"

    _mac = (
        mac.mac_iso9797_3(
            bytes.fromhex("AAAAAAAAAAAAAAAA"),
            bytes.fromhex("BBBBBBBBBBBBBBBB"),
            b"hello world",
            3,
        )
        .hex()
        .upper()
    )
    assert _mac == "1789FED38FC05D1B"
コード例 #2
0
ファイル: cvv.py プロジェクト: husrep/pyemv
def generate_cvc3(icc_cvc3: bytes, track_template: bytes, atc: bytes,
                  un: bytes) -> str:
    r"""Generate MasterCard Dynamic Card Verification Code (CVC3).

    Parameters
    ----------
    icc_cvc3 : bytes
        Binary 16-byte ICC CVC3 key encoded on the card.
        This key is derived from Issuer Master CVC3 key using
        either `kd.derive_icc_mk_a` or `kd.derive_icc_mk_b`.
        Has to be a valid Triple DES key.
    track_template : bytes
        Binary track template data.
        Track2 template consists of:

            PAN || "D" || EXPIRY DATE || SERVICE CODE || DD || "F"?

        DD is Discretionary Data up to 13 digits. DD must have
        value before it's encoded with ATC, UN and CVC3.
        If the resulting track2 template is odd length then it must
        be padded with an "F".

        Track1 template consists of:

            "B" || PAN || ^LAST/FIRST^ || EXPIRY DATE || SERVICE CODE || DD

        Track1 template must be encoded as an ASCII byte string, where, for example,
        character "B" is encoded as "\x42".

    atc : bytes
        Binary data from tag 9F36 (Application Transaction Counter).
    un : bytes
        Binary data from tag 9F37 (Unpredictable Number).

    Returns
    -------
    cvc3 : str
        5-digit Dynamic Card Verification Code.
        Compare generated CVC3 against number of available
        least significant digits of CVC3 received on track1/2.

    Raises
    ------
    ValueError
        ICC CVC3 key must be a double length DES key
        ATC value must be 2 bytes long
        Unpredictable number must be 4 bytes long

    Examples
    --------
    >>> from pyemv.cvv import generate_cvc3
    >>> from pyemv.kd import derive_icc_mk_a
    >>> iss_cvc3 = bytes.fromhex("01234567899876543210012345678998")
    >>> pan = "5123456789012345"
    >>> psn = "00"
    >>> icc_cvc3 = derive_icc_mk_a(iss_cvc3, pan, psn)
    >>> track2 = bytes.fromhex("5123456789012345D35121010000000000000F")
    >>> atc = bytes.fromhex("005E")
    >>> un = bytes.fromhex("00000899")
    >>> generate_cvc3(icc_cvc3, track2, atc, un)
    '29488'
    """
    if len(icc_cvc3) != 16:
        raise ValueError("ICC CVC3 key must be a double length DES key")

    if len(atc) != 2:
        raise ValueError("ATC value must be 2 bytes long")

    if len(un) != 4:
        raise ValueError("Unpredictable number must be 4 bytes long")

    # IV CVC3 is formed from 2 least significant bytes of CBC-MAC
    # computed over track template
    iv_cvc3 = _mac.mac_iso9797_3(icc_cvc3[:8], icc_cvc3[-8:], track_template,
                                 2)[-2:]

    # CVC3 is formed from 2 least significant bytes of TDES encrypted
    # ciphertext block
    block = iv_cvc3 + un + atc
    cvc3 = _tools.encrypt_tdes_ecb(icc_cvc3, block)[-2:]

    return str(int(cvc3.hex(), 16))
コード例 #3
0
ファイル: sm.py プロジェクト: husrep/pyemv
def generate_command_mac(
    sk_smi: bytes, command: bytes, length: Optional[int] = None
) -> bytes:
    r"""Message Authentication Code (MAC) for Issuer Script Integrity

    Parameters
    ----------
    sk_smi : bytes
        Binary ICC Session Key for script integrity (MAC).
    command : bytes
        Binary command to be MACed; may or may not include command data, e.g:

            Command Header || { Command Data if present }

        Some issuers choose to append transaction data, such as ATC and ARQC,
        to the command between header and data. The transaction data is present
        for the MAC calculation but not transmitted.

            Command Header || ATC || ARQC || { Command Data if present }

    length : int, optional
        Desired length of AC [4 <= `length` <= 8] (default 8 bytes).

    Returns
    -------
    mac : bytes
        Binary command MAC.

    Raises
    ------
    ValueError
        Session Key must be a double length DES key

    Notes
    -----
    During a transaction the host may send an Issuer Script. These
    Issuer Scripts allow the issuer to block or unblock an application,
    or unblock or change PIN on the card among other things. These issuer
    scripts are extracted from the host response and sent to the card as
    individual commands. These commands contain a MAC value that the card
    authenticates prior to actioning the script. The MAC can be 4-8 bytes
    in length.

    For further details see also:
        - EMV 4.3 Book 2 Section 9.2 Secure Messaging for Integrity and
          Authentication
        - EMV 4.3 Book 2 Section 9.2.1.2 Format 2
        - EMV 4.3 Book 2 Section 9.2.3 MAC Computation
        - EMV 4.3 Book 2 Annex A 1.2

    Examples
    --------
    >>> from pyemv import sm
    >>> sk_smi = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210")
    >>> command = bytes.fromhex("8424000008")
    >>> atc = bytes.fromhex("FFFF")
    >>> arqc = bytes.fromhex("1234567890123456")
    >>> mac = sm.generate_command_mac(sk_smi, command + atc + arqc)
    >>> mac.hex().upper()
    'E07B8DF1B4184282'
    """
    if len(sk_smi) != 16:
        raise ValueError("Session Key must be a double length DES key")

    return _mac.mac_iso9797_3(sk_smi[:8], sk_smi[-8:], command, 2, length)