def test_local_only_mode_no_service_calls(): """A local-only CryptographyClient shouldn't call the service if an operation can't be performed locally""" mock_client = mock.Mock() jwk = JsonWebKey(kty="RSA", key_ops=[], n=b"10011", e=b"10001") client = CryptographyClient.from_jwk(jwk=jwk) client._client = mock_client with pytest.raises(NotImplementedError): client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 0 with pytest.raises(NotImplementedError): client.encrypt(EncryptionAlgorithm.a256_gcm, b"...") assert mock_client.encrypt.call_count == 0 with pytest.raises(NotImplementedError): client.sign(SignatureAlgorithm.rs256, b"...") assert mock_client.sign.call_count == 0 with pytest.raises(NotImplementedError): client.verify(SignatureAlgorithm.es256, b"...", b"...") assert mock_client.verify.call_count == 0 with pytest.raises(NotImplementedError): client.unwrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") assert mock_client.unwrap_key.call_count == 0 with pytest.raises(NotImplementedError): client.wrap_key(KeyWrapAlgorithm.aes_256, b"...") assert mock_client.wrap_key.call_count == 0
def test_rsa_verify_local_from_jwk(self, key_client, is_hsm, **kwargs): """Sign with Key Vault, verify locally""" for size in (2048, 3072, 4096): key_name = self.get_resource_name("rsa-verify-{}".format(size)) key = self._create_rsa_key(key_client, key_name, size=size, hardware_protected=is_hsm) crypto_client = self.create_crypto_client( key, api_version=key_client.api_version) local_client = CryptographyClient.from_jwk(key.key) for signature_algorithm, hash_function in ( (SignatureAlgorithm.ps256, hashlib.sha256), (SignatureAlgorithm.ps384, hashlib.sha384), (SignatureAlgorithm.ps512, hashlib.sha512), (SignatureAlgorithm.rs256, hashlib.sha256), (SignatureAlgorithm.rs384, hashlib.sha384), (SignatureAlgorithm.rs512, hashlib.sha512), ): digest = hash_function(self.plaintext).digest() result = crypto_client.sign(signature_algorithm, digest) self.assertEqual(result.key_id, key.id) result = local_client.verify(result.algorithm, digest, result.signature) self.assertTrue(result.is_valid)
def test_ec_verify_local_from_jwk(self, key_client, is_hsm, **kwargs): """Sign with Key Vault, verify locally""" matrix = { KeyCurveName.p_256: (SignatureAlgorithm.es256, hashlib.sha256), KeyCurveName.p_256_k: (SignatureAlgorithm.es256_k, hashlib.sha256), KeyCurveName.p_384: (SignatureAlgorithm.es384, hashlib.sha384), KeyCurveName.p_521: (SignatureAlgorithm.es512, hashlib.sha512), } for curve, (signature_algorithm, hash_function) in sorted(matrix.items()): key_name = self.get_resource_name("ec-verify-{}".format( curve.value)) key = self._create_ec_key(key_client, key_name, curve=curve, hardware_protected=is_hsm) crypto_client = self.create_crypto_client( key, api_version=key_client.api_version) local_client = CryptographyClient.from_jwk(key.key) digest = hash_function(self.plaintext).digest() result = crypto_client.sign(signature_algorithm, digest) self.assertEqual(result.key_id, key.id) result = local_client.verify(result.algorithm, digest, result.signature) self.assertTrue(result.is_valid)
def test_rsa_verify_local_from_jwk(self, **kwargs): """Sign with Key Vault, verify locally""" is_hsm = kwargs.pop("is_hsm") self._skip_if_not_configured(is_hsm) endpoint_url = self.managed_hsm_url if is_hsm else self.vault_url key_client = self.create_key_client(endpoint_url) for size in (2048, 3072, 4096): key_name = self.get_resource_name("rsa-verify-{}".format(size)) key = self._create_rsa_key(key_client, key_name, size=size, hardware_protected=is_hsm) crypto_client = self.create_crypto_client(key) local_client = CryptographyClient.from_jwk(key.key) for signature_algorithm, hash_function in ( (SignatureAlgorithm.ps256, hashlib.sha256), (SignatureAlgorithm.ps384, hashlib.sha384), (SignatureAlgorithm.ps512, hashlib.sha512), (SignatureAlgorithm.rs256, hashlib.sha256), (SignatureAlgorithm.rs384, hashlib.sha384), (SignatureAlgorithm.rs512, hashlib.sha512), ): digest = hash_function(self.plaintext).digest() result = crypto_client.sign(signature_algorithm, digest) self.assertEqual(result.key_id, key.id) result = local_client.verify(result.algorithm, digest, result.signature) self.assertTrue(result.is_valid)
def test_aes_cbc_iv_validation(): """The client should raise an error when an iv is not provided""" jwk = JsonWebKey(kty="oct-HSM", key_ops=["encrypt", "decrypt"], k=os.urandom(32)) client = CryptographyClient.from_jwk(jwk=jwk) with pytest.raises(ValueError) as ex: client.encrypt(EncryptionAlgorithm.a256_cbcpad, b"...") assert "iv" in str(ex.value).lower()
def test_wrap_local_from_jwk(self, azure_keyvault_url, **kwargs): """Wrap locally, unwrap with Key Vault""" key_client = self.create_key_client(azure_keyvault_url) key_name = self.get_resource_name("wrap-local") key = key_client.create_rsa_key(key_name, size=4096) crypto_client = self.create_crypto_client(key) local_client = CryptographyClient.from_jwk(key.key) for wrap_algorithm in (algo for algo in KeyWrapAlgorithm if algo.startswith("RSA")): result = local_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_encrypt_local_from_jwk(self, azure_keyvault_url, **kwargs): """Encrypt locally, decrypt with Key Vault""" key_client = self.create_key_client(azure_keyvault_url) key_name = self.get_resource_name("encrypt-local") key = key_client.create_rsa_key(key_name, size=4096) crypto_client = self.create_crypto_client(key) local_client = CryptographyClient.from_jwk(key.key) rsa_encrypt_algorithms = [algo for algo in EncryptionAlgorithm if algo.startswith("RSA")] for encrypt_algorithm in rsa_encrypt_algorithms: result = local_client.encrypt(encrypt_algorithm, self.plaintext) self.assertEqual(result.key_id, key.id) result = crypto_client.decrypt(result.algorithm, result.ciphertext) self.assertEqual(result.plaintext, self.plaintext)
def test_local_only_mode_raise(): """A local-only CryptographyClient should raise an exception if an operation can't be performed locally""" jwk = { "kty": "RSA", "key_ops": ["decrypt", "verify", "unwrapKey"], "n": b"10011", "e": b"10001" } client = CryptographyClient.from_jwk(jwk=jwk) # Algorithm not supported locally with pytest.raises(NotImplementedError) as ex: client.decrypt(EncryptionAlgorithm.a256_gcm, b"...", iv=b"...", authentication_tag=b"...") assert EncryptionAlgorithm.a256_gcm in str(ex.value) assert KeyOperation.decrypt in str(ex.value) # Operation not included in JWK permissions with pytest.raises(AzureError) as ex: client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert KeyOperation.encrypt in str(ex.value) # Algorithm not supported locally with pytest.raises(NotImplementedError) as ex: client.verify(SignatureAlgorithm.es256, b"...", b"...") assert SignatureAlgorithm.es256 in str(ex.value) assert KeyOperation.verify in str(ex.value) # Algorithm not supported locally, and operation not included in JWK permissions with pytest.raises(NotImplementedError) as ex: client.sign(SignatureAlgorithm.rs256, b"...") assert SignatureAlgorithm.rs256 in str(ex.value) assert KeyOperation.sign in str(ex.value) # Algorithm not supported locally with pytest.raises(NotImplementedError) as ex: client.unwrap_key(KeyWrapAlgorithm.aes_256, b"...") assert KeyWrapAlgorithm.aes_256 in str(ex.value) assert KeyOperation.unwrap_key in str(ex.value) # Operation not included in JWK permissions with pytest.raises(AzureError) as ex: client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") assert KeyOperation.wrap_key in str(ex.value)
def test_wrap_local_from_jwk(self, key_client, is_hsm, **kwargs): """Wrap locally, unwrap with Key Vault""" key_name = self.get_resource_name("wrap-local") key = self._create_rsa_key(key_client, key_name, size=4096, hardware_protected=is_hsm) crypto_client = self.create_crypto_client( key, api_version=key_client.api_version) local_client = CryptographyClient.from_jwk(key.key) for wrap_algorithm in (algorithm for algorithm in KeyWrapAlgorithm if algorithm.startswith("RSA")): result = local_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_aes_cbc_key_size_validation(): """The client should raise an error when the key is an inappropriate size for the specified algorithm""" jwk = JsonWebKey(kty="oct-HSM", key_ops=["encrypt", "decrypt"], k=os.urandom(64)) iv = os.urandom(16) client = CryptographyClient.from_jwk(jwk=jwk) with pytest.raises(AzureError) as ex: client.encrypt(EncryptionAlgorithm.a128_cbcpad, b"...", iv=iv) # requires 16-byte key assert "key size" in str(ex.value).lower() with pytest.raises(AzureError) as ex: client.encrypt(EncryptionAlgorithm.a192_cbcpad, b"...", iv=iv) # requires 24-byte key assert "key size" in str(ex.value).lower() with pytest.raises(AzureError) as ex: client.encrypt(EncryptionAlgorithm.a256_cbcpad, b"...", iv=iv) # requires 32-byte key assert "key size" in str(ex.value).lower()
def test_encrypt_local_from_jwk(self, key_client, is_hsm, **kwargs): """Encrypt locally, decrypt with Key Vault""" key_name = self.get_resource_name("encrypt-local") key = self._create_rsa_key(key_client, key_name, size=4096, hardware_protected=is_hsm) crypto_client = self.create_crypto_client( key, api_version=key_client.api_version) local_client = CryptographyClient.from_jwk(key.key) rsa_encrypt_algorithms = [ algorithm for algorithm in EncryptionAlgorithm if algorithm.startswith("RSA") ] for encrypt_algorithm in rsa_encrypt_algorithms: result = local_client.encrypt(encrypt_algorithm, self.plaintext) self.assertEqual(result.key_id, key.id) result = crypto_client.decrypt(result.algorithm, result.ciphertext) self.assertEqual(result.plaintext, self.plaintext)
def test_wrap_local_from_jwk(self, **kwargs): """Wrap locally, unwrap with Key Vault""" is_hsm = kwargs.pop("is_hsm") self._skip_if_not_configured(is_hsm) endpoint_url = self.managed_hsm_url if is_hsm else self.vault_url key_client = self.create_key_client(endpoint_url) key_name = self.get_resource_name("wrap-local") key = self._create_rsa_key(key_client, key_name, size=4096, hardware_protected=is_hsm) crypto_client = self.create_crypto_client(key) local_client = CryptographyClient.from_jwk(key.key) for wrap_algorithm in (algo for algo in KeyWrapAlgorithm if algo.startswith("RSA")): result = local_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_encrypt_local_from_jwk(self, **kwargs): """Encrypt locally, decrypt with Key Vault""" is_hsm = kwargs.pop("is_hsm") self._skip_if_not_configured(is_hsm) endpoint_url = self.managed_hsm_url if is_hsm else self.vault_url key_client = self.create_key_client(endpoint_url) key_name = self.get_resource_name("encrypt-local") key = self._create_rsa_key(key_client, key_name, size=4096, hardware_protected=is_hsm) crypto_client = self.create_crypto_client(key) local_client = CryptographyClient.from_jwk(key.key) rsa_encrypt_algorithms = [ algo for algo in EncryptionAlgorithm if algo.startswith("RSA") ] for encrypt_algorithm in rsa_encrypt_algorithms: result = local_client.encrypt(encrypt_algorithm, self.plaintext) self.assertEqual(result.key_id, key.id) result = crypto_client.decrypt(result.algorithm, result.ciphertext) self.assertEqual(result.plaintext, self.plaintext)