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
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
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 )
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