Ejemplo n.º 1
0
def key_check_digits(key: bytes, length: int = 2) -> bytes:
    r"""Calculate Triple DES key check digits.

    Parameters
    ----------
    key : bytes
        Binary key to provide check digits for. Has to be a valid DES key.
    length : int, optional
        Number of key check digits bytes provided in the response (default 2).

    Returns
    -------
    check_digits : bytes
        Binary check digits (`length` bytes)

    Examples
    --------
    >>> from pyemv import tools
    >>> key = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210")
    >>> tools.key_check_digits(key).hex().upper()
    '08D7'
    """
    cipher = _Cipher(_algorithms.TripleDES(key),
                     _modes.ECB(),
                     backend=_default_backend())
    encryptor = cipher.encryptor()
    return encryptor.update(b"\x00\x00\x00\x00\x00\x00\x00\x00")[:length]
Ejemplo n.º 2
0
def encrypt_tdes_cbc(key: bytes, iv: bytes, data: bytes) -> bytes:
    r"""Encrypt data using Triple DES CBC algorithm.

    Parameters
    ----------
    key : bytes
        Binary Triple DES key. Has to be a valid DES key.
    iv : bytes
        Binary initial initialization vector for CBC.
    data : bytes
        Binary data to be encrypted.

    Returns
    -------
    encrypted_data : bytes
        Binary encrypted data.

    Examples
    --------
    >>> from pyemv.tools import encrypt_tdes_cbc
    >>> key = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210")
    >>> iv = bytes.fromhex("0000000000000000")
    >>> encrypt_tdes_cbc(key, iv, b"12345678").hex().upper()
    '41D2FFBA3CDC15FE'
    """
    cipher = _Cipher(
        _algorithms.TripleDES(key),
        _modes.CBC(iv),
        backend=_default_backend(),
    )
    return cipher.encryptor().update(data)
Ejemplo n.º 3
0
def encrypt_tdes_ecb(key: bytes, data: bytes) -> bytes:
    r"""Encrypt data using Triple DES ECB algorithm.

    Parameters
    ----------
    key : bytes
        Binary Triple DES key. Has to be a valid DES key.
    data : bytes
        Binary data to be encrypted.

    Returns
    -------
    encrypted_data : bytes
        Binary encrypted data.

    Examples
    --------
    >>> from pyemv.tools import encrypt_tdes_ecb
    >>> key = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210")
    >>> encrypt_tdes_ecb(key, b"12345678").hex().upper()
    '41D2FFBA3CDC15FE'
    """
    cipher = _Cipher(_algorithms.TripleDES(key),
                     _modes.ECB(),
                     backend=_default_backend())
    return cipher.encryptor().update(data)
Ejemplo n.º 4
0
def generate_kcv(key: bytes, length: int = 2) -> bytes:
    r"""Generate DES key checksum value (KCV).

    Parameters
    ----------
    key : bytes
        Binary key to provide check digits for. Has to be a valid DES key.
    length : int, optional
        Number of KCV bytes returned (default 2).

    Returns
    -------
    kcv : bytes
        Binary KCV (`length` bytes)

    Examples
    --------
    >>> import psec
    >>> key = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210")
    >>> psec.des.generate_kcv(key).hex().upper()
    '08D7'
    """
    cipher = _Cipher(_algorithms.TripleDES(key),
                     _modes.ECB(),
                     backend=_default_backend())
    encryptor = cipher.encryptor()
    return encryptor.update(b"\x00\x00\x00\x00\x00\x00\x00\x00")[:length]
Ejemplo n.º 5
0
 def _aes256cbc_encrypt(key, iv, plaintext):
     algo = _AES(key)
     mode = _CBC(iv)
     backend = _default_backend()
     cipher = _Cipher(algo, mode, backend)
     encryptor = cipher.encryptor()
     ciphertext = encryptor.update(plaintext)
     ciphertext += encryptor.finalize()
     return ciphertext
Ejemplo n.º 6
0
 def encrypt(self, key, iv, data):
     if len(key) != self.key_size:
         raise EncrError('Key must be of the indicated size {}'.format(
             self.key_size))
     _cipher = _Cipher(self._algorithm(key),
                       modes.CBC(iv),
                       backend=self._backend)
     encryptor = _cipher.encryptor()
     return encryptor.update(data) + encryptor.finalize()
