예제 #1
0
    def decrypt(self, bytes_to_decrypt):
        """
        Decrypts and returns bytes that were encrypted under this master key.

        :param bytes bytes_to_decrypt: (required)
            The bytes to decrypt using this MasterKey.

        :rtype: bytes
        """
        decrypt_data_details = DecryptDataDetails()

        # KMS API expects the key base64 encoded
        decrypt_data_details.ciphertext = convert_to_str(
            base64.b64encode(bytes_to_decrypt))
        decrypt_data_details.key_id = self.master_key_id

        try:
            decrypted_data = self.kms_crypto_client.decrypt(
                decrypt_data_details).data
        except ServiceError as service_error:
            message = "Failed to decrypt data encryption key using masterKeyId: {master_key_id} while targeting vault: {vault_id}.".format(
                master_key_id=self.master_key_id, vault_id=self.vault_id)
            raise_runtime_error_from(message, service_error)

        verify_crc32_checksum(
            base64.b64decode(decrypted_data.plaintext),
            decrypted_data.plaintext_checksum,
        )

        return decrypted_data.plaintext
예제 #2
0
def serialize_header(encrypted_data_header):
    encrypted_data_keys = []
    for encrypted_data_key in encrypted_data_header.encrypted_data_keys:
        encrypted_data_keys.append({
            ENCRYPTED_DATA_KEY_MASTER_KEY_ID:
            encrypted_data_key.master_key_id,
            ENCRYPTED_DATA_KEY_VAULT_ID:
            encrypted_data_key.vault_id,
            ENCRYPTED_DATA_KEY_ENCRYPTED_DATA_KEY:
            convert_bytes_to_base64_encoded_string(
                encrypted_data_key.encrypted_data_key_bytes),
            ENCRYPTED_DATA_KEY_REGION:
            encrypted_data_key.region,
        })

    metadata = {
        METADATA_KEY_ENCRYPTED_CONTENT_FORMAT:
        encrypted_data_header.encrypted_content_format,
        METADATA_KEY_ENCRYPTED_DATA_KEYS:
        encrypted_data_keys,
        METADATA_KEY_IV:
        convert_bytes_to_base64_encoded_string(encrypted_data_header.iv_bytes),
        METADATA_KEY_ALGORITHM_ID:
        encrypted_data_header.algorithm_id,
        METADATA_KEY_ADDITIONAL_AUTHENTICATED_DATA:
        convert_to_str(
            encrypted_data_header.additional_authenticated_data_bytes),
    }

    json_header_as_string = json.dumps(metadata)
    header_format = STRUCT_HEADER_FORMAT.format(
        json_metadata_length=len(json_header_as_string))

    packed_header = struct.pack(
        header_format,
        SERIALIZATION_FORMAT_VERSION,
        len(json_header_as_string),
        convert_to_bytes(json_header_as_string),
    )

    return packed_header
예제 #3
0
    def _init_decryptor_and_header_related_fields(self, header):
        matching_algos = [algo for algo in Algorithm if header.algorithm_id == algo.id]
        if not matching_algos:
            raise ValueError(
                "Could not decrypt payload encrypted using unrecognized algorithm ID: {}".format(
                    header.algorithm_id
                )
            )
        else:
            self._algorithm = matching_algos[0]

        # the user passed in a key provider which is capable of vending master keys
        # we request the specific master key that can decrpt this payload
        encrypted_data_key = header.encrypted_data_keys[0]
        primary_master_key = self._master_key_provider.get_master_key(
            master_key_id=encrypted_data_key.master_key_id,
            vault_id=encrypted_data_key.vault_id,
            region=encrypted_data_key.region,
        )

        decrypted_dek_bytes = primary_master_key.decrypt(
            encrypted_data_key.encrypted_data_key_bytes
        )
        dek_plaintext_bytes = base64.b64decode(decrypted_dek_bytes)

        cipher = Cipher(
            algorithm=self._algorithm.algorithm(dek_plaintext_bytes),
            mode=self._algorithm.mode(header.iv_bytes),
            backend=default_backend(),
        )

        self._decryptor = cipher.decryptor()

        if len(header.additional_authenticated_data_bytes):
            self._encryption_context = json.loads(
                convert_to_str(header.additional_authenticated_data_bytes)
            )
            self._decryptor.authenticate_additional_data(
                header.additional_authenticated_data_bytes
            )
