def test_encryption_cycle_with_caching(): algorithm = Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384 frame_length = 1024 key_provider = fake_kms_key_provider(algorithm.kdf_input_len) cache = aws_encryption_sdk.LocalCryptoMaterialsCache(capacity=10) ccmm = aws_encryption_sdk.CachingCryptoMaterialsManager( master_key_provider=key_provider, cache=cache, max_age=3600.0, max_messages_encrypted=5 ) encrypt_kwargs = dict( source=VALUES["plaintext_128"], materials_manager=ccmm, encryption_context=VALUES["encryption_context"], frame_length=frame_length, algorithm=algorithm, ) encrypt_cache_key = build_encryption_materials_cache_key( partition=ccmm.partition_name, request=EncryptionMaterialsRequest( encryption_context=VALUES["encryption_context"], frame_length=frame_length, algorithm=algorithm, plaintext_length=len(VALUES["plaintext_128"]), ), ) ciphertext, header = aws_encryption_sdk.encrypt(**encrypt_kwargs) decrypt_cache_key = build_decryption_materials_cache_key( partition=ccmm.partition_name, request=DecryptionMaterialsRequest( algorithm=algorithm, encrypted_data_keys=header.encrypted_data_keys, encryption_context=header.encryption_context, ), ) assert len(cache._cache) == 1 assert cache._cache[encrypt_cache_key].messages_encrypted == 1 assert cache._cache[encrypt_cache_key].bytes_encrypted == 128 _, _ = aws_encryption_sdk.decrypt(source=ciphertext, materials_manager=ccmm) assert len(cache._cache) == 2 assert decrypt_cache_key in cache._cache _, _ = aws_encryption_sdk.encrypt(**encrypt_kwargs) _, _ = aws_encryption_sdk.encrypt(**encrypt_kwargs) _, _ = aws_encryption_sdk.encrypt(**encrypt_kwargs) assert len(cache._cache) == 2 assert cache._cache[encrypt_cache_key].messages_encrypted == 4 assert cache._cache[encrypt_cache_key].bytes_encrypted == 512 _, _ = aws_encryption_sdk.encrypt(**encrypt_kwargs) _, _ = aws_encryption_sdk.encrypt(**encrypt_kwargs) _, _ = aws_encryption_sdk.encrypt(**encrypt_kwargs) assert len(cache._cache) == 2 assert cache._cache[encrypt_cache_key].messages_encrypted == 2 assert cache._cache[encrypt_cache_key].bytes_encrypted == 256
def _read_header(self): """Reads the message header from the input stream. :returns: tuple containing deserialized header and header_auth objects :rtype: tuple of aws_encryption_sdk.structures.MessageHeader and aws_encryption_sdk.internal.structures.MessageHeaderAuthentication :raises CustomMaximumValueExceeded: if frame length is greater than the custom max value """ header, raw_header = aws_encryption_sdk.internal.formatting.deserialize.deserialize_header(self.source_stream) if ( self.config.max_body_length is not None and header.content_type == ContentType.FRAMED_DATA and header.frame_length > self.config.max_body_length ): raise CustomMaximumValueExceeded( 'Frame Size in header found larger than custom value: {found} > {custom}'.format( found=header.frame_length, custom=self.config.max_body_length ) ) decrypt_materials_request = DecryptionMaterialsRequest( encrypted_data_keys=header.encrypted_data_keys, algorithm=header.algorithm, encryption_context=header.encryption_context ) decryption_materials = self.config.materials_manager.decrypt_materials(request=decrypt_materials_request) if decryption_materials.verification_key is None: self.verifier = None else: self.verifier = Verifier.from_key_bytes( algorithm=header.algorithm, key_bytes=decryption_materials.verification_key ) if self.verifier is not None: self.verifier.update(raw_header) header_auth = aws_encryption_sdk.internal.formatting.deserialize.deserialize_header_auth( stream=self.source_stream, algorithm=header.algorithm, verifier=self.verifier ) self._derived_data_key = derive_data_encryption_key( source_key=decryption_materials.data_key.data_key, algorithm=header.algorithm, message_id=header.message_id ) aws_encryption_sdk.internal.formatting.deserialize.validate_header( header=header, header_auth=header_auth, raw_header=raw_header, data_key=self._derived_data_key ) return header, header_auth
def test_decrypt_with_keyring_materials_do_not_match_request( kwargs, algorithm_suite): raw_aes256_keyring = ephemeral_raw_aes_keyring( WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING) encrypt_cmm = DefaultCryptoMaterialsManager(keyring=raw_aes256_keyring) decrypt_cmm = DefaultCryptoMaterialsManager( keyring=BrokenKeyring(inner_keyring=raw_aes256_keyring, **kwargs)) encryption_materials_request = EncryptionMaterialsRequest( encryption_context={}, frame_length=1024, algorithm=algorithm_suite) encryption_materials = encrypt_cmm.get_encryption_materials( encryption_materials_request) decryption_materials_request = DecryptionMaterialsRequest( algorithm=encryption_materials.algorithm, encrypted_data_keys=encryption_materials.encrypted_data_keys, encryption_context=encryption_materials.encryption_context, ) with pytest.raises(InvalidCryptographicMaterialsError) as excinfo: decrypt_cmm.decrypt_materials(decryption_materials_request) excinfo.match("Decryption materials do not match request!")
(set([VALUES['basic']['encrypted_data_keys'][1]['key'] ]), [VALUES['basic']['encrypted_data_keys'][1]['hash']]), ([ VALUES['basic']['encrypted_data_keys'][1]['key'], VALUES['basic']['encrypted_data_keys'][0]['key'] ], [ VALUES['basic']['encrypted_data_keys'][0]['hash'], VALUES['basic']['encrypted_data_keys'][1]['hash'] ]))) def test_encrypted_data_keys_hash(encrypted_data_keys, result): hasher = hashes.Hash(hashes.SHA512(), backend=default_backend()) assert _encrypted_data_keys_hash(hasher, encrypted_data_keys) == b''.join( [b64decode(each) for each in result]) @pytest.mark.parametrize( 'inner_request, result', [(dict( partition=scenario['components']['partition_name'], request=DecryptionMaterialsRequest( algorithm=scenario['components']['algorithm'], encrypted_data_keys=scenario['components']['encrypted_data_keys'], encryption_context=scenario['components']['encryption_context'])), scenario['id']) for scenario in VALUES['cache_ids']['decrypt']]) def test_build_decryption_materials_cache_key(inner_request, result): assert build_decryption_materials_cache_key( **inner_request) == b64decode(result) def test_512_bit_pad(): assert _512_BIT_PAD == struct.pack('>64x')
) def test_encrypted_data_keys_hash(encrypted_data_keys, result): hasher = hashes.Hash(hashes.SHA512(), backend=default_backend()) assert _encrypted_data_keys_hash(hasher, encrypted_data_keys) == b"".join( [b64decode(each) for each in result]) @pytest.mark.parametrize( "inner_request, result", [( dict( partition=scenario["components"]["partition_name"], request=DecryptionMaterialsRequest( algorithm=scenario["components"]["algorithm"], encrypted_data_keys=scenario["components"] ["encrypted_data_keys"], encryption_context=scenario["components"] ["encryption_context"], commitment_policy=scenario["components"]["commitment_policy"], ), ), scenario["id"], ) for scenario in VALUES["cache_ids"]["decrypt"]], ) def test_build_decryption_materials_cache_key(inner_request, result): assert build_decryption_materials_cache_key( **inner_request) == b64decode(result) def test_512_bit_pad(): assert _512_BIT_PAD == struct.pack(">64x")
def _read_header(self): """Reads the message header from the input stream. :returns: tuple containing deserialized header and header_auth objects :rtype: tuple of aws_encryption_sdk.structures.MessageHeader and aws_encryption_sdk.internal.structures.MessageHeaderAuthentication :raises CustomMaximumValueExceeded: if frame length is greater than the custom max value """ header, raw_header = deserialize_header(self.source_stream) self.__unframed_bytes_read += len(raw_header) validate_commitment_policy_on_decrypt(self.config.commitment_policy, header.algorithm) if (self.config.max_body_length is not None and header.content_type == ContentType.FRAMED_DATA and header.frame_length > self.config.max_body_length): raise CustomMaximumValueExceeded( "Frame Size in header found larger than custom value: {found:d} > {custom:d}" .format(found=header.frame_length, custom=self.config.max_body_length)) decrypt_materials_request = DecryptionMaterialsRequest( encrypted_data_keys=header.encrypted_data_keys, algorithm=header.algorithm, encryption_context=header.encryption_context, commitment_policy=self.config.commitment_policy, ) decryption_materials = self.config.materials_manager.decrypt_materials( request=decrypt_materials_request) if decryption_materials.verification_key is None: self.verifier = None else: self.verifier = Verifier.from_key_bytes( algorithm=header.algorithm, key_bytes=decryption_materials.verification_key) if self.verifier is not None: self.verifier.update(raw_header) header_auth = deserialize_header_auth(version=header.version, stream=self.source_stream, algorithm=header.algorithm, verifier=self.verifier) self._derived_data_key = derive_data_encryption_key( source_key=decryption_materials.data_key.data_key, algorithm=header.algorithm, message_id=header.message_id) if header.algorithm.is_committing(): expected_commitment_key = calculate_commitment_key( source_key=decryption_materials.data_key.data_key, algorithm=header.algorithm, message_id=header.message_id, ) if not hmac.compare_digest(expected_commitment_key, header.commitment_key): raise MasterKeyProviderError( "Key commitment validation failed. Key identity does not match the identity asserted in the " "message. Halting processing of this message.") validate_header(header=header, header_auth=header_auth, raw_header=raw_header, data_key=self._derived_data_key) return header, header_auth