예제 #1
0
def _create_ocb_cipher(factory, **kwargs):
    """Create a new block cipher, configured in OCB mode.

    :Parameters:
      factory : module
        A symmetric cipher module from `crypto.Cipher`
        (like `crypto.Cipher.AES`).

    :Keywords:
      nonce : bytes/bytearray/memoryview
        A  value that must never be reused for any other encryption.
        Its length can vary from 1 to 15 bytes.
        If not specified, a random 15 bytes long nonce is generated.

      mac_len : integer
        Length of the MAC, in bytes.
        It must be in the range ``[8..16]``.
        The default is 16 (128 bits).

    Any other keyword will be passed to the underlying block cipher.
    See the relevant documentation for details (at least ``key`` will need
    to be present).
    """

    try:
        nonce = kwargs.pop("nonce", None)
        if nonce is None:
            nonce = get_random_bytes(15)
        mac_len = kwargs.pop("mac_len", 16)
    except KeyError as e:
        raise TypeError("Keyword missing: " + str(e))

    return OcbMode(factory, nonce, mac_len, kwargs)
    def verify(self, received_mac_tag):
        """Validate the *binary* MAC tag.

        The caller invokes this function at the very end.

        This method checks if the decrypted message is indeed valid
        (that is, if the key is correct) and it has not been
        tampered with while in transit.

        :Parameters:
          received_mac_tag : bytes/bytearray/memoryview
            This is the *binary* MAC, as received from the sender.
        :Raises ValueError:
            if the MAC does not match. The message has been tampered with
            or the key is incorrect.
        """

        if self.verify not in self._next:
            raise TypeError("verify() cannot be called"
                            " when encrypting a message")
        self._next = [self.verify]

        self._digest()
        secret = get_random_bytes(16)

        mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
        mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)

        if mac1.digest() != mac2.digest():
            raise ValueError("MAC check failed")
예제 #3
0
def new(**kwargs):
    """Create a new ChaCha20 cipher

    :keyword key: The secret key to use. It must be 32 bytes long.
    :type key: byte string

    :keyword nonce:
        A mandatory value that must never be reused for any other encryption
        done with this key. It must be 8 or 12 bytes long.

        If not provided, a random 8-byte string will be generated
        (you can read it back via the ``nonce`` attribute of the returned object).
    :type nonce: bytes, bytearray, memoryview

    :Return: a :class:`Crypto.Cipher.ChaCha20.ChaCha20Cipher` object
    """

    try:
        key = kwargs.pop("key")
    except KeyError as e:
        raise TypeError("Missing parameter %s" % e)

    nonce = kwargs.pop("nonce", None)
    if nonce is None:
        nonce = get_random_bytes(8)

    if len(key) != 32:
        raise ValueError("ChaCha20 key must be 32 bytes long")
    if len(nonce) not in (8, 12):
        raise ValueError("ChaCha20 nonce must be 8 or 12 bytes long")

    if kwargs:
        raise TypeError("Unknown parameters: " + str(kwargs))

    return ChaCha20Cipher(key, nonce)
예제 #4
0
    def verify(self, received_mac_tag):
        """Validate the *binary* MAC tag.

        Call this method after the final `decrypt` (the one with no arguments)
        to check if the message is authentic and valid.

        :Parameters:
          received_mac_tag : bytes/bytearray/memoryview
            This is the *binary* MAC, as received from the sender.
        :Raises ValueError:
            if the MAC does not match. The message has been tampered with
            or the key is incorrect.
        """

        if self.verify not in self._next:
            raise TypeError("verify() cannot be called now for this cipher")

        assert (len(self._cache_P) == 0)

        self._next = [self.verify]

        if self._mac_tag is None:
            self._compute_mac_tag()

        secret = get_random_bytes(16)
        mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
        mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)

        if mac1.digest() != mac2.digest():
            raise ValueError("MAC check failed")
def _create_ccm_cipher(factory, **kwargs):
    """Create a new block cipher, configured in CCM mode.

    :Parameters:
      factory : module
        A symmetric cipher module from `Crypto.Cipher` (like
        `Crypto.Cipher.AES`).

    :Keywords:
      key : bytes/bytearray/memoryview
        The secret key to use in the symmetric cipher.

      nonce : bytes/bytearray/memoryview
        A value that must never be reused for any other encryption.

        Its length must be in the range ``[7..13]``.
        11 or 12 bytes are reasonable values in general. Bear in
        mind that with CCM there is a trade-off between nonce length and
        maximum message size.

        If not specified, a 11 byte long random string is used.

      mac_len : integer
        Length of the MAC, in bytes. It must be even and in
        the range ``[4..16]``. The default is 16.

      msg_len : integer
        Length of the message to (de)cipher.
        If not specified, ``encrypt`` or ``decrypt`` may only be called once.

      assoc_len : integer
        Length of the associated data.
        If not specified, all data is internally buffered.
    """

    try:
        key = key = kwargs.pop("key")
    except KeyError as e:
        raise TypeError("Missing parameter: " + str(e))

    nonce = kwargs.pop("nonce", None)  # N
    if nonce is None:
        nonce = get_random_bytes(11)
    mac_len = kwargs.pop("mac_len", factory.block_size)
    msg_len = kwargs.pop("msg_len", None)  # p
    assoc_len = kwargs.pop("assoc_len", None)  # a
    cipher_params = dict(kwargs)

    return CcmMode(factory, key, nonce, mac_len, msg_len, assoc_len,
                   cipher_params)