Ejemplo n.º 7
0
def decrypt_tdes_cbc(key: bytes, iv: bytes, data: bytes) -> bytes:
    r"""Decrypt data using Triple DES CBC algorithm.

    Parameters
    ----------
    key : bytes
        Binary Triple DES key. Has to be a valid DES key.
    iv : bytes
        Binary initial initialization vector for CBC.
        Has to be 8 bytes long.
    data : bytes
        Binary data to be decrypted.
        Has to be multiple of 8 bytes.

    Returns
    -------
    decrypted_data : bytes
        Binary decrypted data.

    Raises
    ------
    ValueError
        Data length must be multiple of DES block size 8.

    Examples
    --------
    >>> import psec
    >>> key = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210")
    >>> iv = bytes.fromhex("0000000000000000")
    >>> psec.des.decrypt_tdes_cbc(key, iv, bytes.fromhex("41D2FFBA3CDC15FE"))
    b'12345678'
    """
    if len(data) < 8 or len(data) % 8 != 0:
        raise ValueError(
            f"Data length ({str(len(data))}) must be multiple of DES block size 8."
        )

    cipher = _Cipher(
        _algorithms.TripleDES(key),
        _modes.CBC(iv),
        backend=_default_backend(),
    )
    return cipher.decryptor().update(data)
Ejemplo n.º 8
0
def encrypt_tdes_ecb(key: bytes, data: bytes) -> bytes:
    r"""Encrypt data using Triple DES ECB algorithm.

    Parameters
    ----------
    key : bytes
        Binary Triple DES key. Has to be a valid DES key.
    data : bytes
        Binary data to be encrypted.
        Has to be multiple of 8 bytes.

    Returns
    -------
    encrypted_data : bytes
        Binary encrypted data.

    Raises
    ------
    ValueError
        Data length must be multiple of DES block size 8.

    Examples
    --------
    >>> import psec
    >>> key = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210")
    >>> psec.des.encrypt_tdes_ecb(key, b"12345678").hex().upper()
    '41D2FFBA3CDC15FE'
    """
    if len(data) < 8 or len(data) % 8 != 0:
        raise ValueError(
            f"Data length ({str(len(data))}) must be multiple of DES block size 8."
        )

    cipher = _Cipher(_algorithms.TripleDES(key),
                     _modes.ECB(),
                     backend=_default_backend())
    return cipher.encryptor().update(data)
Ejemplo n.º 9
0
def mac_iso9797_3(key1: bytes,
                  key2: bytes,
                  data: bytes,
                  padding: int,
                  length: Optional[int] = None) -> bytes:
    r"""ISO/IEC 9797-1 MAC algorithm 3. Requires two independent keys.
    Only the last data block is processed using TDES,
    all previous blocks are processed using single DES.

    Parameters
    ----------
    key1 : bytes
        Binary MAC key used in initial transformation.
        Has to be a valid DES key.
    key2 : bytes
        Binary MAC key used  in output transformation.
        Has to be a valid DES key.
    data : bytes
        Data to be MAC'd.
    padding : int
        Padding method of `data`.

            - 1 = ISO/IEC 9797-1 method 1.
            - 2 = ISO/IEC 9797-1 method 2.
            - 3 = ISO/IEC 9797-1 method 3.

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

    Returns
    -------
    mac : bytes
        Returns a binary MAC of requested length

    Raises
    ------
    ValueError
        Invalid padding method specified

    Notes
    -----
    See https://en.wikipedia.org/wiki/ISO/IEC_9797-1 for the
    algorithm reference.

    See Also
    --------
    pyemv.mac.pad_iso9797_1 : ISO/IEC 9791-1 padding method 1
    pyemv.mac.pad_iso9797_2 : ISO/IEC 9791-1 padding method 2
    pyemv.mac.pad_iso9797_3 : ISO/IEC 9791-1 padding method 3

    Examples
    --------
    >>> from pyemv.mac import mac_iso9797_3
    >>> key1 = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210")
    >>> key2 = bytes.fromhex("FEDCBA98765432100123456789ABCDEF")
    >>> data = bytes.fromhex("1234567890ABCDEF")
    >>> mac_iso9797_3(key1, key2, data, padding=2).hex().upper()
    '644AA5C915DBDAF8'
    """
    if length is None:
        length = 8

    if padding == 1:
        data = pad_iso9797_1(data, 8)
    elif padding == 2:
        data = pad_iso9797_2(data, 8)
    elif padding == 3:
        data = pad_iso9797_3(data, 8)
    else:
        raise ValueError("Specify valid padding method: 1, 2 or 3.")

    # Encrypt first block with key1 then
    # encrypt the rest of the data in CBC mode
    cipher1 = _Cipher(
        _algorithms.TripleDES(key1),
        _modes.CBC(b"\x00\x00\x00\x00\x00\x00\x00\x00"),
        backend=_default_backend(),
    )
    encryptor1 = cipher1.encryptor()
    data = encryptor1.update(data)[-8:]

    # Decrypt the last block with key2 and then encrypt it with key1
    cipher2 = _Cipher(_algorithms.TripleDES(key2),
                      _modes.CBC(data),
                      backend=_default_backend())
    decryptor2 = cipher2.decryptor()
    return encryptor1.update(decryptor2.update(data))[:length]
