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 get_encryption_materials(self, request): """Provides encryption materials appropriate for the request. :param request: Encryption materials request :type request: aws_encryption_sdk.materials_managers.EncryptionMaterialsRequest :returns: encryption materials :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ if not self._should_cache_encryption_request(request): return self.backing_materials_manager.get_encryption_materials( request) # Inner request strips any information about the plaintext from the actual request. # This is done because the resulting encryption materials may be used to encrypt # multiple plaintexts. inner_request = EncryptionMaterialsRequest( encryption_context=request.encryption_context, frame_length=request.frame_length, algorithm=request.algorithm, ) cache_key = build_encryption_materials_cache_key( partition=self.partition_name, request=inner_request) # Attempt to retrieve from cache try: cache_entry = self.cache.get_encryption_materials( cache_key=cache_key, plaintext_length=request.plaintext_length) except CacheKeyError: pass else: if self._cache_entry_has_exceeded_limits(cache_entry): self.cache.remove(cache_entry) else: return cache_entry.value # Nothing found in cache: try the material manager new_result = self.backing_materials_manager.get_encryption_materials( inner_request) if not new_result.algorithm.safe_to_cache( ) or request.plaintext_length >= self.max_bytes_encrypted: return new_result # Add results into cache self.cache.put_encryption_materials( cache_key=cache_key, encryption_materials=new_result, plaintext_length=request.plaintext_length, entry_hints=CryptoMaterialsCacheEntryHints(lifetime=self.max_age), ) return new_result
def test_build_encryption_materials_cache_key(inner_request, result): assert build_encryption_materials_cache_key( **inner_request) == b64decode(result)