예제 #6
0
def _create_gcm_cipher(factory, **kwargs):
    """Create a new block cipher, configured in Galois Counter Mode (GCM).

    :Parameters:
      factory : module
        A block cipher module, taken from `crypto.Cipher`.
        The cipher must have block length of 16 bytes.
        GCM has been only defined for `crypto.Cipher.AES`.

    :Keywords:
      key : bytes/bytearray/memoryview
        The secret key to use in the symmetric cipher.
        It must be 16 (e.g. *AES-128*), 24 (e.g. *AES-192*)
        or 32 (e.g. *AES-256*) bytes long.

      nonce : bytes/bytearray/memoryview
        A value that must never be reused for any other encryption.

        There are no restrictions on its length,
        but it is recommended to use at least 16 bytes.

        The nonce shall never repeat for two
        different messages encrypted with the same key,
        but it does not need to be random.

        If not provided, a 16 byte nonce will be randomly created.

      mac_len : integer
        Length of the MAC, in bytes.
        It must be no larger than 16 bytes (which is the default).
    """

    try:
        key = kwargs.pop("key")
    except KeyError as e:
        raise TypeError("Missing parameter:" + str(e))

    nonce = kwargs.pop("nonce", None)
    if nonce is None:
        nonce = get_random_bytes(16)
    mac_len = kwargs.pop("mac_len", 16)

    # Not documented - only used for testing
    use_clmul = kwargs.pop("use_clmul", True)
    if use_clmul and _ghash_clmul:
        ghash_c = _ghash_clmul
    else:
        ghash_c = _ghash_portable

    return GcmMode(factory, key, nonce, mac_len, kwargs, ghash_c)
예제 #7
0
def _create_cfb_cipher(factory, **kwargs):
    """Instantiate a cipher object that performs CFB encryption/decryption.

    :Parameters:
      factory : module
        The underlying block cipher, a module from ``Crypto.Cipher``.

    :Keywords:
      iv : bytes/bytearray/memoryview
        The IV to use for CFB.

      IV : bytes/bytearray/memoryview
        Alias for ``iv``.

      segment_size : integer
        The number of bit the plaintext and ciphertext are segmented in.
        If not present, the default is 8.

    Any other keyword will be passed to the underlying block cipher.
    See the relevant documentation for details (at least ``key`` will need
    to be present).
    """

    cipher_state = factory._create_base_cipher(kwargs)

    iv = kwargs.pop("IV", None)
    IV = kwargs.pop("iv", None)

    if (None, None) == (iv, IV):
        iv = get_random_bytes(factory.block_size)
    if iv is not None:
        if IV is not None:
            raise TypeError("You must either use 'iv' or 'IV', not both")
    else:
        iv = IV

    if len(iv) != factory.block_size:
        raise ValueError("Incorrect IV length (it must be %d bytes long)" %
                         factory.block_size)

    segment_size_bytes, rem = divmod(kwargs.pop("segment_size", 8), 8)
    if segment_size_bytes == 0 or rem != 0:
        raise ValueError(
            "'segment_size' must be positive and multiple of 8 bits")

    if kwargs:
        raise TypeError("Unknown parameters for CFB: %s" % str(kwargs))
    return CfbMode(cipher_state, iv, segment_size_bytes)
예제 #8
0
def _derive_Poly1305_key_pair(key, nonce):
    """Derive a tuple (r, s, nonce) for a Poly1305 MAC.
    
    If nonce is ``None``, a new 16-byte nonce is generated.
    """

    if len(key) != 32:
        raise ValueError("Poly1305 with AES requires a 32-byte key")

    if nonce is None:
        nonce = get_random_bytes(16)
    elif len(nonce) != 16:
        raise ValueError("Poly1305 with AES requires a 16-byte nonce")

    s = new(key[:16], MODE_ECB).encrypt(nonce)
    return key[16:], s, nonce