Ejemplo n.º 10
0
def generate_retail_mac(
    key1: bytes,
    key2: bytes,
    data: bytes,
    padding: int,
    length: _typing.Optional[int] = None,
) -> bytes:
    r"""ISO/IEC 9797-1 MAC algorithm 3 aka retail MAC.
    Requires two independent keys.
    All blocks until the last are processed using single DES using key1.
    The last data block is processed using TDES using key2 and key1.
    The resulting block is the MAC.

    Parameters
    ----------
    key1 : bytes
        Binary MAC key used in initial transformation.
        Has to be a valid DES key.
    key2 : bytes
        Binary MAC key used  in output transformation.
        Has to be a valid DES key.
    data : bytes
        Data to be MAC'd.
    padding : int
        Padding method of `data`.

            - 1 = ISO/IEC 9797-1 method 1.
            - 2 = ISO/IEC 9797-1 method 2.
            - 3 = ISO/IEC 9797-1 method 3.

    length : int, optional
        Desired MAC length [4 <= N <= 8] (default 8 bytes).

    Returns
    -------
    mac : bytes
        Returns a binary MAC of requested length

    Raises
    ------
    ValueError
        Invalid padding method specified

    Notes
    -----
    See https://en.wikipedia.org/wiki/ISO/IEC_9797-1 for the
    algorithm reference.

    See Also
    --------
    psec.mac.pad_iso_1 : ISO/IEC 9791-1 padding method 1
    psec.mac.pad_iso_2 : ISO/IEC 9791-1 padding method 2
    psec.mac.pad_iso_3 : ISO/IEC 9791-1 padding method 3

    Examples
    --------
    >>> import psec
    >>> key1 = bytes.fromhex("0123456789ABCDEFFEDCBA9876543210")
    >>> key2 = bytes.fromhex("FEDCBA98765432100123456789ABCDEF")
    >>> data = bytes.fromhex("1234567890ABCDEF")
    >>> psec.mac.generate_retail_mac(key1, key2, data, padding=2).hex().upper()
    '644AA5C915DBDAF8'
    """
    if length is None:
        length = 8

    try:
        data = _pad_dispatch[padding](data, 8)
    except KeyError:
        raise ValueError("Specify valid padding method: 1, 2 or 3.")

    # Encrypt first block with key1 then
    # encrypt the rest of the data in CBC mode
    cipher1 = _Cipher(
        _algorithms.TripleDES(key1),
        _modes.CBC(b"\x00\x00\x00\x00\x00\x00\x00\x00"),
        backend=_default_backend(),
    )
    encryptor1 = cipher1.encryptor()
    data = encryptor1.update(data)[-8:]

    # Decrypt the last block with key2 and then encrypt it with key1
    cipher2 = _Cipher(
        _algorithms.TripleDES(key2), _modes.CBC(data), backend=_default_backend()
    )
    decryptor2 = cipher2.decryptor()
    return encryptor1.update(decryptor2.update(data))[:length]