def decrypt(self, key, data, mode, padding):
        # this can be disabled by _disable_encryption, so pylint: disable=method-hidden
        """Decrypt data using the supplied values.

        :param bytes key: Loaded decryption key
        :param bytes data: IV prepended to encrypted data
        :param JavaMode mode: Decryption mode to use
        :param JavaPadding padding: Padding mode to use
        :returns: Decrypted data
        :rtype: bytes
        """
        try:
            block_size = self.cipher.block_size
            iv_len = block_size // 8
            iv = data[:iv_len]
            data = data[iv_len:]

            decryptor = Cipher(self.cipher(key),
                               mode.build(iv),
                               backend=default_backend()).decryptor()
            decrypted_data = decryptor.update(data) + decryptor.finalize()

            unpadder = padding.build(block_size).unpadder()
            return unpadder.update(decrypted_data) + unpadder.finalize()
        except Exception:
            error_message = "Decryption failed"
            _LOGGER.exception(error_message)
            raise DecryptionError(error_message)
Beispiel #2
0
    def decrypt(self, key, data, mode, padding):
        # pylint: disable=unused-argument,no-self-use
        """Decrypt data using the supplied values.

        :param bytes key: Loaded decryption key
        :param bytes data: IV prepended to encrypted data
        :param JavaMode mode: Decryption mode to use (not used by :class:`JavaAsymmetricEncryptionAlgorithm`)
        :param JavaPadding padding: Padding mode to use
        :returns: Decrypted data
        :rtype: bytes
        """
        if hasattr(key, "public_bytes"):
            raise NotImplementedError('"decrypt" is not supported by public keys')
        try:
            return key.decrypt(data, padding.build())
        except Exception:
            error_message = "Decryption failed"
            _LOGGER.exception(error_message)
            raise DecryptionError(error_message)
Beispiel #3
0
def decrypt_dynamodb_item(item, crypto_config):
    # type: (dynamodb_types.ITEM, CryptoConfig) -> dynamodb_types.ITEM
    """Decrypt a DynamoDB item.

    >>> from dynamodb_encryption_sdk.encrypted.item import decrypt_python_item
    >>> encrypted_item = {
    ...     'some': {'B': b'ENCRYPTED_DATA'},
    ...     'more': {'B': b'ENCRYPTED_DATA'}
    ... }
    >>> decrypted_item = decrypt_python_item(
    ...     item=encrypted_item,
    ...     crypto_config=my_crypto_config
    ... )

    .. note::

        This handles DynamoDB-formatted items and is for use with the boto3 DynamoDB client.

    :param dict item: Encrypted and signed DynamoDB item
    :param CryptoConfig crypto_config: Cryptographic configuration
    :returns: Plaintext DynamoDB item
    :rtype: dict
    """
    unique_actions = set([crypto_config.attribute_actions.default_action.name])
    unique_actions.update(
        set([
            action.name for action in
            crypto_config.attribute_actions.attribute_actions.values()
        ]))

    if crypto_config.attribute_actions.take_no_actions:
        # If we explicitly have been told not to do anything to this item, just copy it.
        return item.copy()

    try:
        signature_attribute = item.pop(ReservedAttributes.SIGNATURE.value)
    except KeyError:
        # The signature is always written, so if no signature is found then the item was not
        # encrypted or signed.
        raise DecryptionError("No signature attribute found in item")

    inner_crypto_config = crypto_config.copy()
    # Retrieve the material description from the item if found.
    try:
        material_description_attribute = item.pop(
            ReservedAttributes.MATERIAL_DESCRIPTION.value)
    except KeyError:
        # If no material description is found, we use inner_crypto_config as-is.
        pass
    else:
        # If material description is found, override the material description in inner_crypto_config.
        material_description = deserialize_material_description(
            material_description_attribute)
        inner_crypto_config.encryption_context.material_description = material_description

    decryption_materials = inner_crypto_config.decryption_materials()

    verify_item_signature(signature_attribute, item,
                          decryption_materials.verification_key,
                          inner_crypto_config)

    try:
        decryption_key = decryption_materials.decryption_key
    except AttributeError:
        if inner_crypto_config.attribute_actions.contains_action(
                CryptoAction.ENCRYPT_AND_SIGN):
            raise DecryptionError(
                "Attribute actions ask for some attributes to be decrypted but no decryption key is available"
            )

        return item.copy()

    decryption_mode = inner_crypto_config.encryption_context.material_description.get(
        MaterialDescriptionKeys.ATTRIBUTE_ENCRYPTION_MODE.value)
    algorithm_descriptor = decryption_key.algorithm + decryption_mode

    # Once the signature has been verified, actually decrypt the item attributes.
    decrypted_item = {}
    for name, attribute in item.items():
        if inner_crypto_config.attribute_actions.action(
                name) is CryptoAction.ENCRYPT_AND_SIGN:
            decrypted_item[name] = decrypt_attribute(
                attribute_name=name,
                attribute=attribute,
                decryption_key=decryption_key,
                algorithm=algorithm_descriptor)
        else:
            decrypted_item[name] = attribute.copy()

    return decrypted_item