예제 #9
0
    def encrypt_message(self, plaintext, public_key):
        if not public_key.startswith("-----BEGIN RSA PUBLIC KEY-----"):
            public_key = "-----BEGIN RSA PUBLIC KEY-----\n" + public_key + "\n-----END RSA PUBLIC KEY-----"
        recipient_key = RSA.importKey(public_key)
        session_key = get_random_bytes(16)

        # Encrypt the session key with the public RSA key
        cipher_rsa = PKCS1_OAEP.new(recipient_key)
        enc_session_key = cipher_rsa.encrypt(session_key)

        # Encrypt the data with the AES session key
        cipher_aes = AES.new(session_key, AES.MODE_EAX)
        ciphertext, tag = cipher_aes.encrypt_and_digest(
            plaintext.encode("UTF-8"))
        encrypted_message = b"".join(
            [x for x in (enc_session_key, cipher_aes.nonce, tag, ciphertext)])
        return encrypted_message
예제 #10
0
    def verify(self, mac_tag):
        """Verify that a given **binary** MAC (computed by another party)
        is valid.

        Args:
          mac_tag (byte string/array): the expected MAC of the message.

        Raises:
            ValueError: if the MAC does not match. It means that the message
                has been tampered with or that the MAC key is incorrect.
        """

        secret = get_random_bytes(16)

        mac1 = new(digest_bits=160, key=secret, data=mac_tag)
        mac2 = new(digest_bits=160, key=secret, data=self.digest())

        if mac1.digest() != mac2.digest():
            raise ValueError("MAC check failed")
예제 #11
0
def new(key, nonce=None):
    """Create a new Salsa20 cipher

    :keyword key: The secret key to use. It must be 16 or 32 bytes long.
    :type key: bytes/bytearray/memoryview

    :keyword nonce:
        A value that must never be reused for any other encryption
        done with this key. It must be 8 bytes long.

        If not provided, a random byte string will be generated (you can read
        it back via the ``nonce`` attribute of the returned object).
    :type nonce: bytes/bytearray/memoryview

    :Return: a :class:`Crypto.Cipher.Salsa20.Salsa20Cipher` object
    """

    if nonce is None:
        nonce = get_random_bytes(8)

    return Salsa20Cipher(key, nonce)
예제 #12
0
def _create_ofb_cipher(factory, **kwargs):
    """Instantiate a cipher object that performs OFB encryption/decryption.

    :Parameters:
      factory : module
        The underlying block cipher, a module from ``crypto.Cipher``.

    :Keywords:
      iv : bytes/bytearray/memoryview
        The IV to use for OFB.

      IV : bytes/bytearray/memoryview
        Alias for ``iv``.

    Any other keyword will be passed to the underlying block cipher.
    See the relevant documentation for details (at least ``key`` will need
    to be present).
    """

    cipher_state = factory._create_base_cipher(kwargs)
    iv = kwargs.pop("IV", None)
    IV = kwargs.pop("iv", None)

    if (None, None) == (iv, IV):
        iv = get_random_bytes(factory.block_size)
    if iv is not None:
        if IV is not None:
            raise TypeError("You must either use 'iv' or 'IV', not both")
    else:
        iv = IV

    if len(iv) != factory.block_size:
        raise ValueError("Incorrect IV length (it must be %d bytes long)" %
                         factory.block_size)

    if kwargs:
        raise TypeError("Unknown parameters for OFB: %s" % str(kwargs))

    return OfbMode(cipher_state, iv)
def _create_openpgp_cipher(factory, **kwargs):
    """Create a new block cipher, configured in OpenPGP mode.

    :Parameters:
      factory : module
        The module.

    :Keywords:
      key : bytes/bytearray/memoryview
        The secret key to use in the symmetric cipher.

      IV : bytes/bytearray/memoryview
        The initialization vector to use for encryption or decryption.

        For encryption, the IV must be as long as the cipher block size.

        For decryption, it must be 2 bytes longer (it is actually the
        *encrypted* IV which was prefixed to the ciphertext).
    """

    iv = kwargs.pop("IV", None)
    IV = kwargs.pop("iv", None)

    if (None, None) == (iv, IV):
        iv = get_random_bytes(factory.block_size)
    if iv is not None:
        if IV is not None:
            raise TypeError("You must either use 'iv' or 'IV', not both")
    else:
        iv = IV

    try:
        key = kwargs.pop("key")
    except KeyError as e:
        raise TypeError("Missing component: " + str(e))

    return OpenPgpMode(factory, key, iv, kwargs)
