def test_calls_service_for_operations_unsupported_locally(): """When an operation can't be performed locally, the client should request Key Vault perform it""" mock_client = mock.Mock() key = mock.Mock(spec=KeyVaultKey, id="https://localhost/fake/key/version") client = CryptographyClient(key, mock.Mock()) client._client = mock_client supports_nothing = mock.Mock(supports=mock.Mock(return_value=False)) with mock.patch( CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_nothing): client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 1 assert supports_nothing.decrypt.call_count == 0 client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.encrypt.call_count == 1 assert supports_nothing.encrypt.call_count == 0 client.sign(SignatureAlgorithm.rs256, b"...") assert mock_client.sign.call_count == 1 assert supports_nothing.sign.call_count == 0 client.verify(SignatureAlgorithm.rs256, b"...", b"...") assert mock_client.verify.call_count == 1 assert supports_nothing.verify.call_count == 0 client.unwrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") assert mock_client.unwrap_key.call_count == 1 assert supports_nothing.unwrap_key.call_count == 0 client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") assert mock_client.wrap_key.call_count == 1 assert supports_nothing.wrap_key.call_count == 0
def test_operations(key, expected_error_substrings, encrypt_algorithms, wrap_algorithms): crypto_client = CryptographyClient(key, credential) for algorithm in encrypt_algorithms: with pytest.raises(ValueError) as ex: crypto_client.encrypt(algorithm, self.plaintext) for substring in expected_error_substrings: assert substring in str(ex.value) for algorithm in wrap_algorithms: with pytest.raises(ValueError) as ex: crypto_client.wrap_key(algorithm, self.plaintext) for substring in expected_error_substrings: assert substring in str(ex.value)
def test_wrap_unwrap(self, key_client, **kwargs): credential = self.get_credential(CryptographyClient) key_name = self.get_resource_name("crypto-test-wrapping-key") key = key_client.create_rsa_key(key_name) client = CryptographyClient(key, credential, api_version=key_client.api_version) key_bytes = b"5063e6aaa845f150200547944fd199679c98ed6f99da0a0b2dafeaf1f4684496fd532c1c229968cb9dee44957fcef7ccef59ceda0b362e56bcd78fd3faee5781c623c0bb22b35beabde0664fd30e0e824aba3dd1b0afffc4a3d955ede20cf6a854d52cfd" # [START wrap_key] from azure.keyvault.keys.crypto import KeyWrapAlgorithm # the result holds the encrypted key and identifies the encryption key and algorithm used result = client.wrap_key(KeyWrapAlgorithm.rsa_oaep, key_bytes) encrypted_key = result.encrypted_key print(result.key_id) print(result.algorithm) # [END wrap_key] # [START unwrap_key] from azure.keyvault.keys.crypto import KeyWrapAlgorithm result = client.unwrap_key(KeyWrapAlgorithm.rsa_oaep, encrypted_key) key = result.key
class KeyWrapper: """ Class that fulfills the interface used by the storage SDK's automatic client-side encyrption and decryption routines. """ def __init__(self, kek, credential): self.algorithm = KeyWrapAlgorithm.aes_256 self.kek = kek self.kid = kek.id self.client = CryptographyClient(kek, credential) def wrap_key(self, key): if self.algorithm != KeyWrapAlgorithm.aes_256: raise ValueError('Unknown key wrap algorithm. {}'.format( self.algorithm)) wrapped = self.client.wrap_key(key=key, algorithm=self.algorithm) return wrapped.encrypted_key def unwrap_key(self, key, _): if self.algorithm != KeyWrapAlgorithm.aes_256: raise ValueError('Unknown key wrap algorithm. {}'.format( self.algorithm)) unwrapped = self.client.unwrap_key(encrypted_key=key, algorithm=self.algorithm) return unwrapped.key def get_key_wrap_algorithm(self): return self.algorithm def get_kid(self): return self.kid
def test_rsa_key_id(self, key_client, credential, **kwargs): """When initialized with a key ID, the client should retrieve the key and perform public operations locally""" key = key_client.create_rsa_key(self.create_random_name("rsakey")) crypto_client = CryptographyClient(key.id, credential) crypto_client._initialize() assert crypto_client.key_id == key.id # ensure all remote crypto operations will fail crypto_client._client = None crypto_client.encrypt(EncryptionAlgorithm.rsa_oaep, self.plaintext) crypto_client.verify(SignatureAlgorithm.rs256, hashlib.sha256(self.plaintext).digest(), self.plaintext) crypto_client.wrap_key(KeyWrapAlgorithm.rsa_oaep, self.plaintext)
class UnwrapTest(PerfStressTest): def __init__(self, arguments): super().__init__(arguments) # Auth configuration self.credential = DefaultAzureCredential() self.async_credential = AsyncDefaultAzureCredential() # Create clients vault_url = self.get_from_env("AZURE_KEYVAULT_URL") self.client = KeyClient(vault_url, self.credential, **self._client_kwargs) self.async_client = AsyncKeyClient(vault_url, self.async_credential, **self._client_kwargs) self.key_name = "livekvtestunwrapperfkey" async def global_setup(self): """The global setup is run only once.""" await super().global_setup() rsa_key = await self.async_client.create_rsa_key(self.key_name) self.crypto_client = CryptographyClient(rsa_key.id, self.credential, permissions=NO_GET, **self._client_kwargs) self.async_crypto_client = AsyncCryptographyClient( rsa_key.id, self.async_credential, permissions=NO_GET, **self._client_kwargs) self.test_algorithm = EncryptionAlgorithm.rsa_oaep_256 key_bytes = os.urandom(32) self.encrypted_key = self.crypto_client.wrap_key( self.test_algorithm, key_bytes).encrypted_key async def global_cleanup(self): """The global cleanup is run only once.""" await self.async_client.delete_key(self.key_name) await self.async_client.purge_deleted_key(self.key_name) await super().global_cleanup() async def close(self): """This is run after cleanup.""" await self.async_client.close() await self.async_crypto_client.close() await self.async_credential.close() await super().close() def run_sync(self): """The synchronous perf test.""" self.crypto_client.unwrap_key(self.test_algorithm, self.encrypted_key) async def run_async(self): """The asynchronous perf test.""" await self.async_crypto_client.unwrap_key(self.test_algorithm, self.encrypted_key)
def test_symmetric_wrap_and_unwrap_local(self, **kwargs): jwk = {"k": os.urandom(32), "kty": "oct", "key_ops": ("unwrapKey", "wrapKey")} key = KeyVaultKey(key_id="http://fake.test.vault/keys/key/version", jwk=jwk) crypto_client = CryptographyClient(key, credential=lambda *_: None) # Wrap a key with the created key, then unwrap it. The wrapped key's bytes should round-trip. key_bytes = os.urandom(32) wrap_result = crypto_client.wrap_key(KeyWrapAlgorithm.aes_256, key_bytes) unwrap_result = crypto_client.unwrap_key(wrap_result.algorithm, wrap_result.encrypted_key) self.assertEqual(unwrap_result.key, key_bytes)
def test_prefers_local_provider(): """The client should complete operations locally whenever possible""" mock_client = mock.Mock() key = mock.Mock( spec=KeyVaultKey, id="https://localhost/fake/key/version", properties=mock.Mock(not_before=datetime(2000, 1, 1, tzinfo=_UTC), expires_on=datetime(3000, 1, 1, tzinfo=_UTC)), ) client = CryptographyClient(key, mock.Mock()) client._client = mock_client supports_everything = mock.Mock(supports=mock.Mock(return_value=True)) with mock.patch( CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_everything): client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 0 assert supports_everything.decrypt.call_count == 1 client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.encrypt.call_count == 0 assert supports_everything.encrypt.call_count == 1 client.sign(SignatureAlgorithm.rs256, b"...") assert mock_client.sign.call_count == 0 assert supports_everything.sign.call_count == 1 client.verify(SignatureAlgorithm.rs256, b"...", b"...") assert mock_client.verify.call_count == 0 assert supports_everything.verify.call_count == 1 client.unwrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") assert mock_client.unwrap_key.call_count == 0 assert supports_everything.unwrap_key.call_count == 1 client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") assert mock_client.wrap_key.call_count == 0 assert supports_everything.wrap_key.call_count == 1
def test_wrap_local(self, key_client, credential, **kwargs): """Wrap locally, unwrap with Key Vault""" key = key_client.create_rsa_key("wrap-local", size=4096) crypto_client = CryptographyClient(key, credential) for wrap_algorithm in (algo for algo in KeyWrapAlgorithm if algo.value.startswith("RSA")): result = crypto_client.wrap_key(wrap_algorithm, self.plaintext) self.assertEqual(result.key_id, key.id) result = crypto_client.unwrap_key(result.algorithm, result.encrypted_key) self.assertEqual(result.key, self.plaintext)
def test_wrap_and_unwrap(self, key_client, credential, **kwargs): key_name = self.get_resource_name("keywrap") created_key = key_client.create_key(key_name, "RSA") self.assertIsNotNone(created_key) crypto_client = CryptographyClient(created_key.id, credential) # Wrap a key with the created key, then unwrap it. The wrapped key's bytes should round-trip. key_bytes = self.plaintext result = crypto_client.wrap_key(KeyWrapAlgorithm.rsa_oaep, key_bytes) self.assertEqual(result.key_id, created_key.id) result = crypto_client.unwrap_key(result.algorithm, result.encrypted_key) self.assertEqual(key_bytes, result.key)