예제 #4
0
def deserialize_header_from_stream(ciphertext_stream):
    short_format = ">H"
    short_size_offset = struct.calcsize(short_format)
    unsigned_int_format = ">I"
    unsigned_int_size_offset = struct.calcsize(unsigned_int_format)
    offset = 0

    # get serialization format version
    next_content = ciphertext_stream.read(short_size_offset)
    (serialization_format_version, ) = struct.unpack_from(
        short_format, next_content, offset)
    offset = offset + short_size_offset

    if serialization_format_version != SERIALIZATION_FORMAT_VERSION:
        raise ValueError(
            "Could not deserialize header with unrecognized serialization format version: {}"
            .format(serialization_format_version))

    # get json metadata length
    next_content = ciphertext_stream.read(unsigned_int_size_offset)
    (json_metadata_length, ) = struct.unpack_from(unsigned_int_format,
                                                  next_content)
    offset = offset + short_size_offset

    # get json metadata
    chunk_format = "{}s".format(json_metadata_length)
    next_content = ciphertext_stream.read(struct.calcsize(chunk_format))
    (json_metadata_bytes, ) = struct.unpack_from(chunk_format, next_content)
    offset = offset + struct.calcsize(chunk_format)

    json_metadata = convert_to_str(json_metadata_bytes)

    try:
        metadata = json.loads(json_metadata)
    except ValueError as e:
        raise ValueError(
            "Could not parse metadata inside header. Error: {}".format(str(e)))

    required_top_level_keys = [
        METADATA_KEY_IV,
        METADATA_KEY_ALGORITHM_ID,
        METADATA_KEY_ADDITIONAL_AUTHENTICATED_DATA,
    ]

    required_encrypted_data_key_keys = [
        ENCRYPTED_DATA_KEY_MASTER_KEY_ID,
        ENCRYPTED_DATA_KEY_VAULT_ID,
        ENCRYPTED_DATA_KEY_ENCRYPTED_DATA_KEY,
        ENCRYPTED_DATA_KEY_REGION,
    ]

    missing_or_none_top_level_keys = [
        required_key for required_key in required_top_level_keys
        if (required_key not in metadata) or (
            metadata.get(required_key, None) is None) or (
                isinstance(metadata.get(required_key), list)
                and len(metadata.get(required_key)) == 0)
    ]
    if missing_or_none_top_level_keys:
        raise ValueError(
            "Invalid header. The following metadata keys must be present and not null: {}."
            .format(", ".join(missing_or_none_top_level_keys)))

    encrypted_data_keys_raw = metadata.get(METADATA_KEY_ENCRYPTED_DATA_KEYS)
    encrypted_data_keys = []
    for encrypted_data_key_raw in encrypted_data_keys_raw:
        missing_or_none_dek_keys = [
            required_key for required_key in required_encrypted_data_key_keys
            if (required_key not in encrypted_data_key_raw) or (
                encrypted_data_key_raw.get(required_key, None) is None)
        ]
        if missing_or_none_dek_keys:
            raise ValueError(
                "Invalid header. The following metadata keys must be present and not null in each encrypted data key: {}."
                .format(", ".join(missing_or_none_dek_keys)))

        encrypted_data_keys.append(
            EncryptedDataHeaderDataEncryptionKey(
                master_key_id=encrypted_data_key_raw.get(
                    ENCRYPTED_DATA_KEY_MASTER_KEY_ID),
                vault_id=encrypted_data_key_raw.get(
                    ENCRYPTED_DATA_KEY_VAULT_ID),
                encrypted_data_key_bytes=convert_base64_encoded_string_to_bytes(
                    encrypted_data_key_raw.get(
                        ENCRYPTED_DATA_KEY_ENCRYPTED_DATA_KEY)),
                region=encrypted_data_key_raw.get(ENCRYPTED_DATA_KEY_REGION),
            ))

    header = EncryptedDataHeader(
        encrypted_data_keys=encrypted_data_keys,
        iv_bytes=convert_base64_encoded_string_to_bytes(
            metadata.get(METADATA_KEY_IV)),
        algorithm_id=metadata.get(METADATA_KEY_ALGORITHM_ID),
        additional_authenticated_data_bytes=convert_to_bytes(
            metadata.get(METADATA_KEY_ADDITIONAL_AUTHENTICATED_DATA)),
    )

    return header