예제 #14
0
def _create_eax_cipher(factory, **kwargs):
    """Create a new block cipher, configured in EAX mode.

    :Parameters:
      factory : module
        A symmetric cipher module from `crypto.Cipher` (like
        `crypto.Cipher.AES`).

    :Keywords:
      key : bytes/bytearray/memoryview
        The secret key to use in the symmetric cipher.

      nonce : bytes/bytearray/memoryview
        A value that must never be reused for any other encryption.
        There are no restrictions on its length, but it is recommended to use
        at least 16 bytes.

        The nonce shall never repeat for two different messages encrypted with
        the same key, but it does not need to be random.

        If not specified, a 16 byte long random string is used.

      mac_len : integer
        Length of the MAC, in bytes. It must be no larger than the cipher
        block bytes (which is the default).
    """

    try:
        key = kwargs.pop("key")
        nonce = kwargs.pop("nonce", None)
        if nonce is None:
            nonce = get_random_bytes(16)
        mac_len = kwargs.pop("mac_len", factory.block_size)
    except KeyError as e:
        raise TypeError("Missing parameter: " + str(e))

    return EaxMode(factory, key, nonce, mac_len, kwargs)
def _create_ctr_cipher(factory, **kwargs):
    """Instantiate a cipher object that performs CTR encryption/decryption.

    :Parameters:
      factory : module
        The underlying block cipher, a module from ``Crypto.Cipher``.

    :Keywords:
      nonce : bytes/bytearray/memoryview
        The fixed part at the beginning of the counter block - the rest is
        the counter number that gets increased when processing the next block.
        The nonce must be such that no two messages are encrypted under the
        same key and the same nonce.

        The nonce must be shorter than the block size (it can have
        zero length; the counter is then as long as the block).

        If this parameter is not present, a random nonce will be created with
        length equal to half the block size. No random nonce shorter than
        64 bits will be created though - you must really think through all
        security consequences of using such a short block size.

      initial_value : posive integer or bytes/bytearray/memoryview
        The initial value for the counter. If not present, the cipher will
        start counting from 0. The value is incremented by one for each block.
        The counter number is encoded in big endian mode.

      counter : object
        Instance of ``Crypto.Util.Counter``, which allows full customization
        of the counter block. This parameter is incompatible to both ``nonce``
        and ``initial_value``.

    Any other keyword will be passed to the underlying block cipher.
    See the relevant documentation for details (at least ``key`` will need
    to be present).
    """

    cipher_state = factory._create_base_cipher(kwargs)

    counter = kwargs.pop("counter", None)
    nonce = kwargs.pop("nonce", None)
    initial_value = kwargs.pop("initial_value", None)
    if kwargs:
        raise TypeError("Invalid parameters for CTR mode: %s" % str(kwargs))

    if counter is not None and (nonce, initial_value) != (None, None):
        raise TypeError("'counter' and 'nonce'/'initial_value'"
                        " are mutually exclusive")

    if counter is None:
        # Crypto.Util.Counter is not used
        if nonce is None:
            if factory.block_size < 16:
                raise TypeError("Impossible to create a safe nonce for short"
                                " block sizes")
            nonce = get_random_bytes(factory.block_size // 2)
        else:
            if len(nonce) >= factory.block_size:
                raise ValueError("Nonce is too long")

        # What is not nonce is counter
        counter_len = factory.block_size - len(nonce)

        if initial_value is None:
            initial_value = 0

        if isinstance(initial_value, int):
            if (1 << (counter_len * 8)) - 1 < initial_value:
                raise ValueError("Initial counter value is too large")
            initial_counter_block = nonce + long_to_bytes(
                initial_value, counter_len)
        else:
            if len(initial_value) != counter_len:
                raise ValueError(
                    "Incorrect length for counter byte string (%d bytes, expected %d)"
                    % (len(initial_value), counter_len))
            initial_counter_block = nonce + initial_value

        return CtrMode(
            cipher_state,
            initial_counter_block,
            len(nonce),  # prefix
            counter_len,
            False)  # little_endian

    # Crypto.Util.Counter is used

    # 'counter' used to be a callable object, but now it is
    # just a dictionary for backward compatibility.
    _counter = dict(counter)
    try:
        counter_len = _counter.pop("counter_len")
        prefix = _counter.pop("prefix")
        suffix = _counter.pop("suffix")
        initial_value = _counter.pop("initial_value")
        little_endian = _counter.pop("little_endian")
    except KeyError:
        raise TypeError("Incorrect counter object"
                        " (use Crypto.Util.Counter.new)")

    # Compute initial counter block
    words = []
    while initial_value > 0:
        words.append(struct.pack('B', initial_value & 255))
        initial_value >>= 8
    words += [b'\x00'] * max(0, counter_len - len(words))
    if not little_endian:
        words.reverse()
    initial_counter_block = prefix + b"".join(words) + suffix

    if len(initial_counter_block) != factory.block_size:
        raise ValueError("Size of the counter block (%d bytes) must match"
                         " block size (%d)" %
                         (len(initial_counter_block), factory.block_size))

    return CtrMode(cipher_state, initial_counter_block, len(prefix),
                   counter_len, little_endian)