def get_or_create_provider(self, material_name, version): # type: (Text, int) -> CryptographicMaterialsProvider """Obtain a cryptographic materials provider identified by a name and version. If the requested version does not exist, a new one will be created. :param str material_name: Material to locate :param int version: Version of material to locate :returns: cryptographic materials provider :rtype: CryptographicMaterialsProvider :raises InvalidVersionError: if the requested version is not available and cannot be created """ encryption_key = JceNameLocalDelegatedKey.generate( MetaStoreValues.ENCRYPTION_ALGORITHM.value, MetaStoreValues.KEY_BITS.value) signing_key = JceNameLocalDelegatedKey.generate( MetaStoreValues.INTEGRITY_ALGORITHM.value, MetaStoreValues.KEY_BITS.value) encryption_key, signing_key = self._save_or_load_materials( material_name, version, encryption_key, signing_key) return WrappedCryptographicMaterialsProvider( signing_key=signing_key, wrapping_key=encryption_key, unwrapping_key=encryption_key, material_description=self._material_description( material_name, version), )
def wrapped_cmp(): wrapping_key = JceNameLocalDelegatedKey.generate("AES", 256) signing_key = JceNameLocalDelegatedKey.generate("HmacSHA512", 256) cmp = WrappedCryptographicMaterialsProvider(signing_key=signing_key, wrapping_key=wrapping_key, unwrapping_key=wrapping_key) return cmp
def test_no_decryption_key_but_decryption_requested(actions, parametrized_item): encryption_key = JceNameLocalDelegatedKey.generate("AES", 256) signing_key = JceNameLocalDelegatedKey.generate("HmacSHA256", 256) encrypting_cmp = StaticCryptographicMaterialsProvider( encryption_materials=RawEncryptionMaterials( encryption_key=encryption_key, signing_key=signing_key)) decrypting_cmp = StaticCryptographicMaterialsProvider( decryption_materials=RawDecryptionMaterials( verification_key=signing_key)) encrypted_item = encrypt_python_item( parametrized_item, CryptoConfig(materials_provider=encrypting_cmp, encryption_context=EncryptionContext(), attribute_actions=actions), ) with pytest.raises(DecryptionError) as excinfo: decrypt_python_item( encrypted_item, CryptoConfig(materials_provider=decrypting_cmp, encryption_context=EncryptionContext(), attribute_actions=actions), ) excinfo.match( "Attribute actions ask for some attributes to be decrypted but no decryption key is available" )
def test_wrapped_symmetric_encrypted_table(ddb_table_name): wrapping_key_bytes = JceNameLocalDelegatedKey.generate("AES", 256).key signing_key_bytes = JceNameLocalDelegatedKey.generate("HmacSHA512", 256).key wrapped_symmetric_encrypted_table.encrypt_item(ddb_table_name, wrapping_key_bytes, signing_key_bytes)
def test_wrapped_rsa_encrypted_table(ddb_table_name): wrapping_key_bytes = JceNameLocalDelegatedKey.generate("RSA", 4096).key signing_key_bytes = JceNameLocalDelegatedKey.generate( "SHA512withRSA", 4096).key wrapped_rsa_encrypted_table.encrypt_item(ddb_table_name, wrapping_key_bytes, signing_key_bytes)
def _generate_content_key(self): """Generate the content encryption key and create a new material description containing necessary information about the content and wrapping keys. :returns content key and new material description :rtype: tuple containing DelegatedKey and dict """ if self._wrapping_key is None: raise WrappingError("Cryptographic materials cannot be generated: no wrapping key") wrapping_algorithm = self.material_description.get( MaterialDescriptionKeys.CONTENT_KEY_WRAPPING_ALGORITHM.value, self._wrapping_transformation(self._wrapping_key.algorithm), ) args = self._content_key_algorithm.split("/", 1) content_algorithm = args[0] try: content_key_length = int(args[1]) except IndexError: content_key_length = None content_key = JceNameLocalDelegatedKey.generate(algorithm=content_algorithm, key_length=content_key_length) wrapped_key = self._wrapping_key.wrap( algorithm=wrapping_algorithm, content_key=content_key.key, additional_associated_data=None ) new_material_description = self.material_description.copy() new_material_description.update( { MaterialDescriptionKeys.WRAPPED_DATA_KEY.value: base64.b64encode(wrapped_key), MaterialDescriptionKeys.CONTENT_ENCRYPTION_ALGORITHM.value: self._content_key_algorithm, MaterialDescriptionKeys.CONTENT_KEY_WRAPPING_ALGORITHM.value: wrapping_algorithm, } ) return content_key, new_material_description
def test_no_encryption_key(): signing_key = JceNameLocalDelegatedKey.generate('HmacSHA512', 256) encryption_materials = RawEncryptionMaterials(signing_key=signing_key) with pytest.raises(AttributeError) as excinfo: encryption_materials.encryption_key excinfo.match('No encryption key available')
def test_no_decryption_key(): verification_key = JceNameLocalDelegatedKey.generate('HmacSHA512', 256) decryption_materials = RawDecryptionMaterials( verification_key=verification_key) with pytest.raises(AttributeError) as excinfo: decryption_materials.decryption_key excinfo.match('No decryption key available')
def test_no_encryption_key_but_encryption_requested(actions, parametrized_item): signing_key = JceNameLocalDelegatedKey.generate("HmacSHA256", 256) cmp = StaticCryptographicMaterialsProvider(encryption_materials=RawEncryptionMaterials(signing_key=signing_key)) crypto_config = CryptoConfig( materials_provider=cmp, encryption_context=EncryptionContext(), attribute_actions=actions ) with pytest.raises(EncryptionError) as excinfo: encrypt_python_item(parametrized_item, crypto_config) excinfo.match("Attribute actions ask for some attributes to be encrypted but no encryption key is available")
def test_only_sign_item(parametrized_item): signing_key = JceNameLocalDelegatedKey.generate("HmacSHA256", 256) cmp = StaticCryptographicMaterialsProvider( encryption_materials=RawEncryptionMaterials(signing_key=signing_key), decryption_materials=RawDecryptionMaterials(verification_key=signing_key), ) actions = AttributeActions(default_action=CryptoAction.SIGN_ONLY) crypto_config = CryptoConfig( materials_provider=cmp, encryption_context=EncryptionContext(), attribute_actions=actions ) signed_item = encrypt_python_item(parametrized_item, crypto_config) material_description = signed_item[ReservedAttributes.MATERIAL_DESCRIPTION.value].value assert MaterialDescriptionKeys.ATTRIBUTE_ENCRYPTION_MODE.value.encode("utf-8") not in material_description decrypt_python_item(signed_item, crypto_config)
def test_generate_correct_key_length(algorithm, requested_bits, expected_bits, length_finder): test = JceNameLocalDelegatedKey.generate(algorithm, requested_bits) assert length_finder(test.key) == expected_bits
def test_warn_on_short_keys(caplog, algorithm, key_bits, too_short, error_message): with caplog.at_level(logging.DEBUG): _test = JceNameLocalDelegatedKey.generate(algorithm, key_bits) logging_results = caplog.text assert (too_short and error_message in logging_results) or (not too_short and error_message not in logging_results)