diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/_internal.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/_internal.py
index 1b7670efc43a..ba08b7863dbb 100644
--- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/_internal.py
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/_internal.py
@@ -2,7 +2,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------
-
import codecs
from base64 import b64encode, b64decode
@@ -67,29 +66,41 @@ def _b64_to_str(b64str):
return _b64_to_bstr(b64str).decode("utf8")
-def _int_to_bigendian_8_bytes(i):
+def _int_to_fixed_length_bigendian_bytes(i, length):
+ """Convert an integer to a bigendian byte string left-padded with zeroes to a fixed length."""
+
b = _int_to_bytes(i)
- if len(b) > 8:
- raise ValueError("the specified integer is to large to be represented by 8 bytes")
+ if len(b) > length:
+ raise ValueError("{} is too large to be represented by {} bytes".format(i, length))
- if len(b) < 8:
- b = (b"\0" * (8 - len(b))) + b
+ if len(b) < length:
+ b = (b"\0" * (length - len(b))) + b
return b
-def encode_key_vault_ecdsa_signature(signature):
- """
- ASN.1 DER encode a Key Vault ECDSA signature.
-
- Key Vault returns ECDSA signatures as the concatenated bytes of two equal-size integers. ``cryptography`` expects
- ECDSA signatures be ASN.1 DER encoded.
+def ecdsa_to_asn1_der(signature):
+ """ASN.1 DER encode an ECDSA signature.
- :param bytes signature: ECDSA signature returned by Key Vault
- :return: signature encoded for use by ``cryptography``
+ :param bytes signature: ECDSA signature encoded according to RFC 7518, i.e. the concatenated big-endian bytes of
+ two integers (as produced by Key Vault)
+ :return: signature, ASN.1 DER encoded (as expected by ``cryptography``)
"""
mid = len(signature) // 2
r = _bytes_to_int(signature[:mid])
s = _bytes_to_int(signature[mid:])
return utils.encode_dss_signature(r, s)
+
+
+def asn1_der_to_ecdsa(signature, algorithm):
+ """Convert an ASN.1 DER encoded signature to ECDSA encoding.
+
+ :param bytes signature: an ASN.1 DER encoded ECDSA signature (as produced by ``cryptography``)
+ :param _Ecdsa algorithm: signing algorithm which produced ``signature``
+ :return: signature encoded according to RFC 7518 (as expected by Key Vault)
+ """
+ r, s = utils.decode_dss_signature(signature)
+ r_bytes = _int_to_fixed_length_bigendian_bytes(r, algorithm.coordinate_length)
+ s_bytes = _int_to_fixed_length_bigendian_bytes(s, algorithm.coordinate_length)
+ return r_bytes + s_bytes
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/aes_cbc_hmac.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/aes_cbc_hmac.py
index a6016bd30503..f27bdd83c08c 100644
--- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/aes_cbc_hmac.py
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/aes_cbc_hmac.py
@@ -10,7 +10,7 @@
from ..algorithm import AuthenticatedSymmetricEncryptionAlgorithm
from ..transform import AuthenticatedCryptoTransform
-from .._internal import _int_to_bigendian_8_bytes
+from .._internal import _int_to_fixed_length_bigendian_bytes
class _AesCbcHmacCryptoTransform(AuthenticatedCryptoTransform):
@@ -24,7 +24,7 @@ def __init__(self, key, iv, auth_data, auth_tag):
self._cipher = Cipher(algorithms.AES(self._aes_key), modes.CBC(iv), backend=default_backend())
self._tag = auth_tag or bytearray()
self._hmac = hmac.HMAC(self._hmac_key, hash_algo, backend=default_backend())
- self._auth_data_length = _int_to_bigendian_8_bytes(len(auth_data) * 8)
+ self._auth_data_length = _int_to_fixed_length_bigendian_bytes(len(auth_data) * 8, 8)
# prime the hash
self._hmac.update(auth_data)
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/aes_kw.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/aes_kw.py
index 4f0b24e1598b..e2a3845fd9d1 100644
--- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/aes_kw.py
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/aes_kw.py
@@ -7,6 +7,7 @@
from ..algorithm import AsymmetricEncryptionAlgorithm
from ..transform import CryptoTransform
+from ..._enums import KeyWrapAlgorithm
class _AesKeyWrapTransform(CryptoTransform):
@@ -59,7 +60,7 @@ class AesKw192(_AesKeyWrap):
class AesKw256(_AesKeyWrap):
_key_size = 256
- _name = "A256KW"
+ _name = KeyWrapAlgorithm.aes_256
AesKw128.register()
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/ecdsa.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/ecdsa.py
index cff7410a6b44..968fcdbf4375 100644
--- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/ecdsa.py
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/ecdsa.py
@@ -2,12 +2,23 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------
+import abc
+import sys
+
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric import utils
from ..algorithm import SignatureAlgorithm
from ..transform import SignatureTransform
+from ..._enums import SignatureAlgorithm as KeyVaultSignatureAlgorithm
+
+if sys.version_info < (3, 3):
+ abstractproperty = abc.abstractproperty
+else: # abc.abstractproperty is deprecated as of 3.3
+ import functools
+
+ abstractproperty = functools.partial(property, abc.abstractmethod)
class _EcdsaSignatureTransform(SignatureTransform):
@@ -28,25 +39,33 @@ class _Ecdsa(SignatureAlgorithm):
def create_signature_transform(self, key):
return _EcdsaSignatureTransform(key, self.default_hash_algorithm)
+ @abstractproperty
+ def coordinate_length(self):
+ pass
+
class Ecdsa256(_Ecdsa):
- _name = "ES256K"
+ _name = KeyVaultSignatureAlgorithm.es256_k
_default_hash_algorithm = hashes.SHA256()
+ coordinate_length = 32
class Es256(_Ecdsa):
- _name = "ES256"
+ _name = KeyVaultSignatureAlgorithm.es256
_default_hash_algorithm = hashes.SHA256()
+ coordinate_length = 32
class Es384(_Ecdsa):
- _name = "ES384"
+ _name = KeyVaultSignatureAlgorithm.es384
_default_hash_algorithm = hashes.SHA384()
+ coordinate_length = 48
class Es512(_Ecdsa):
- _name = "ES512"
+ _name = KeyVaultSignatureAlgorithm.es512
_default_hash_algorithm = hashes.SHA512()
+ coordinate_length = 66
Ecdsa256.register()
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/rsa_encryption.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/rsa_encryption.py
index e3b72fa8db59..df83c67365d2 100644
--- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/rsa_encryption.py
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/rsa_encryption.py
@@ -7,6 +7,7 @@
from ..algorithm import AsymmetricEncryptionAlgorithm
from ..transform import CryptoTransform
+from ..._enums import EncryptionAlgorithm
class _Rsa1_5Encryptor(CryptoTransform):
@@ -20,7 +21,7 @@ def transform(self, data):
class Rsa1_5(AsymmetricEncryptionAlgorithm): # pylint:disable=client-incorrect-naming-convention
- _name = "RSA1_5"
+ _name = EncryptionAlgorithm.rsa1_5
def create_encryptor(self, key):
return _Rsa1_5Encryptor(key)
@@ -54,7 +55,7 @@ def transform(self, data):
class RsaOaep(AsymmetricEncryptionAlgorithm):
- _name = "RSA-OAEP"
+ _name = EncryptionAlgorithm.rsa_oaep
def create_encryptor(self, key):
return _RsaOaepEncryptor(key, hashes.SHA1)
@@ -64,7 +65,7 @@ def create_decryptor(self, key):
class RsaOaep256(AsymmetricEncryptionAlgorithm):
- _name = "RSA-OAEP-256"
+ _name = EncryptionAlgorithm.rsa_oaep_256
def create_encryptor(self, key):
return _RsaOaepEncryptor(key, hashes.SHA256)
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/rsa_signing.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/rsa_signing.py
index 885070631b85..984befca583a 100644
--- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/rsa_signing.py
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/algorithms/rsa_signing.py
@@ -7,6 +7,7 @@
from ..algorithm import SignatureAlgorithm
from ..transform import SignatureTransform
+from ..._enums import SignatureAlgorithm as KeyVaultSignatureAlgorithm
class RsaSignatureTransform(SignatureTransform):
@@ -17,7 +18,7 @@ def __init__(self, key, padding_function, hash_algorithm):
self._hash_algorithm = hash_algorithm
def sign(self, digest):
- return self._key.sign(digest, self._padding_function(digest), self._hash_algorithm)
+ return self._key.sign(digest, self._padding_function(digest), utils.Prehashed(self._hash_algorithm))
def verify(self, digest, signature):
self._key.verify(signature, digest, self._padding_function(digest), utils.Prehashed(self._hash_algorithm))
@@ -37,32 +38,32 @@ def _get_padding(self, digest):
class Ps256(RsaSsaPss):
- _name = "PS256"
+ _name = KeyVaultSignatureAlgorithm.ps256
_default_hash_algorithm = hashes.SHA256()
class Ps384(RsaSsaPss):
- _name = "PS384"
+ _name = KeyVaultSignatureAlgorithm.ps384
_default_hash_algorithm = hashes.SHA384()
class Ps512(RsaSsaPss):
- _name = "PS512"
+ _name = KeyVaultSignatureAlgorithm.ps512
_default_hash_algorithm = hashes.SHA512()
class Rs256(RsaSsaPkcs1v15):
- _name = "RS256"
+ _name = KeyVaultSignatureAlgorithm.rs256
_default_hash_algorithm = hashes.SHA256()
class Rs384(RsaSsaPkcs1v15):
- _name = "RS384"
+ _name = KeyVaultSignatureAlgorithm.rs384
_default_hash_algorithm = hashes.SHA384()
class Rs512(RsaSsaPkcs1v15):
- _name = "RS512"
+ _name = KeyVaultSignatureAlgorithm.rs512
_default_hash_algorithm = hashes.SHA512()
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/ec_key.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/ec_key.py
index 324ee606f31b..4c88ee5dff20 100644
--- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/ec_key.py
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/ec_key.py
@@ -7,6 +7,8 @@
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric.ec import (
+ EllipticCurvePrivateKey,
+ EllipticCurvePrivateNumbers,
EllipticCurvePublicNumbers,
SECP256R1,
SECP384R1,
@@ -14,37 +16,49 @@
SECP256K1,
)
-from ._internal import _bytes_to_int, encode_key_vault_ecdsa_signature
+from ._internal import _bytes_to_int, asn1_der_to_ecdsa, ecdsa_to_asn1_der
from .key import Key
from .algorithms.ecdsa import Es256, Es512, Es384, Ecdsa256
+from ... import KeyCurveName
-_crypto_crv_to_kv_crv = {"secp256r1": "P-256", "secp384r1": "P-384", "secp521r1": "P-521", "secp256k1": "P-256K"}
+_crypto_crv_to_kv_crv = {
+ "secp256r1": KeyCurveName.p_256,
+ "secp384r1": KeyCurveName.p_384,
+ "secp521r1": KeyCurveName.p_521,
+ "secp256k1": KeyCurveName.p_256_k,
+}
_kv_crv_to_crypto_cls = {
- "P-256": SECP256R1,
- "P-256K": SECP256K1,
- "P-384": SECP384R1,
- "P-521": SECP521R1,
- "SECP256K1": SECP256K1,
+ KeyCurveName.p_256: SECP256R1,
+ KeyCurveName.p_256_k: SECP256K1,
+ KeyCurveName.p_384: SECP384R1,
+ KeyCurveName.p_521: SECP521R1,
+ "SECP256K1": SECP256K1, # "SECP256K1" is from Key Vault 2016-10-01
}
_curve_to_default_algo = {
- "P-256": Es256.name(),
- "P-256K": Ecdsa256.name(),
- "P-384": Es384.name(),
- "P-521": Es512.name(),
- "SECP256K1": Ecdsa256.name(),
+ KeyCurveName.p_256: Es256.name(),
+ KeyCurveName.p_256_k: Ecdsa256.name(),
+ KeyCurveName.p_384: Es384.name(),
+ KeyCurveName.p_521: Es512.name(),
+ "SECP256K1": Ecdsa256.name(), # "SECP256K1" is from Key Vault 2016-10-01
}
class EllipticCurveKey(Key):
- _supported_signature_algorithms = _curve_to_default_algo.values()
+ _supported_signature_algorithms = frozenset(_curve_to_default_algo.values())
- def __init__(self, x, y, kid=None, curve=None):
+ def __init__(self, x, y, d=None, kid=None, curve=None):
super(EllipticCurveKey, self).__init__()
self._kid = kid or str(uuid.uuid4())
self._default_algo = _curve_to_default_algo[curve]
curve_cls = _kv_crv_to_crypto_cls[curve]
- self._ec_impl = EllipticCurvePublicNumbers(x, y, curve_cls()).public_key(default_backend())
+
+ public_numbers = EllipticCurvePublicNumbers(x, y, curve_cls())
+ self._public_key = public_numbers.public_key(default_backend())
+ self._private_key = None
+ if d is not None:
+ private_numbers = EllipticCurvePrivateNumbers(d, public_numbers)
+ self._private_key = private_numbers.private_key(default_backend())
@classmethod
def from_jwk(cls, jwk):
@@ -54,33 +68,39 @@ def from_jwk(cls, jwk):
if not jwk.x or not jwk.y:
raise ValueError("jwk must have values for 'x' and 'y'")
- return cls(_bytes_to_int(jwk.x), _bytes_to_int(jwk.y), kid=jwk.kid, curve=jwk.crv)
+ x = _bytes_to_int(jwk.x)
+ y = _bytes_to_int(jwk.y)
+ d = _bytes_to_int(jwk.d) if jwk.d is not None else None
+ return cls(x, y, d, kid=jwk.kid, curve=jwk.crv)
def is_private_key(self):
- return False
+ return isinstance(self._private_key, EllipticCurvePrivateKey)
def decrypt(self, cipher_text, **kwargs):
- raise NotImplementedError()
+ raise NotImplementedError("Local decryption isn't supported with elliptic curve keys")
def encrypt(self, plain_text, **kwargs):
- raise NotImplementedError()
+ raise NotImplementedError("Local encryption isn't supported with elliptic curve keys")
def wrap_key(self, key, **kwargs):
- raise NotImplementedError()
+ raise NotImplementedError("Local key wrapping isn't supported with elliptic curve keys")
def unwrap_key(self, encrypted_key, **kwargs):
- raise NotImplementedError()
+ raise NotImplementedError("Local key unwrapping isn't supported with elliptic curve keys")
def sign(self, digest, **kwargs):
- raise NotImplementedError()
+ algorithm = self._get_algorithm("sign", **kwargs)
+ signer = algorithm.create_signature_transform(self._private_key)
+ signature = signer.sign(digest)
+ ecdsa_signature = asn1_der_to_ecdsa(signature, algorithm)
+ return ecdsa_signature
def verify(self, digest, signature, **kwargs):
algorithm = self._get_algorithm("verify", **kwargs)
- signer = algorithm.create_signature_transform(self._ec_impl)
- dss_signature = encode_key_vault_ecdsa_signature(signature)
+ signer = algorithm.create_signature_transform(self._public_key)
+ asn1_signature = ecdsa_to_asn1_der(signature)
try:
- # cryptography's verify methods return None, and raise when verification fails
- signer.verify(digest, dss_signature)
+ signer.verify(digest, asn1_signature)
return True
except InvalidSignature:
return False
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/jose.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/jose.py
deleted file mode 100644
index b6b7fb2d3190..000000000000
--- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/jose.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# ------------------------------------
-# Copyright (c) Microsoft Corporation.
-# Licensed under the MIT License.
-# ------------------------------------
-
-import json
-import os
-from ._internal import _str_to_b64url, _b64_to_str
-from .symmetric_key import SymmetricKey
-from .key import Key
-
-
-def protect(plaintext, kek=None, alg=None, cek=None, enc=None): # pylint:disable=unused-argument
- # if neither the kek or the cek is specified raise an error
- if not kek and not cek:
- raise ValueError(
- "Either kek must be specified for key encryption sharing, "
- "or cek must be specified for direct encryption key sharing"
- )
-
- # key encryption key can be any key (symmetric or asymmetric)
- if kek and not isinstance(kek, Key):
- raise TypeError("The specified kek must be a valid Key")
-
- # only symmetric keys are valid for the content encryption key
- if cek and not isinstance(cek, SymmetricKey):
- raise TypeError("The specified cek must be a valid SymmetricKey")
-
- # create the cek if not specified
- cek = cek or SymmetricKey()
-
- # kid is the kek id if were using key encryption sharing else it's the cek id for direct sharing
- kid = kek.kid if kek else cek.kid
-
- # alg is 'dir' for direct sharing otherwise use the specified alg
- # or the default key wrap algorithm if not specified
- alg = "dir" if not kek else alg or kek.default_key_wrap_algorithm
-
- # use the specified enc or the default encryption algorithm of the cek if not specified
- enc = enc or cek.default_encryption_algorithm
-
- jwe = JweObject()
- jwe.unprotected = JweHeader(alg=alg, kid=kid, enc=enc)
- jwe.iv = os.urandom(16)
- jwe.ciphertext = cek.encrypt()
-
- # add the encrypted key if we're using key encryption sharing
- if kek:
- jwe.encrypted_key = kek.wrap_key(key=cek)
-
-
-class JoseObject(object):
- def deserialize(self, s):
- d = json.loads(s)
- self.__dict__ = d # pylint:disable=attribute-defined-outside-init
- return self
-
- def deserialize_b64(self, s):
- self.deserialize(_b64_to_str(s))
- return self
-
- def serialize(self):
- return json.dumps(self.__dict__)
-
- def serialize_b64url(self):
- return _str_to_b64url(self.serialize())
-
-
-class JoseHeader(JoseObject):
- def to_compact_header(self):
- return _str_to_b64url(json.dumps(self.__dict__))
-
-
-class JweHeader(JoseHeader):
- def __init__(self, alg=None, kid=None, enc=None):
- self.alg = alg
- self.kid = kid
- self.enc = enc
-
- @staticmethod
- def from_compact_header(compact):
- header = JweHeader()
- header.__dict__ = json.loads(_b64_to_str(compact)) # pylint:disable=attribute-defined-outside-init
- return header
-
-
-class JweObject(JoseObject):
- def __init__(self):
- self.unprotected = None
- self.protected = None
- self.encrypted_key = None
- self.iv = None
- self.ciphertext = None
- self.tag = None
-
- def to_flattened_jwe(self):
- if not (self.protected, self.encrypted_key, self.iv, self.ciphertext, self.tag):
- raise ValueError("JWE is not complete.")
-
- return json.dumps(self.__dict__)
-
-
-class JwsHeader(JoseHeader):
- def __init__(self):
- self.alg = None
- self.kid = None
- self.at = None
- self.ts = None
- self.p = None
- self.typ = None
-
- @staticmethod
- def from_compact_header(compact):
- header = JwsHeader()
- header.__dict__ = json.loads(_b64_to_str(compact)) # pylint:disable=attribute-defined-outside-init
- return header
-
-
-class JwsObject(JoseObject):
- def __init__(self):
- self.protected = None
- self.payload = None
- self.signature = None
-
- def to_flattened_jws(self):
- if not (self.protected, self.payload, self.signature):
- raise ValueError("JWS is not complete.")
-
- return json.dumps(self.__dict__)
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/rsa_key.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/rsa_key.py
index 117f0b900687..06852817717d 100644
--- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/rsa_key.py
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/rsa_key.py
@@ -7,6 +7,7 @@
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric.rsa import (
+ RSAPrivateKey,
RSAPrivateNumbers,
RSAPublicNumbers,
generate_private_key,
@@ -15,27 +16,26 @@
rsa_crt_iqmp,
)
-from azure.keyvault.keys._models import JsonWebKey
from ._internal import _bytes_to_int, _int_to_bytes
from .key import Key
from .algorithms import Ps256, Ps384, Ps512, Rsa1_5, RsaOaep, RsaOaep256, Rs256, Rs384, Rs512
+from ... import JsonWebKey, KeyOperation
class RsaKey(Key): # pylint:disable=too-many-public-methods
- PUBLIC_KEY_DEFAULT_OPS = ["encrypt", "wrapKey", "verify"]
- PRIVATE_KEY_DEFAULT_OPS = ["encrypt", "decrypt", "wrapKey", "unwrapKey", "verify", "sign"]
-
- _supported_encryption_algorithms = [Rsa1_5.name(), RsaOaep.name(), RsaOaep256.name()]
- _supported_key_wrap_algorithms = [Rsa1_5.name(), RsaOaep.name(), RsaOaep256.name()]
- _supported_signature_algorithms = [
- Ps256.name(),
- Ps384.name(),
- Ps512.name(),
- Rs256.name(),
- Rs384.name(),
- Rs512.name(),
+ PUBLIC_KEY_DEFAULT_OPS = [KeyOperation.encrypt, KeyOperation.wrap_key, KeyOperation.verify]
+ PRIVATE_KEY_DEFAULT_OPS = PUBLIC_KEY_DEFAULT_OPS + [
+ KeyOperation.decrypt,
+ KeyOperation.unwrap_key,
+ KeyOperation.sign,
]
+ _supported_encryption_algorithms = frozenset((Rsa1_5.name(), RsaOaep.name(), RsaOaep256.name()))
+ _supported_key_wrap_algorithms = frozenset((Rsa1_5.name(), RsaOaep.name(), RsaOaep256.name()))
+ _supported_signature_algorithms = frozenset(
+ (Ps256.name(), Ps384.name(), Ps512.name(), Rs256.name(), Rs384.name(), Rs512.name(),)
+ )
+
def __init__(self, kid=None):
super(RsaKey, self).__init__()
self._kid = kid
@@ -212,10 +212,7 @@ def unwrap_key(self, encrypted_key, **kwargs):
return decryptor.transform(encrypted_key)
def is_private_key(self):
- # return isinstance(self._rsa_impl, RSAPrivateKey)
- # TODO returning False here even if someone sneaked in private key material because
- # currently we don't want to perform decrypt/unwrap/sign locally
- return False
+ return isinstance(self._rsa_impl, RSAPrivateKey)
def _public_key_material(self):
return self.public_key.public_numbers()
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/symmetric_key.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/symmetric_key.py
index 2e4d7e73422f..e2cfdb4d6610 100644
--- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/symmetric_key.py
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_internal/symmetric_key.py
@@ -55,6 +55,26 @@ def __init__(self, kid=None, key_bytes=None, key_size=None):
self._key = key_bytes
+ supported_encryption_algorithms = []
+ supported_key_wrap_algorithms = []
+ key_size = len(self._key)
+ if key_size >= key_size_128:
+ supported_encryption_algorithms.append(Aes128Cbc.name())
+ supported_key_wrap_algorithms.append(AesKw128.name())
+ if key_size >= key_size_192:
+ supported_encryption_algorithms.append(Aes192Cbc.name())
+ supported_key_wrap_algorithms.append(AesKw192.name())
+ if key_size >= key_size_256:
+ supported_encryption_algorithms.append(Aes256Cbc.name())
+ supported_encryption_algorithms.append(Aes128CbcHmacSha256.name())
+ supported_key_wrap_algorithms.append(AesKw256.name())
+ if key_size >= key_size_384:
+ supported_encryption_algorithms.append(Aes192CbcHmacSha384.name())
+ if key_size >= key_size_512:
+ supported_encryption_algorithms.append(Aes256CbcHmacSha512.name())
+ self._supported_encryption_algorithms = frozenset(supported_encryption_algorithms)
+ self._supported_key_wrap_algorithms = frozenset(supported_key_wrap_algorithms)
+
def is_private_key(self):
return True
@@ -74,39 +94,6 @@ def default_encryption_algorithm(self):
def default_key_wrap_algorithm(self):
return _default_kw_alg_by_size[len(self._key)]
- @property
- def supported_encryption_algorithms(self):
- supported = []
- key_size = len(self._key)
-
- if key_size >= key_size_128:
- supported.append(Aes128Cbc.name())
- if key_size >= key_size_192:
- supported.append(Aes192Cbc.name())
- if key_size >= key_size_256:
- supported.append(Aes256Cbc.name())
- supported.append(Aes128CbcHmacSha256.name())
- if key_size >= key_size_384:
- supported.append(Aes192CbcHmacSha384.name())
- if key_size >= key_size_512:
- supported.append(Aes256CbcHmacSha512.name())
-
- return supported
-
- @property
- def supported_key_wrap_algorithms(self):
- supported = []
- key_size = len(self._key)
-
- if key_size >= key_size_128:
- supported.append(AesKw128.name())
- if key_size >= key_size_192:
- supported.append(AesKw192.name())
- if key_size >= key_size_256:
- supported.append(AesKw256.name())
-
- return supported
-
def encrypt(self, plain_text, iv, **kwargs): # pylint:disable=arguments-differ
algorithm = self._get_algorithm("encrypt", **kwargs)
encryptor = algorithm.create_encryptor(key=self._key, iv=iv)
@@ -128,7 +115,7 @@ def unwrap_key(self, encrypted_key, **kwargs):
return decryptor.transform(encrypted_key)
def sign(self, digest, **kwargs):
- raise NotImplementedError()
+ raise NotImplementedError("Local signing isn't supported with symmetric keys")
def verify(self, digest, signature, **kwargs):
- raise NotImplementedError()
+ raise NotImplementedError("Local signature verification isn't supported with symmetric keys")
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py
new file mode 100644
index 000000000000..6648d5f19fa3
--- /dev/null
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py
@@ -0,0 +1,26 @@
+# ------------------------------------
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+# ------------------------------------
+from typing import TYPE_CHECKING
+
+from .ec import EllipticCurveCryptographyProvider
+from .rsa import RsaCryptographyProvider
+from .symmetric import SymmetricCryptographyProvider
+from ... import KeyType
+
+if TYPE_CHECKING:
+ from .local_provider import LocalCryptographyProvider
+ from ... import KeyVaultKey
+
+
+def get_local_cryptography_provider(key):
+ # type: (KeyVaultKey) -> LocalCryptographyProvider
+ if key.key_type in (KeyType.ec, KeyType.ec_hsm):
+ return EllipticCurveCryptographyProvider(key)
+ if key.key_type in (KeyType.rsa, KeyType.rsa_hsm):
+ return RsaCryptographyProvider(key)
+ if key.key_type == KeyType.oct:
+ return SymmetricCryptographyProvider(key)
+
+ raise ValueError('Unsupported key type "{}"'.format(key.key_type))
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py
new file mode 100644
index 000000000000..1534e1da9927
--- /dev/null
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py
@@ -0,0 +1,37 @@
+# ------------------------------------
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+# ------------------------------------
+from typing import TYPE_CHECKING
+
+from .local_provider import LocalCryptographyProvider
+from .._internal import EllipticCurveKey
+from ... import KeyOperation, KeyType
+
+if TYPE_CHECKING:
+ # pylint:disable=unused-import
+ from .local_provider import Algorithm
+ from .._internal import Key
+ from ... import KeyVaultKey
+
+_PRIVATE_KEY_OPERATIONS = frozenset((KeyOperation.decrypt, KeyOperation.sign, KeyOperation.unwrap_key))
+
+
+class EllipticCurveCryptographyProvider(LocalCryptographyProvider):
+ def _get_internal_key(self, key):
+ # type: (KeyVaultKey) -> Key
+ if key.key_type not in (KeyType.ec, KeyType.ec_hsm):
+ raise ValueError('"key" must be an EC or EC-HSM key')
+ return EllipticCurveKey.from_jwk(key.key)
+
+ def supports(self, operation, algorithm):
+ # type: (KeyOperation, Algorithm) -> bool
+ if operation in _PRIVATE_KEY_OPERATIONS and not self._internal_key.is_private_key():
+ return False
+ if operation in (KeyOperation.decrypt, KeyOperation.encrypt):
+ return algorithm in self._internal_key.supported_encryption_algorithms
+ if operation in (KeyOperation.unwrap_key, KeyOperation.wrap_key):
+ return algorithm in self._internal_key.supported_key_wrap_algorithms
+ if operation in (KeyOperation.sign, KeyOperation.verify):
+ return algorithm in self._internal_key.supported_signature_algorithms
+ return False
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py
new file mode 100644
index 000000000000..1d81dd897cc6
--- /dev/null
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py
@@ -0,0 +1,97 @@
+# ------------------------------------
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+# ------------------------------------
+import abc
+from typing import TYPE_CHECKING
+
+from azure.core.exceptions import AzureError
+
+from .. import DecryptResult, EncryptResult, SignResult, UnwrapResult, VerifyResult, WrapResult
+from ... import KeyOperation
+
+try:
+ ABC = abc.ABC
+except AttributeError: # Python 2.7
+ ABC = abc.ABCMeta("ABC", (object,), {"__slots__": ()}) # type: ignore
+
+if TYPE_CHECKING:
+ # pylint:disable=unused-import
+ from typing import Union
+ from .._internal.key import Key
+ from .. import EncryptionAlgorithm, KeyWrapAlgorithm, SignatureAlgorithm
+ from ... import KeyVaultKey
+
+ Algorithm = Union[EncryptionAlgorithm, KeyWrapAlgorithm, SignatureAlgorithm]
+
+
+class LocalCryptographyProvider(ABC):
+ def __init__(self, key):
+ # type: (KeyVaultKey) -> None
+ self._allowed_ops = frozenset(key.key_operations)
+ self._internal_key = self._get_internal_key(key)
+ self._key = key
+
+ @abc.abstractmethod
+ def _get_internal_key(self, key):
+ # type: (KeyVaultKey) -> Key
+ pass
+
+ @abc.abstractmethod
+ def supports(self, operation, algorithm):
+ # type: (KeyOperation, Algorithm) -> bool
+ pass
+
+ @property
+ def key_id(self):
+ # type: () -> str
+ """The full identifier of the provider's key.
+
+ :rtype: str
+ """
+ return self._key.id
+
+ def _raise_if_unsupported(self, operation, algorithm):
+ # type: (KeyOperation, Algorithm) -> None
+ if not self.supports(operation, algorithm):
+ raise NotImplementedError(
+ 'This key does not support the "{}" operation with algorithm "{}"'.format(operation, algorithm)
+ )
+ if operation not in self._allowed_ops:
+ raise AzureError('This key does not allow the "{}" operation'.format(operation))
+
+ def encrypt(self, algorithm, plaintext):
+ # type: (EncryptionAlgorithm, bytes) -> EncryptResult
+ self._raise_if_unsupported(KeyOperation.encrypt, algorithm)
+ ciphertext = self._internal_key.encrypt(plaintext, algorithm=algorithm.value)
+ return EncryptResult(key_id=self._key.id, algorithm=algorithm, ciphertext=ciphertext)
+
+ def decrypt(self, algorithm, ciphertext):
+ # type: (EncryptionAlgorithm, bytes) -> DecryptResult
+ self._raise_if_unsupported(KeyOperation.decrypt, algorithm)
+ plaintext = self._internal_key.decrypt(ciphertext, iv=None, algorithm=algorithm.value)
+ return DecryptResult(key_id=self._key.id, algorithm=algorithm, plaintext=plaintext)
+
+ def wrap_key(self, algorithm, key):
+ # type: (KeyWrapAlgorithm, bytes) -> WrapResult
+ self._raise_if_unsupported(KeyOperation.wrap_key, algorithm)
+ encrypted_key = self._internal_key.wrap_key(key, algorithm=algorithm.value)
+ return WrapResult(key_id=self._key.id, algorithm=algorithm, encrypted_key=encrypted_key)
+
+ def unwrap_key(self, algorithm, encrypted_key):
+ # type: (KeyWrapAlgorithm, bytes) -> UnwrapResult
+ self._raise_if_unsupported(KeyOperation.unwrap_key, algorithm)
+ unwrapped_key = self._internal_key.unwrap_key(encrypted_key, algorithm=algorithm.value)
+ return UnwrapResult(key_id=self._key.id, algorithm=algorithm, key=unwrapped_key)
+
+ def sign(self, algorithm, digest):
+ # type: (SignatureAlgorithm, bytes) -> SignResult
+ self._raise_if_unsupported(KeyOperation.sign, algorithm)
+ signature = self._internal_key.sign(digest, algorithm=algorithm.value)
+ return SignResult(key_id=self._key.id, algorithm=algorithm, signature=signature)
+
+ def verify(self, algorithm, digest, signature):
+ # type: (SignatureAlgorithm, bytes, bytes) -> VerifyResult
+ self._raise_if_unsupported(KeyOperation.verify, algorithm)
+ is_valid = self._internal_key.verify(digest, signature, algorithm=algorithm.value)
+ return VerifyResult(key_id=self._key.id, algorithm=algorithm, is_valid=is_valid)
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py
new file mode 100644
index 000000000000..b7d913a7f7ed
--- /dev/null
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py
@@ -0,0 +1,37 @@
+# ------------------------------------
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+# ------------------------------------
+from typing import TYPE_CHECKING
+
+from .local_provider import LocalCryptographyProvider
+from .._internal import RsaKey
+from ... import KeyOperation, KeyType
+
+if TYPE_CHECKING:
+ # pylint:disable=unused-import
+ from .local_provider import Algorithm
+ from .._internal import Key
+ from ... import KeyVaultKey
+
+_PRIVATE_KEY_OPERATIONS = frozenset((KeyOperation.decrypt, KeyOperation.sign, KeyOperation.unwrap_key))
+
+
+class RsaCryptographyProvider(LocalCryptographyProvider):
+ def _get_internal_key(self, key):
+ # type: (KeyVaultKey) -> Key
+ if key.key_type not in (KeyType.rsa, KeyType.rsa_hsm):
+ raise ValueError('"key" must be an RSA or RSA-HSM key')
+ return RsaKey.from_jwk(key.key)
+
+ def supports(self, operation, algorithm):
+ # type: (KeyOperation, Algorithm) -> bool
+ if operation in _PRIVATE_KEY_OPERATIONS and not self._internal_key.is_private_key():
+ return False
+ if operation in (KeyOperation.decrypt, KeyOperation.encrypt):
+ return algorithm in self._internal_key.supported_encryption_algorithms
+ if operation in (KeyOperation.unwrap_key, KeyOperation.wrap_key):
+ return algorithm in self._internal_key.supported_key_wrap_algorithms
+ if operation in (KeyOperation.sign, KeyOperation.verify):
+ return algorithm in self._internal_key.supported_signature_algorithms
+ return False
diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py
new file mode 100644
index 000000000000..ef34238ff395
--- /dev/null
+++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py
@@ -0,0 +1,30 @@
+# ------------------------------------
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+# ------------------------------------
+from typing import TYPE_CHECKING
+
+from .local_provider import LocalCryptographyProvider
+from .._internal import SymmetricKey
+from ... import KeyOperation, KeyType
+
+if TYPE_CHECKING:
+ # pylint:disable=unused-import
+ from .local_provider import Algorithm
+ from .._internal import Key
+ from ... import KeyVaultKey
+
+
+class SymmetricCryptographyProvider(LocalCryptographyProvider):
+ def _get_internal_key(self, key):
+ # type: (KeyVaultKey) -> Key
+ if key.key_type != KeyType.oct:
+ raise ValueError('"key" must be an oct (symmetric) key')
+ return SymmetricKey.from_jwk(key.key)
+
+ def supports(self, operation, algorithm):
+ # type: (KeyOperation, Algorithm) -> bool
+ return (
+ operation in (KeyOperation.unwrap_key, KeyOperation.wrap_key)
+ and algorithm in self._internal_key.supported_key_wrap_algorithms
+ )
diff --git a/sdk/keyvault/azure-keyvault-keys/tests/keys.py b/sdk/keyvault/azure-keyvault-keys/tests/keys.py
new file mode 100644
index 000000000000..80db438ae5f2
--- /dev/null
+++ b/sdk/keyvault/azure-keyvault-keys/tests/keys.py
@@ -0,0 +1,103 @@
+# ------------------------------------
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+# ------------------------------------
+"""Keys for use in test cases"""
+
+from azure.keyvault.keys import KeyCurveName, KeyVaultKey
+
+EC_KEYS = {
+ KeyCurveName.p_256: KeyVaultKey(
+ key_id="https://localhost/keys/key-name/version",
+ jwk={
+ "kty": "EC",
+ "key_ops": ["encrypt", "decrypt", "wrapKey", "unwrapKey", "sign", "verify"],
+ "d": b"^T\xf9F\r\xb5\xa8\x1a \n\xa6[\xfa\x12-0\n\xb7\x92\t\xee\xd1\x03\x9d\xd5\xca\x9c\n\xc4\x10\xefI",
+ "crv": "P-256",
+ "x": b"\xba\xb3Z\\\xea\x01\x10\xb4\xbe\x81\xb0\xc4h\xc2\xeb1\xa3\xbfb\x11A\xd939\xcc\x8aY\x05\xf3\x83\x12E",
+ "y": b"\x1fs\xbe\xfa\xc7\xef\xd3{H\xea\x1a\xcb:r\xc2\x8c\xf2\xde#z2B]\xc3\xa6>\xc0\xa6.pUN",
+ },
+ ),
+ KeyCurveName.p_384: KeyVaultKey(
+ key_id="https://localhost/keys/key-name/version",
+ jwk={
+ "kty": "EC",
+ "key_ops": ["encrypt", "decrypt", "wrapKey", "unwrapKey", "sign", "verify"],
+ "d": b"\xe1\x13g}\xdeV\xad(`\x85\xed\x8c\xc4}\x9f\x9eE\x14\x1c\x12\xff\xa4s\xa5L\x05j*W\xb3X\x88A\xe2?\x1f\x80\xd6\xf1\x0fR\x91\x0fh\xf3EH\xcf",
+ "crv": "P-384",
+ "x": b"\xa5\xd1\tFX\x12\xd5\xa8\xb5\x00\xe4p\xf8S\x8e\x8d\x80q\xdc.\xbe\x86\xef\xf1\x99\x15\xaa\xde0\xb1'(\xc0\xcb;43\xca\x14\x17,\xe1T\x10\xc2iK\x08",
+ "y": b"H6\x19\x8c\xe6\xcc\x0brhJ\x98\xd3\x9b\xf2\x08\xf5\xf0z&/S\xd2\xb3x \x18[\xcc\xb9E\xb6M\x87\xfb\x06z\xd9\x95\xcbj\x84\x8aPq$\xf3t\x9c",
+ },
+ ),
+ KeyCurveName.p_256_k: KeyVaultKey(
+ key_id="https://localhost/keys/key-name/version",
+ jwk={
+ "kty": "EC",
+ "key_ops": ["encrypt", "decrypt", "wrapKey", "unwrapKey", "sign", "verify"],
+ "d": b"\x84\x9f\xb9\x07\x91\x1c\xb9V#\x8d\xb8\xec+\x8e\xba\x17%\xc9[\xb1\xd0J\x94\xfd\xcb\x1c\x89\xd1[\x10\x86R",
+ "crv": "P-256K",
+ "x": b"~\xa5i\xa0\n\xe5wo\xf7\x08of\xb8\xf1\xee\xc8\x0b\x18\xde\x99t\x95\x06\x9c\xccb&L\xe4|;\xf6",
+ "y": b"t\xe9\x9d\x07^\x81\xb3\xdb(8\x90\x95\xdd \xa7\xf6\x0ep\xec$\x1cq\xc7\xcf\x08\xf8\xb5r\x9e04\xf3",
+ },
+ ),
+ KeyCurveName.p_521: KeyVaultKey(
+ key_id="https://localhost/keys/key-name/version",
+ jwk={
+ "kty": "EC",
+ "key_ops": ["encrypt", "decrypt", "wrapKey", "unwrapKey", "sign", "verify"],
+ "d": b"\xb55`\xbe\xd7\x0f'0D\xdf\xe0 \xd4\xed?\xf4\xee\xe0\xf0l\xd7\x08\x87l0\x04R\x01l1\x85\xb7\xf5\x14H\xde\x19\xeb\x13\xab_\xf0\t\xbe\x88\x18\x1b\xbd.\x89\xe9\xda3\xdc\x97\xc5\x18\x0f8\xa4\xbeb\x83z\xf0",
+ "crv": "P-521",
+ "x": b"\x83\x95Q\x1e\xa3\xf3\xad\xde\xc6\xb4\xdd\xe8\x1d^}\x15\x85\\\xcc\x95\xe4\xfc\xea\x89\x7f\x8d\xd2\xe5\x81/u\xbb^\xd0W\t\x93P\xdb3\xd6T\x8f\x9c\x90\xa1\x95\xffQ\xa0\x96\xd7\x11a.C\x03?\x81\x02D\xb2x\xf3\xaa",
+ "y": b'\x01\x8c\xda\xc9\x1ej\xe5B7\xcc\xaaFD\x0e\xb2\xe9\xaad\xf9\n\xc5\x93:\xcaBE\xbc\x04\x94\x03\xe0\xb8h\x00K3L"\xfa\r\x91\x8fJ\xbfJF2\x17\xd0\xfb\xbb@9\xbe\x87+\x05I\xab\x9cu\xafV\xaa\x1c\x99',
+ },
+ ),
+}
+
+
+RSA_KEYS = {
+ 2048: KeyVaultKey(
+ key_id="https://localhost/keys/key-name/version",
+ jwk={
+ "kty": "RSA",
+ "key_ops": ["encrypt", "decrypt", "wrapKey", "unwrapKey", "sign", "verify"],
+ "n": b"\xeb
\xc8z\xdb\xa4\xa3U;\xb7Bn\xcfP\x9dA\x89\xdcq\xc7\x89\xe2I\x8dI9\xd5\x90b\xf0\xe5\t\xaf\x90\xf2\x8aC`5\xb1h\xbb\x19U\x86\xe1\xc2\x9f\xee_N\x93\xdec*\xc8J\x1bS3\xe4\xa0\xe5\x82\x0e\xd7P\xba\x1d\xbbb\xfbF\x85\x80\x9c\xb8)\xfb\xbb\xc0Y\xbasb\xc9-AZ\x85\xeajt\xcc\xf1\x96\x14\xaeD\x88,\xa3\x13\xcaE\xb3\xb2\xd7\x152P\xee\xf6lS\x1c\xdbp\xe4^\xd3\xf1\x18\xe6?\x94\xc9\x1dS\xdc\xc9\x08s\xd1bA\xa5\x1a?\x0cT\x7fAs\xb8\xfc\xdb\x0c\x82\xad+\x80\xb8=\xa2:\x85~\xe1\xef\xdc@w\x04\\j\x9c\x18h\x14j?*\xa8g\xd5\x91+\xe1\t!:\x0b\x10\xe0\x99\xc9\xe3g\x1e\xfao\xb5\x8fD\xd6r\x7f\x94\x7fX\x00\x9e#]\xcf@z\xae\x82\xa1\xa2)\x00\x8e\xb3\xdc\xc1\xdczNm\xb5',
+ "dp": b"\x91|\xbd\xa3\xf6\x01\x08\xb7\x92\x1c\x1a}\xe3\xc4\xb1#\x97\x0bxT\xb6\x13\xecx\x8f\xf6\xf3=B=\x80\xb2@\xf2\xce6rSDtB\x04u\x8d\x0c\xb3J\x84\xa3\xedz>\x0fW\xdd\xeeu_[\xf2X-\xdc\xb5}\xd2\xd0b\x11\x9e\x16l\xbc\xcdGZ}h\xa8&\x12 \x08Y\x9d}\x08\x06\xd3c\x93\x106\x8a\x1a\x19\x9f\xf5\x95P\xcce#\x05N\x01\xb8\xbb\x07\x04@\x19\x8e\xb3\x81WzIow\xff\xe1a\xe9\xd0`e\xff",
+ "dq": b"\x0eV\x80:\xd9k\xa8\x02U(Ew\x14\x16\x01C\xd8\xe2\x06\x10\x9a\x9aZ\xf1\xf3\x0f\xbe&E\xaa<\t\xb2\xbf&\x0c1\xf3B\xf0j\xc4\x8d\xf7\xa2^\x8f9\x9fY\x0f\xf8\x0f\xa7\x9c\xbd\xb9\xb6<\xaf\xc6\x9b\xb8wJ\x9d\x0c\xa0\xd0|\x97?b\xb0\x0e\x19\xf9\x96\xf3\x1e\x96\xfcp\xe7\x7f\x0f\xad(h\x878'\xccJ\x022\xc7\x06\x89|\x99DH\x9e\x8d\x97\xb2\xbe#(\xb9\xef\xb3\xc9\x00!\\8\x98WVO\x1e\xb0u\xb1l\x11",
+ "qi": b"ny\xfb\x87\x05-\xd6\x8dvt\xfd\xe4\x7f$7\xe0\xe3aU(\xa0b[\xc9\xb1PN\xfe\xfd\xf1\x80\xe4?:\x1eA\x8f\x86\xdd\xfd)\xcf\x93C\xac\x14\xbf\xe7\xd9#\x0e\x9e\x14\x15\xd7\xc9\x0b\xf4\xdd<\xe6\xe1,/u\xeb,\x0b\xaaX\xadMo\x86Q\xb00\xd4A\x97\x03\x8d\x86E\x0f;\xcc\xf0\x88\x0f\x90\xd2\xfdc]\xdd\xed\xd8\xfd\xd3\x8d\x99\xc7Uz\xa4\x8d)\x03\xd1\xf7\xb1\xdf\x85\x05Uvsc2W\xa8\x19\x8eS55u",
+ "p": b'\xf8\xa8\x80\x8f\xe9\x11.\xc8\xcc\xbe\x91\xfe\xe8&S\xdea6\x85E\xa7\xe40\xc444qq\xa1\xf3KrI\xb9\xda\x9b\xae\r\xd6\x9e\x18\xa3\xdb\xc5\x81*\xd2\xa2r\xf0Q\x94\x97\x0eMd\x9c\xe0v\xb0"\x13\xac\x91\xcc\x8e\x15\xba\xf7\xc1\x82\xc2k\x83\x9c\n\xbd\x8f$^\xcaz4r3\xd6\xab\xc0p:\xe6\x95\t\x98\x89<\x17\xd7\x9a\x9e\t\xaa\xaf\xefW\xceR\x07v[\xa8\xa22\x99|\x9eM\xe4\x17{\xb3\x12\x86p\xc6\xdc\r\x0f',
+ "q": b"\xf2.Z\xe0pT\x8cE|\xbd\xaar\xa4}\xfaP\xe6\x86\x00,a\xd8@&\xed\xa3.Q\x89\xccbo\xd2\"\\\x97}\x0f\xa1;~{\x08\xb8\xc3\xb5'\x12aL}\xb2\xe9H\x13Z\xaf\x80\xaf\xa3Q\x84l\xee\xc8\xdd\x1c\xe3\xd5\x9a\x1c<\xd4'\x1c\xa3\x14\xa5\x85\xe8b\xe7\xb6\\\xe5\x8d\xbc\xf8u'\xa1\xfb\x03\xd0e!\xdc\xb8\xc6\xacA\x82\x7f\xecZ$\xf8w\xae\x1cO\xbb;)\xf5\x12;\xc6=9q\xe9\x1a\xe4PZ\xe7[",
+ },
+ ),
+ 3072: KeyVaultKey(
+ key_id="https://localhost/keys/key-name/version",
+ jwk={
+ "kty": "RSA",
+ "key_ops": ["encrypt", "decrypt", "wrapKey", "unwrapKey", "sign", "verify"],
+ "n": b"\xd4\x17\x03\t\xed\x10q\x96~\xaf\xf1\xa2\xd6Cb\xbf5\x9a\t\xda\xe0\xfe\x0c\xfa8C\x94\xad\x84\xdb\x90B\xb17\xf4\xb4\x16\x1b\x8d\xdc\xd2\t3\xae\x86\xffP\xfa\x07\x8cm\xb2?ZH\x0e\xb3\xdf\x18y`\x95\xf1\xe0\xf5\xa80O\xfdZ\x07\x00}\xd7g@\xd7\xce\x1a3|\xeb\x80(\xf5\xb9XR\x82`\xd9m\xd3\x9d\xf4\x02BPN\xdf\xfb\xcd\xad\r\xe7mM\xf9'\xdd\x1b9vK\x82!\xb6\x8b\x04\xc3\xc9b\xe1\xe6\x9b\n\xe1\xb6\x82\xf3\x93k\xba\xd0g\x91\x08\x80\x8eR\xd5*\xe0\x85\x1a\xe6\xe7\x94\xb4O]\x07\x14\x92\xc70\x807J\x00i\x19A \x878\xaf%C\x17\xb9\x0e\x01\x9f\x9b\x1a7um\xd1\x1c\xb0\xd9\tyR\xaf\xac\xc80C\xe4Ks-Q#\x07 5\xd0s\xa0c2\x9b-[b\x93\x00\x96\x0bWRN\xde\x0eF\xb6%\xdf\xfc`\xfa[r\xa7\x99\xcd\xfaX\xa1\x17\xd8JA\xbbE>\x1c\xe6\xe8\xf6\x8f\xcdE\x88\xae\xc8zc\xf1\xc2N\x9f+x\xab\x08\xde4Jc\xdc6\xac\xba\x1bh\xaav\xdbR\x96\x1a\xe3\xb2x\xb3x\xc3\xf0\x19\xfav\x0e\x1c\xcc\x8f\xfb\xbe!\xa8\x13\xc8\xa8\xa0\xa3\xcc\xda3?\x05,%\x10_t\x92\x80D\xec&UY1\x91\x9bV\x95\xc9\x80\xeaF\x14\xdb\x87ORp\x0b\xff1Eh\xb7?\xf2\xdbX\xbax\xc3G\xd0\x8fms#\x82]0@N\x17\xd7\xe4i\x11:C\x1b\x0bJ\x11\xda\x19s/\x7f\xbfi`\x8b\xf5\x91\x19d< \xdc\x1f\xef",
+ "e": b"\x01\x00\x01",
+ "d": b"r\xa5\xf9\xe3\x8c\xbd\xfd\xd9\x0f\xa4\xc6\xa7r\xd1\xbcx\x86^=\x83\x8fje\xd3\x81D\xaf\x03Y\xb5b\xf7Z[X1]^\t\xc2\xdb\xdbS\x8f\xbd\xb4\x18\xaf\x00\x13\x9e\\\xe3\xb8G\t\x83\x9cN\xdb\x96%\x98:61s\xe4Y\x9d'\xf9\xd1\x0c\xf6\xe8\xeb\x7f\xa3T?\xec\x02<\xa2\x10N9S\xf7L\xb1\xfc\xd9\xfe\xc4\x95\xdaY\xb8\xe4\xa2[1\x0f\xf0[]\x1bz\x7f\xb4\x01Ir\x10\r`z\xf3\xe7RG\xb1d\x10n\xd1=Z\xb4Oa\x0e5^\x06M\x90\" \xcfk\xcd(,\xb7\xf4\xff\xbf\x83\x17G\xbc\xccf`y\x02\xcc\xd4\x03m\xdcJ\x9c\x8e\xb9B\xday\x13\xa47\x06\x1e\x16\xea\xa8\xb1\x88\xa3\xe4\xbf%QX[\xbb_\xb3\xe2\xa1\xbb~\n\xb8X\xbbv\xe2\x8d`\xb6^\xe2\xdb\x85L\xff\x12|\x8b\xb0\x07\x8d\x97\xcb\xbe\x1e9<\xc1Aq\xc8)%\xd44\xd4\xd7\xbc\x90\x1b\xae\x8f\xf0\xc4\x86O\xc6Y@\xfa\x89\xfb\xcfc\xba,\x83\xe9\x1bR\\\x8b\x9c\xec4\xc7\xcd\xfb$\x9d\xdau\x0cy\xcci\xbd\x04S\x13\xea\xd1\xf0-<\x8c\xd7\xd5\x16\x88f\t\xfa\x9c\x95\xda\xf9\xffePZ\x94{[1\xaa\x9c\xf9\x9c\x12|\xf5\xe2\xb2\xd4\x114Q\x9f\x0c\xed6\x06\x1e\xbb\x9d&Z\xa2\xf5\x1c\x1c\xc1M\xbb\x7f\xaf\xb5~\xec\x13\xef ;\x8a\x85\x0f\x93\xfb+\xafJ\x8e\xb5\xb8\x02\xa8|*7\x8c\x7f\t0\xb8\xc4\xcb\x8f\xbf<~\x958Y\xd1\xdf\xc6\x893\xe5\x17\xcb\xca\xeaSp\x894q",
+ "dp": b"\x824'\xf8\xaf\x99\xbf\xa0\x05\x1a\xca\x1a\xf8\xf3\x8ed\xd5\x8a\xa9/+\\\xf8\xfa\x11\xd7\x00\xd1\t\x95\xbb\x8f\x1e\xdd\x03\xf4[\xa3E\xb3Q\xc1\x9cG\x83t\x00\xe0\xcf}'\xafj\x94sB\xde\xab\xf1J\xcb\x13F\xd3[jf1\xec\xf4\xcdG.#\xe7\xb5)1\xa7{\x8cQ\xc4GI\x81\x8c']\xc9\xb2\x9by\x93\x82\x8cD\xc1\x8e\x12\x04\xef\xb7w5\xd7F\xea\xcf\x93tu\x86kM\xf1\xd5\xdd\x8d\x88j\x9f\x85F\xa7\xf6\xe2\n\xbc\xdey\xcak\xa0(\xb3\x18Ci\xc0\xfd\xaa\xda\x01\xee\xc1>\xb33\xb0\xe9-\xe0B\xe4\xc8\x81\xeb\xd8\x19\xa8G\x05\x93T\xccx\xaa\xe1h\xd4\x8f\xf5\xf3\xdfTb\x1cUkE1\xaap\x89\xe0\xddR<\xfa\xfb1",
+ "dq": b'xs\x81\x0bF\xa1\xf6\x05j\x03V~GD\x1dnHq{\x88b\xfd\xc5p\x07U\x8c\xd6o\x93N\xc8I\xc2\x1d\xc3\x16v\xf5\x0b\x94\xd3\x04b\xb2\xb3rkpO\xdfv,\xd5\x1e\xe6\x0b\x98\xeap\xc9\x84\xbc\xcf\x1f\x8b\x91\xc5tY\xa3w+/^\x15%\x18\x12@\xb5\xb6\xa8\'}\xd7w\xb6\x84\xaaQp\x06o\xce@]p\xa4!\xf5\x1bQ5\xe1=PMkA\x8f\x95\xe7\xdd-\x16\x00p.e\xd0l\xe6\r\xbb\x9cI\xcd\x18i\x9e\xdb\xe6\x86\xec\xad[\xee"\x8a\x12\xb2\xc7\xcc\xdcV\xc9\xce\xbdG\xbf\xa7K \xa8\xec\xf6\xecF\x98\x9cI\xde\x18\x12tjQ2+\xaa_\xef\xf1\xaaWZf\xdd\x0c\x1e\xaf"xq',
+ "qi": b'8\xa1B\xe2@\xae\x10(_z\xfa\x13\xfd\xd6\x85b\xc3\x8d\x0e!\xfe\x18\x8f4\x80d[ p`-\xfc)\xfc\xa2\x93\x18\x1f\xe3=8\x08qxa9\x99i\xc6\x99\x1e\xb9f\x93\xdc"\x10\x1f\x89\x9a\x85\x89\xb0.\x9c\x04=\xd1`L+\xc8ZR\x07\xd7\x96u\\rzH\xc4\x1b\x13\x97\xda\x89\x8eB&\xe3\x07\x8bNv\xb2\xbe\xe2\xb2\x98\xfb4\x8b*\\\x17\xe5\xf2\xb7-9c\xee&r1\xd1\xd4\xcfR\xfa\xa7\x0b\x95\xb0\x15\x15\x1c\x11"\x1fX\xed\x86\xe7\x15\xce\xe6\x87n\x9b\xe2>z*i\xe0\xcc\xa1\xa0z\x18h\xa8R @\xd1M.\x9bG|V\x12T\xdc\xf2o\x8c\xc9\x1b\xd2\xebu\xf8\xf7\xcd\xbf\xea\x99\x0b\xc0tt\x17\xc5\xd0\xa0\x03\x8d',
+ "p": b"\xf6\xd9\xfa\xff\xff0G\x85\xc0\x91\x9e\xa4\x9bT\xb7^+\x99\xd9\xeb-\xe3\x00w\x84\xe5L\xc8S\xb4p\xd6\xe6\xca\xc2U\xe7,b\x83\xd1;\x86\xf8<\xa2]h\x18\xde9S\x05\x10\x83u\xf8\xe1\xb9\xaa\x8a\x80uZ\xf5`\xe0\xden]r_\x96\xa0\x01\x9b\x86\xb716[7\xdf{d^>\to66l\xfb\xc9:yE=\xee\xba\r\xa3\xab60\x91\xf4\xfe\xec#\xd0n\xde\xa6\xa1{o\xca\xb4D\xe7Zw\x9an\xc5\\\x9c\xdf\xc7\x87q#\xcd\xac^\x90\"#\xefwYW\x02\x05\x1e_\xc6\x13X1\x851\xd4\xc9\xc1\x9a\xd7A\x08y\x93\xae\xe9\x07\xc2{\xff\x02\x19\xe0\x12\x8f\xfe\xbcW\xeeY\xa2\x91\x1c\x97\xc8\xcc\xaa\x84\xe1\xbf\x9d\xfc\xbe'",
+ "q": b"\xdb\xf3:~\xd2\x1d\x9e\xd8i\xa1\"\xceK\xd3Z\\\xccW\x81\x9eD\xc6\xcf\xb9\x1a\xbb+.\xb96\x11\xea;\xf6K\xbbD\xd8\xdd\x89\xa2\xb8Y\xf8\xf28b\xf0\x91\xd1\xfa\x14|\xe0\xbd\xdf<&\xc9\xfc\xcd\xdd\xd5\xf1\x82*\x8c\xcf\x95+\xcf\x1a@\xf4\xc0\xd9Q\xcbi[\xcc\xdd\xe7]/+l\x05G\xf2\xce\x0b'\xac\tMrg\x9c\x0b1w\xfaM]\xe0\xa7\x9d?\xb7\xd5\xd3\x92\x84\x81\xf4\xa7\xc0\xc3\xffz`\x91\x96M]\x180\xbfp#k)\x10\x19\xb5\x82\x1dg\xbak\x91\xff\xf8\niZ\xa4@\x03\xa1SB\xc6`e\xa7\xd1\xde\xec\x03\xf7\x94\x9b\x1bTr\x17\n\xee*\xd4s0\x0bc9\x91\x02W\x84\x96\xa7|f@\xdf\xa8Q&\xf4\xf9",
+ },
+ ),
+ 4096: KeyVaultKey(
+ key_id="https://localhost/keys/key-name/version",
+ jwk={
+ "kty": "RSA",
+ "key_ops": ["encrypt", "decrypt", "wrapKey", "unwrapKey", "sign", "verify"],
+ "n": b"\xea\x1e\x81=\n\x98\x81\xdf'T\x9e\xbaH\x19\n\x1d\x8b\x9a\xf1DJ\xe9\x7f6Q\x84o\x9f\x13}5p/\xce\xf7\xc5;\xef\x1a\x88\xb6\nvm\x94\xc1_N\xc4\xbd)\x80Z)\x12\x1e\xa5&\x8a]\xff\xbe\xfc1\x8e\xc8\xfa\x0b\x14\x0c\xeen\xa4S\xc5P\x08\x0e|\x1b\x01/\x98\xe1\xd8A\xa5\x88\x9b\xbd\xb9i\xe83A(p\x9f\xbf3Gp\xc7\xb7\xcc\xf7\x86\x08\xff\x10\x9f)=W\xe8\x8a\xa4H\xb6\x0c\xd44\xe3K\xa7L\x11.\xdd\x1d\xe5\xc9\xcf\xed.4mo\xe2\x03\x8e\xc9\xc2F\xc1\xf3\xdc\x18\\3\xe7\xe2Z\xf8\xccr\xea\xc4\x0c\x82I\x01E\x8e\x875\x87\x8f\xb4r\xd6\x1fZts\x1f\x05\xfa\xa9\xec\xe6z5\xd7\x19V*\xfeY\t$\xeegG\xfdz\x92\x10\xcb\xbb\x19$\xaa\xeb\x0c\t\xd1Nk6\x84c[`\x16\xd2!\x97\x19\xcc\x08\x9f\xc4\x1c\xed\x12k3{\xa1`\x97\x97\xa7\x05:L\x11t\xfa\xc4I\xab\xber\xd0M\xf4Fi\r\xaa-\x9b\xdb\xdaX?\x98w\xf1\xc4O\x01\xd2\x9b\xb0\x1a\x8d`Wmh3h@\x08\rP)\x9bt0t\xad4$\xfc\xd8\xe2\xd8M3\x91\xa2Y\x91\xcb\xeb\x1e\x12\xe2\xc2\x84\xa8Zs\xf3o\xa5\xa7\x00\x14>~<\x81\x10\x8d\x9d\xe4\\%\xc1\xf2\xd8~[\xb7!\xb9\x96]tb\xf7\xddt\x9f\xc1o\xc8\x99\xb3=\xe1+g\x90\xc6\xb9\xe2$wu\xca|\x97v\x13\x980\xa2\xa5\xb7\xe8u\xb1\x05/w\xafg?\xc3\x18\xaf\xfc\xe6;A\x84 %s\xabw\x83\xd7\x7fD\x8a\xca\xab\xb48\x8c\x06\xe6\xf5\xf1\xfb&&\x10h\x18(\x08d\x0ej\xe077W\xb3_\xd7\xa6Ds0\x13\xf2t\x92V\xceV\xce/O\xbeA*b \xb4\xc0\x01s\xa3M\xe1\x0c2 <\xc2\x80\xd9b\xeb>\xa8\xac\xba\x80v\xfd\x86\x12\xe0\xd2\xec\xe5\xcc\xd9\x10C\xbab\xcc\xcb\xf1\xa0\x11\x03\xcauP[~^LjB\x01\xc3\xa65\x9f\xfb\x83\xdb\xe0\xf1\xd2\xe3\xd1\x06\x17N\x90\x04\x02\x0b\xa4f\xc4\x01\xd5\x02\x85\xa7l\xd3\x17\x1c}\"hf\x16\xf2\xfc\xcfl\x9e\x99t\x82{9\x8cH\xa98\xbe\xd1|y\xc6a\xa2\x81#*\x84\xb8N\xb2gM\xd8i\x03\xcf\xaf\xd8v\x80\x04\\\x98\xbf\xe4\xca\x85\xe7\xb9C)\xff\x8bN\x07\xd2\xa9d\xafB\xaesi\x12\xf9\xddx\xeb{|1\xd3tH\xc6\xfc0~\xd8BB\xd0\x0b\xa1\x7fS\x8e\xf5\x88\xc4\xe8\xfa2\xf2\xff~\x07\xfe\x08\xab\x80\xd6,\xdfx>\x898W\x98+\xaf\x84\xf1\xd7\x01q\xbf\xdd\xf9\xee\"M\xa8\xf7\xc5\xf5`\x05\xde\xf9TS\x07\xd6\xc7\x90\xf0+\xa0`r\xc7\x8f\xd9\x0b\x12W\x17\xb9\xa3\x02\xf6\x02K\xfb6[-82\x14^Iz\t\x80.\x13gL\x17\xa3=\x9e\xad\xf7\xder\x85P\xcb\xb9\xcb\xa8\xf4\xee\x87e\x93\xe2\x0f\xf7]m\xb94N\xd3\xc6\xb0\xcc"\x90s\xeb\xf5\xb0\x19',
+ "dq": b'\xed\xdbX\xa5\xbbx\xd0\xb8UI\x80\xc6\xd0k\xe0*\xa4\xa3\x9ahk;\xb3\xc6L\xce\xd3N\x0e\xc3\xce\x00\x9e\xe4-\xc7H=\xd1\x05y\xef\xb1\xe8\xd9\xb9\xdd\x0e\x85#\x95\xa7\xfcyM\x97?\xbas\x03\xc3\x1a1\xee\xd7-\x841\xc5\x1e\xc5.R\xe2\x86\xa0\xbcM\xcd\xcalt \x06#\r\xfc\xe2\xb9\xd6\x91\xcbzGv\x8eD\xdd\xb7\xf8\xe7\\7\xaf"\xf9q\x9fK\x17u\xd2S1\xef\xe5\xb4\xd9u\x0f;\x81\xb4\x88<\x9bRj\xb3\xec\x1f\xef\x7f\x01#J\xf2iO"\x8e\xe9\xa7\xff\x93\xaa,Z\x07\x8f}\xabS\\\x97a\xa2\x1f\xde\xcb\xc2\x8f^tW\x00L\xa51\nD\xc79y\x11\x11\x03\xa5Vy8R\xf3IZ\xa4\xda\xa8\xa2\x16\x03y#\x1b\xe2|o<\x04\xdeZ\xa2j#/\xdd\xe2\xc13P\xe0\x94;\x97}\x83\x0c\xe7[p\x143\x08\xf0\xd4FH\xa8=(\xd5\x1b\xd1\xbb\xdeb\xd1]B\xcf\xbe\xb8=iS o\x8fF\xa6V\x89^\xf5\x00\x99',
+ "qi": b'.\x988y\xe9:1Q\x06\x89\xb3\x85\xdc\xfd\xe9]\xb1\xd0\xadb\xef\xbb\x8d\x18.\xa1\xc9\x92m\xe2b\x97\xea\xcf\xd0\xcc\xc8f\x9e\x9a\x9f\xae\x05\x16\x8dD?\xd3\xed}\xfcMA\x97x\xc4\xf5\xa1i\x14\xda\xfcr\x7f\xddN\xefT\x1a\xe5\xf3t\xa4z\x1f\xef\xf8\x8d\x1a7sJ\xfc\xfc\x19\x99Z\x1aR\x9a\xdch\x91,qo\x13\xc3\xf3\xd2\xe13O\x12\xa7t\xbfk\xa2\x84\xd2x\xec\x18M\n\xc6\xf7;\x9a!:"\xa2\nmtsV\xe2\xb8\xdf\xdfzI\xcf7g\xa9\xe7h\x10V%\x9f\x88x*`Gf\xe99\x86\xa8\x8e\x1e\xf2\xf7\xeb\xfd\xf0\xca\x84\xa1?\x8f\x18\xbb\x07{DR+\x86\xdeA\x13V\x1ad`\x05W\x88\x98\x86\xb2Ti25\xfa\xb9\x81?g\x13\xd4\xbb\xbe\xde\xef\x04\'\xd5\xef\xf7!\xb6\x06\n\x9b\xc7d\x90Wk\xb2\x82e3\xa8\t\xc2a\xb5\x1e\xcf\xd6rWa" \xd1\xde\xa8"\x1aBB\x1a0\xaf\x90bjv\xbe\xa9\x83\xfdk$\xb5',
+ "p": b"\xfa\xf4[T\xb5<\x06t\xfaN\x96!2\x12,\x87\x82$y\xadHsBX\xe9\xc7\xed\x8a6\xc0\x14\x87\xed\x8a\xd0\xad\x86\x05\xc1or^\x87\xb2\xcc\xa2\x08_\xed\xe2N\x91\xa0#\xba\xaa\x03\xba\xffv\xad\x9az\xcej\x8et\x96S\x1b\xbd\x93\x99\x94Q\xac\xdd4\x07\x9b\x17x8\xaf\x9b\xdd\xadM6\x1fk\xfa \xdd\xdf\xcbp]b|f6n\xd0U\xc0\xee0\x94\xf6!\x93}\xa3\nE\xa5\xc3\x86\xff\x82YO\x0c%\xfe\xeb_T\xa8\x8e\xd3\xe3\x80\x8d\x06\xca\xdf\xf1J5\xf1\x87\xc7g\x17\xe3\xba\xd24\x0b\xa6\xd6\x1bR\x9d_!$\x8c \xc0\xcdH\x16y\xb9\xdd\x9a\x9c!\xc9'SU\x91\x9a\xd1\x8b\xb9n\xb2\xaa\xd15JO\xf0\x08c\xe0`!Y(\xf8K{\xbb\x8d\xdf\x05\xaac\xc7\xbaeo\x1d\xb4\x11\x01r\xc8`'\x02\x92f\xc1^\xc5\xf7H\r\xfd\xd2.A\xb8&\xd7*>\xe8[;\xd5\xa0Z*\x8b^{\xc7\x8bw\x8d\x1c\xbe6\xd4}\x12\xd5+",
+ "q": b'\xee\xd3\x7fo\xff\r\x91<}\x9f\xe0\x8f\xc6\x06\xad\x80\x1em\xbe\xa6_\xdd[%Z?\x8b\xe4\xb1\xcd\xea\xec\x9b\xd2\x19\'\x7f\xe8\x80\xf0\xc40A\xcc\xa8} N\xd3\xcbXI\xf6\xb1\xa7\xf7lp\xf3\xaaq\x8d\x80\x83\x10\xc8\xbb)\x06\xc8\x8f\xea\x11\\\xd2\x99C\x95\x7f\xd9\x92w)\xd4\x90\x1dNF\xbd\xf3\xed"\x84\xcej\x81\xfb\xf9\xd2qv\xc9\x152K\xb8\xf7\x10|\xc7\xeb\xdc\xf0\xb9s\x0f\xc0\x0c\xf7T\xb7B\xa4\x05\xbb\x124\xde\xc0\xec\x88\xb5"qI\x91=\x0cso\\R\xc8\x9a\xe3\xff\xc3\xc5\xdb\xb9\xf8\xbdL\xfc\x9c;\xf3\x90\xa1\xa2\xf3\x08\xb5\x07\x19\xceZ@\xea\xe2\x9acO\r\x1f\x1fL\x1c#?\x0b\x0e\x9d\xbd\x97/\xb5\xb0\x90\x84>s\xccs\xa9R\x988\x06\x18\xaf\r\xfa=\xa3\xcf\xa4\x90o\x95\x95\xbd\x1c\xee\xac*\xc2\xad\xeec4THb\xcb{\xc0\x08Nj>?\x16%\x9d\x0eC\x83\xf7\xc8\x80\x14\x91l\x19p\x17\xb8C\xf3\xf4\xb8\x07\xfe\xa6)',
+ },
+ ),
+}
diff --git a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_local_validity_period_enforcement.yaml b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_local_validity_period_enforcement.yaml
index 5f4889d2e452..da7e35b7bcec 100644
--- a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_local_validity_period_enforcement.yaml
+++ b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_local_validity_period_enforcement.yaml
@@ -13,7 +13,7 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
+ - azsdk-python-keyvault-keys/4.2.0b2 Python/3.5.4 (Windows-10-10.0.19041-SP0)
method: POST
uri: https://vaultname.vault.azure.net/keys/rsa-not-yet-valid/create?api-version=7.1
response:
@@ -28,7 +28,7 @@ interactions:
content-type:
- application/json; charset=utf-8
date:
- - Wed, 29 Jul 2020 16:12:00 GMT
+ - Wed, 08 Jul 2020 23:56:23 GMT
expires:
- '-1'
pragma:
@@ -43,11 +43,11 @@ interactions:
x-content-type-options:
- nosniff
x-ms-keyvault-network-info:
- - conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
+ - conn_type=Ipv4;addr=24.17.201.78;act_addr_fam=InterNetwork;
x-ms-keyvault-region:
- westus
x-ms-keyvault-service-version:
- - 1.1.10.0
+ - 1.1.8.0
x-powered-by:
- ASP.NET
status:
@@ -67,12 +67,12 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
+ - azsdk-python-keyvault-keys/4.2.0b2 Python/3.5.4 (Windows-10-10.0.19041-SP0)
method: POST
uri: https://vaultname.vault.azure.net/keys/rsa-not-yet-valid/create?api-version=7.1
response:
body:
- string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/rsa-not-yet-valid/0aaab98564734fcdbe66073de241c33b","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"7x35JTvGBCTQP2XUsojh2QMLZ98Qq7C4499vFHVazyQwT3zw4joAmaOrHpxtirVuZKo1ifnBHPsr-vJbZlzWbWzVmkuhgWIt3xQY7NvQpZAG-5zUk9wQxLWuyOr1jaVQzRjpxfRqsnilnTrCjmJz7LMxT02iy8pht39aKQ_qAhDceERqQSgBZN3KpqhgUiWZ37gyXsEjiiGAVTBNVhzUyd68q04yQoDv3DeKajCKoHcxCEwf7N_WSdVlBKJhl2NNR18Hgn0YOJz3gK_uL-0HPwLFg_TdgTqPBOwn1KmZuzbL57QSoiYS10EUrFtOKidD3pRUg0jci0b5e9Q9GXGX2w","e":"AQAB"},"attributes":{"enabled":true,"nbf":32503680000,"created":1596039122,"updated":1596039122,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
+ string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/rsa-not-yet-valid/7ea0933149864a4b963beaf5fd82c0f3","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"jzPKCMGd6gllD7wMFu6taNREuGaiP0D3p-OgXD6OJhrSurq4e2t8QgTU6oHsWCScEOpsOJ4PgSehSULfRYUeGOOd8jXWMqzo2INHhQcF1izccfvSK2pBlAlsWm5WzVIum_plFCxXapucrttrYuzsbzwdUO0i4dPevlQNYCQAuu08qMwoQYpC78A6JZ4cKU_nBP3rvMfMoJ88sHl7xUE9CjhauOjEUfeQgSq9DjmSgHCWSYRZgHIipW3UUymlMClfCGVIqIcKfKnwV03aqb6w76mF0u7-PkS7yfx7Uf9T8xxUYdbp5qRwhE3KHWpAkOwwjaQZZU1YHvb5btUCUcfrGw","e":"AQAB"},"attributes":{"enabled":true,"nbf":32503680000,"created":1594252583,"updated":1594252583,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
headers:
cache-control:
- no-cache
@@ -81,7 +81,7 @@ interactions:
content-type:
- application/json; charset=utf-8
date:
- - Wed, 29 Jul 2020 16:12:01 GMT
+ - Wed, 08 Jul 2020 23:56:24 GMT
expires:
- '-1'
pragma:
@@ -93,61 +93,11 @@ interactions:
x-content-type-options:
- nosniff
x-ms-keyvault-network-info:
- - conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
+ - conn_type=Ipv4;addr=24.17.201.78;act_addr_fam=InterNetwork;
x-ms-keyvault-region:
- westus
x-ms-keyvault-service-version:
- - 1.1.10.0
- x-powered-by:
- - ASP.NET
- status:
- code: 200
- message: OK
-- request:
- body: '{"kty": "EC", "attributes": {"nbf": 32503680000}}'
- headers:
- Accept:
- - application/json
- Accept-Encoding:
- - gzip, deflate
- Connection:
- - keep-alive
- Content-Length:
- - '49'
- Content-Type:
- - application/json
- User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
- method: POST
- uri: https://vaultname.vault.azure.net/keys/ec-not-yet-valid/create?api-version=7.1
- response:
- body:
- string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/ec-not-yet-valid/a9488190f47643bb88b3079d546a47de","kty":"EC","key_ops":["sign","verify"],"crv":"P-256","x":"dbcDNoxjBhTAWa2yRE6t55WO02WswmuS62kUQaHQDvQ","y":"vKqwWNFGsMjZ_b8RM4tZBdEEIyErmB9e4buTmh9tCIU"},"attributes":{"enabled":true,"nbf":32503680000,"created":1596039122,"updated":1596039122,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
- headers:
- cache-control:
- - no-cache
- content-length:
- - '425'
- content-type:
- - application/json; charset=utf-8
- date:
- - Wed, 29 Jul 2020 16:12:01 GMT
- expires:
- - '-1'
- pragma:
- - no-cache
- strict-transport-security:
- - max-age=31536000;includeSubDomains
- x-aspnet-version:
- - 4.0.30319
- x-content-type-options:
- - nosniff
- x-ms-keyvault-network-info:
- - conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
- x-ms-keyvault-region:
- - westus
- x-ms-keyvault-service-version:
- - 1.1.10.0
+ - 1.1.8.0
x-powered-by:
- ASP.NET
status:
@@ -167,12 +117,12 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
+ - azsdk-python-keyvault-keys/4.2.0b2 Python/3.5.4 (Windows-10-10.0.19041-SP0)
method: POST
uri: https://vaultname.vault.azure.net/keys/rsa-expired/create?api-version=7.1
response:
body:
- string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/rsa-expired/a9d9ebdcaa6e463cb81dcbac014791bf","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"xjCQJAlehYTUozcODbTjSgsfp2DzXDPwAPqgawNzJx7WSRnAqWYXtPI_oMyoSu2e3zPqQHILoHQTzRtMmt0kyKC1N6Rmxi-XPC20Tw39Lx4A-P0izw4GUgRAyWTWK4QmSwLEFLQYQS0tQtZLIiOuvHX-lvOz6joL2KFrXNnv56ENs9pZlnJ5gOznjt-eFVfZA1zo0lHjYbNtnFWhd9TuKJnXrRYJDPobg6xjoJSNPg6U_brV01fO6uOceK4sRlnmR7quItPMzwVG51y7Ysl4Y97yZsyev2NtOF56PMYIf-Ko5t5OUIMvxV__131NnRNItcX8iZny-Pap1W3pKUMWbQ","e":"AQAB"},"attributes":{"enabled":true,"exp":946684800,"created":1596039122,"updated":1596039122,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
+ string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/rsa-expired/e635d043959b47919761cd2afa48d8ae","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"j6jR55imX613PlsKicrY79HVu9MptCV6uAZJzdb-z7-pGDwyxSWRx0MDDcyKEWPj7D0ccXa6GscQi3WmhgaOa6R9p6-0XzOcFqJjIguQJ1Qa4-L-yUb2DQA6nSX6-O5qmrHR0VdmbM0SZSDSktjqqTi13jMiaj41bEQcYbbqNm35j_osMk-h5UzracaVOgm-wyW4NrCVCddyEZM4fumt_e0cDBC9Ffz7XcprCFaZ3m6Jn0IzG3X-mr6EubLNAZ4hvIalWacJQo4Clh2WAIZEb-9KvbXBO6l8ufac4iosDlRtdP7BgTkj5Opx2RIgOYyAFX6Zld9hY2DzvimRopUv_w","e":"AQAB"},"attributes":{"enabled":true,"exp":946684800,"created":1594252584,"updated":1594252584,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
headers:
cache-control:
- no-cache
@@ -181,7 +131,7 @@ interactions:
content-type:
- application/json; charset=utf-8
date:
- - Wed, 29 Jul 2020 16:12:02 GMT
+ - Wed, 08 Jul 2020 23:56:24 GMT
expires:
- '-1'
pragma:
@@ -193,61 +143,11 @@ interactions:
x-content-type-options:
- nosniff
x-ms-keyvault-network-info:
- - conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
+ - conn_type=Ipv4;addr=24.17.201.78;act_addr_fam=InterNetwork;
x-ms-keyvault-region:
- westus
x-ms-keyvault-service-version:
- - 1.1.10.0
- x-powered-by:
- - ASP.NET
- status:
- code: 200
- message: OK
-- request:
- body: '{"kty": "EC", "attributes": {"exp": 946684800}}'
- headers:
- Accept:
- - application/json
- Accept-Encoding:
- - gzip, deflate
- Connection:
- - keep-alive
- Content-Length:
- - '47'
- Content-Type:
- - application/json
- User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
- method: POST
- uri: https://vaultname.vault.azure.net/keys/ec-expired/create?api-version=7.1
- response:
- body:
- string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/ec-expired/77f6482d7a364e7ebddb1faa115c7812","kty":"EC","key_ops":["sign","verify"],"crv":"P-256","x":"6ZzntLSyQUMZryICePHIv6eKxOo0ifP3Oza-DImTF30","y":"ovJC2ZXaTrjU6eP2k9qkLMXJoCnmlJzf0gT-9Fv1ed0"},"attributes":{"enabled":true,"exp":946684800,"created":1596039123,"updated":1596039123,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
- headers:
- cache-control:
- - no-cache
- content-length:
- - '417'
- content-type:
- - application/json; charset=utf-8
- date:
- - Wed, 29 Jul 2020 16:12:02 GMT
- expires:
- - '-1'
- pragma:
- - no-cache
- strict-transport-security:
- - max-age=31536000;includeSubDomains
- x-aspnet-version:
- - 4.0.30319
- x-content-type-options:
- - nosniff
- x-ms-keyvault-network-info:
- - conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
- x-ms-keyvault-region:
- - westus
- x-ms-keyvault-service-version:
- - 1.1.10.0
+ - 1.1.8.0
x-powered-by:
- ASP.NET
status:
@@ -267,12 +167,12 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
+ - azsdk-python-keyvault-keys/4.2.0b2 Python/3.5.4 (Windows-10-10.0.19041-SP0)
method: POST
uri: https://vaultname.vault.azure.net/keys/rsa-valid/create?api-version=7.1
response:
body:
- string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/rsa-valid/aed3e4a2ed634e6f8a0c5a4484cf01cf","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"naE2briqe_cgB4RYvFD9qX1oSsSAL85-IJoaSbXNS6ilpOpSGSXp1dFPwAY6g3PlpFpsdCrXu8nCsf5ZFamycYi_YGkC6gxAHDq_qIzkLmlCOkuqiSuMQpREboL3XOop78Lu7rFBu7KDrM6UgyT8SnDPCs02cu_vl33zcy0wL5AomfPf1gvo8tgK1N8megrQ0qKZ1tez_cH291Coifn-6r6m9SZ7wjMsJ3Gmg1LO1u6-rSMGTydBPd3GVGdXF6ED7_HuXH0vZGIZPdNcaz6oPfhGsuA0nX3DZiCEZQF8ourQp7BV52mJ1kFs4nIgCubwx0vbEbjnhU-SG7okRPNwEQ","e":"AQAB"},"attributes":{"enabled":true,"nbf":32503680000,"exp":32535216000,"created":1596039123,"updated":1596039123,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
+ string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/rsa-valid/aa5a5a00dd6544a0b6b6fcce751f09e1","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"qRYTtMlU78wP2vgWJ8mzQUQU2iiQ9NIw9omBJUjO4IJ0sAZo0YoQ6NUv-xOUadQ6JDMQJwAUbnh2fgp8xLU9_4grrX4bNAcJ9AroTveOaDxWh1llesKO2tBPA9gusX7hJ5PMJ7HKaYNqkFxSPTzqe64I28b4ANc6RJy345GwPldofOIAg0d7jBEwgT8K4rU5smgUEkhvX3GTKaovhhQMP69EzuqdMSck6MDmdkIhfqg7u3Y779RD7TASFaj2JE83ki4mizDrVr_WfPDLtxJLbh12G1fI7yauVu6La_1MGumJLOy581tFhse7EFIbKYZR3DmAFczETUhLrQMrtRU3rQ","e":"AQAB"},"attributes":{"enabled":true,"nbf":32503680000,"exp":32535216000,"created":1594252584,"updated":1594252584,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
headers:
cache-control:
- no-cache
@@ -281,57 +181,7 @@ interactions:
content-type:
- application/json; charset=utf-8
date:
- - Wed, 29 Jul 2020 16:12:02 GMT
- expires:
- - '-1'
- pragma:
- - no-cache
- strict-transport-security:
- - max-age=31536000;includeSubDomains
- x-aspnet-version:
- - 4.0.30319
- x-content-type-options:
- - nosniff
- x-ms-keyvault-network-info:
- - conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
- x-ms-keyvault-region:
- - westus
- x-ms-keyvault-service-version:
- - 1.1.10.0
- x-powered-by:
- - ASP.NET
- status:
- code: 200
- message: OK
-- request:
- body: '{"kty": "EC", "attributes": {"nbf": 32503680000, "exp": 32535216000}}'
- headers:
- Accept:
- - application/json
- Accept-Encoding:
- - gzip, deflate
- Connection:
- - keep-alive
- Content-Length:
- - '69'
- Content-Type:
- - application/json
- User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
- method: POST
- uri: https://vaultname.vault.azure.net/keys/ec-valid/create?api-version=7.1
- response:
- body:
- string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/ec-valid/ef5fab0fdcd74cb4adabb6b3b8741937","kty":"EC","key_ops":["sign","verify"],"crv":"P-256","x":"0jeZ6wM0UwWXDhXDc-nQtXSunbURtvm8w8aBlF70t58","y":"YRoP3FMyUNScK-RyNkHu2vDdCjTD89O-vir186q-ikQ"},"attributes":{"enabled":true,"nbf":32503680000,"exp":32535216000,"created":1596039123,"updated":1596039123,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
- headers:
- cache-control:
- - no-cache
- content-length:
- - '435'
- content-type:
- - application/json; charset=utf-8
- date:
- - Wed, 29 Jul 2020 16:12:02 GMT
+ - Wed, 08 Jul 2020 23:56:24 GMT
expires:
- '-1'
pragma:
@@ -343,11 +193,11 @@ interactions:
x-content-type-options:
- nosniff
x-ms-keyvault-network-info:
- - conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
+ - conn_type=Ipv4;addr=24.17.201.78;act_addr_fam=InterNetwork;
x-ms-keyvault-region:
- westus
x-ms-keyvault-service-version:
- - 1.1.10.0
+ - 1.1.8.0
x-powered-by:
- ASP.NET
status:
diff --git a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_local_validity_period_enforcement.yaml b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_local_validity_period_enforcement.yaml
index 75f0df28bd17..6b51c3912e90 100644
--- a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_local_validity_period_enforcement.yaml
+++ b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_local_validity_period_enforcement.yaml
@@ -9,7 +9,7 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
+ - azsdk-python-keyvault-keys/4.2.0b2 Python/3.5.4 (Windows-10-10.0.19041-SP0)
method: POST
uri: https://vaultname.vault.azure.net/keys/rsa-not-yet-valid/create?api-version=7.1
response:
@@ -20,7 +20,7 @@ interactions:
cache-control: no-cache
content-length: '87'
content-type: application/json; charset=utf-8
- date: Wed, 29 Jul 2020 16:12:43 GMT
+ date: Wed, 08 Jul 2020 23:56:24 GMT
expires: '-1'
pragma: no-cache
strict-transport-security: max-age=31536000;includeSubDomains
@@ -28,14 +28,14 @@ interactions:
resource="https://vault.azure.net"
x-aspnet-version: 4.0.30319
x-content-type-options: nosniff
- x-ms-keyvault-network-info: conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
+ x-ms-keyvault-network-info: conn_type=Ipv4;addr=24.17.201.78;act_addr_fam=InterNetwork;
x-ms-keyvault-region: westus
- x-ms-keyvault-service-version: 1.1.10.0
+ x-ms-keyvault-service-version: 1.1.8.0
x-powered-by: ASP.NET
status:
code: 401
message: Unauthorized
- url: https://pemiijtsjrmvajb4aefm7sap.vault.azure.net/keys/rsa-not-yet-valid/create?api-version=7.1
+ url: https://pb3ak4szgezegnx3inn6gur4.vault.azure.net/keys/rsa-not-yet-valid/create?api-version=7.1-preview
- request:
body: '{"kty": "RSA", "attributes": {"nbf": 32503680000}}'
headers:
@@ -46,64 +46,30 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
+ - azsdk-python-keyvault-keys/4.2.0b2 Python/3.5.4 (Windows-10-10.0.19041-SP0)
method: POST
uri: https://vaultname.vault.azure.net/keys/rsa-not-yet-valid/create?api-version=7.1
response:
body:
- string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/rsa-not-yet-valid/887f8910cff94b61969b9808a4790383","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"lHRf_JqnhLO-D3pNSQd7bO_vuEeZZFxihwkOtoztcEpcuWREGtSzVbM0s0EzlNegizM1tbXSTwnz_N2oUfoY1PtrDPSahUAkc8IRkha_T5Mgl5Hd2dw99n0U3Zw6CzoiWyL0flJJ6xV-gTB1JR6sizaXXSqwJbapyH2gjCgOcu1Ede5kbCdyyG2VM0FyZD_SBc-QKkIrQv9X4MSREPtJSKPhd9ab5S5o313jZ8K2IEaRpBouRRlt0EsSaO9o5lHWcoYb4lMy31YFzIp_HYL8m7wIR4HkFEiWCS00EypJHlKqWs5pQcRrk18HQQ-J_LrUI4fo3ugn8XIBWfFd44LZZw","e":"AQAB"},"attributes":{"enabled":true,"nbf":32503680000,"created":1596039164,"updated":1596039164,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
+ string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/rsa-not-yet-valid/f33f7d6a308d47dc9df59da4a2600ed9","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"t2WQni7-1EvYosrt66t5l2ksuslLKcffo2ku5IbvMlgiTVOotmCwV6ifKXKlFskOXC_RLk97dZcNYzYksGYJsbVb4uXH5rEYBerHHaJlEGIaKsYw2RM-409EKMyS8e6FHllx_Llcu07bHiNKuvoT--KQcdqflymGrdYHWFueEy8q2Cpbx1WmXNd7L0ac9kdYcvB6j0YL1UMjSKYI13PUpZRADmTEGag63VBucfsxqedVqjEyTqLxyTtwcSsYyBPen8frnlICOOp-_QG_ZNokZk6CFZ6_Rpq891AasXQK-CSakINgdfz6SJtKwecrCknDPi2rFkT7TLgDdc_a9SScsw","e":"AQAB"},"attributes":{"enabled":true,"nbf":32503680000,"created":1594252584,"updated":1594252584,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
headers:
cache-control: no-cache
content-length: '715'
content-type: application/json; charset=utf-8
- date: Wed, 29 Jul 2020 16:12:44 GMT
+ date: Wed, 08 Jul 2020 23:56:25 GMT
expires: '-1'
pragma: no-cache
strict-transport-security: max-age=31536000;includeSubDomains
x-aspnet-version: 4.0.30319
x-content-type-options: nosniff
- x-ms-keyvault-network-info: conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
+ x-ms-keyvault-network-info: conn_type=Ipv4;addr=24.17.201.78;act_addr_fam=InterNetwork;
x-ms-keyvault-region: westus
- x-ms-keyvault-service-version: 1.1.10.0
+ x-ms-keyvault-service-version: 1.1.8.0
x-powered-by: ASP.NET
status:
code: 200
message: OK
- url: https://pemiijtsjrmvajb4aefm7sap.vault.azure.net/keys/rsa-not-yet-valid/create?api-version=7.1
-- request:
- body: '{"kty": "EC", "attributes": {"nbf": 32503680000}}'
- headers:
- Accept:
- - application/json
- Content-Length:
- - '49'
- Content-Type:
- - application/json
- User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
- method: POST
- uri: https://vaultname.vault.azure.net/keys/ec-not-yet-valid/create?api-version=7.1
- response:
- body:
- string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/ec-not-yet-valid/91659fe30ad6420b8be81f61797b5b21","kty":"EC","key_ops":["sign","verify"],"crv":"P-256","x":"_EsN6wNkHLRqxqfIzDrooYzU32NgILylQ3bC525lD1M","y":"uJlcAWWusZiCWbKmDHgrj3z2sUQdnz9yHdmJr_jnMXY"},"attributes":{"enabled":true,"nbf":32503680000,"created":1596039164,"updated":1596039164,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
- headers:
- cache-control: no-cache
- content-length: '425'
- content-type: application/json; charset=utf-8
- date: Wed, 29 Jul 2020 16:12:44 GMT
- expires: '-1'
- pragma: no-cache
- strict-transport-security: max-age=31536000;includeSubDomains
- x-aspnet-version: 4.0.30319
- x-content-type-options: nosniff
- x-ms-keyvault-network-info: conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
- x-ms-keyvault-region: westus
- x-ms-keyvault-service-version: 1.1.10.0
- x-powered-by: ASP.NET
- status:
- code: 200
- message: OK
- url: https://pemiijtsjrmvajb4aefm7sap.vault.azure.net/keys/ec-not-yet-valid/create?api-version=7.1
+ url: https://pb3ak4szgezegnx3inn6gur4.vault.azure.net/keys/rsa-not-yet-valid/create?api-version=7.1-preview
- request:
body: '{"kty": "RSA", "attributes": {"exp": 946684800}}'
headers:
@@ -114,66 +80,32 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
+ - azsdk-python-keyvault-keys/4.2.0b2 Python/3.5.4 (Windows-10-10.0.19041-SP0)
method: POST
uri: https://vaultname.vault.azure.net/keys/rsa-expired/create?api-version=7.1
response:
body:
- string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/rsa-expired/4c30efab47ac44108fec8e4b530d3d16","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"wDQtd3BFo88BOqd1-miCgJKIi4UnM7mQyaDhfHJaoCe-bWCuHrjgGN4xa0-zYb9eHaXh36n_j_4gXGQJNBRNmfl0wWf3j2EHtsPrfejdQguNU8LHstEwk0tQbyFflcqppyxX_r_6eQA7YsQJ9RPgZ9PXHvkCY_AE8thMuhTs1MRy9ZDHqW0C9-EnMSnALIpqabT4UHuJOheK7uDhF9N5b_AFY3xDSS2tPiYyTWQUiX8uJzY8kNkM2wcR960GwYEvS0RJ0vVEovFtodz5vxCJehx-K3-1QZZxZta4_S_v2XkRuerBziWPyEwk94K5Un95CxoLBMDsubbJJbhwBM_y0Q","e":"AQAB"},"attributes":{"enabled":true,"exp":946684800,"created":1596039165,"updated":1596039165,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
+ string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/rsa-expired/55f375b758a240c695501fd45a69e5e3","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"nvExHxIdr7he4WswsXvsi0DzsILD1LPNlC5MIwoJTNmzseCKXIB8qx_gqQDO2UpWxfMR41EI0-FseNm5hy5AF9ctESXKr5hdmhoOYUjFo0UJYFoS_QR0o4Lo-6oyoiWsKH-AkjfFY9upxS671IgCoJPV3shGvvvL1O_b4TO6gU_nSJHeVOYc8feSL-zoAs7C6jkdZju3W3AMATo22VJFrLlnaohdUQRP71cNS05hoRn6pSpBpHMUxGA9YzmiY9yWpd9rXLUv_RsFJ-lVbW8qPZLr0UFYNW0lyOCJTpsgCGxwCRvpd4F_hCphXWHIS-n1E13RW1roc8pHn4y17_qy0w","e":"AQAB"},"attributes":{"enabled":true,"exp":946684800,"created":1594252585,"updated":1594252585,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
headers:
cache-control: no-cache
content-length: '707'
content-type: application/json; charset=utf-8
- date: Wed, 29 Jul 2020 16:12:44 GMT
- expires: '-1'
- pragma: no-cache
- strict-transport-security: max-age=31536000;includeSubDomains
- x-aspnet-version: 4.0.30319
- x-content-type-options: nosniff
- x-ms-keyvault-network-info: conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
- x-ms-keyvault-region: westus
- x-ms-keyvault-service-version: 1.1.10.0
- x-powered-by: ASP.NET
- status:
- code: 200
- message: OK
- url: https://pemiijtsjrmvajb4aefm7sap.vault.azure.net/keys/rsa-expired/create?api-version=7.1
-- request:
- body: '{"kty": "EC", "attributes": {"exp": 946684800}}'
- headers:
- Accept:
- - application/json
- Content-Length:
- - '47'
- Content-Type:
- - application/json
- User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
- method: POST
- uri: https://vaultname.vault.azure.net/keys/ec-expired/create?api-version=7.1
- response:
- body:
- string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/ec-expired/87a8d53eff1948f1bcbcf108c4598a32","kty":"EC","key_ops":["sign","verify"],"crv":"P-256","x":"DkYr0uvQcqJ51n6W1opTvNlQGit92-ilmw2K9Hu1tPk","y":"Yo4_cJt67ps5yxy95zDBE3p3TnJ2RaMbmWUPEwWgSQg"},"attributes":{"enabled":true,"exp":946684800,"created":1596039165,"updated":1596039165,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
- headers:
- cache-control: no-cache
- content-length: '417'
- content-type: application/json; charset=utf-8
- date: Wed, 29 Jul 2020 16:12:44 GMT
+ date: Wed, 08 Jul 2020 23:56:25 GMT
expires: '-1'
pragma: no-cache
strict-transport-security: max-age=31536000;includeSubDomains
x-aspnet-version: 4.0.30319
x-content-type-options: nosniff
- x-ms-keyvault-network-info: conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
+ x-ms-keyvault-network-info: conn_type=Ipv4;addr=24.17.201.78;act_addr_fam=InterNetwork;
x-ms-keyvault-region: westus
- x-ms-keyvault-service-version: 1.1.10.0
+ x-ms-keyvault-service-version: 1.1.8.0
x-powered-by: ASP.NET
status:
code: 200
message: OK
- url: https://pemiijtsjrmvajb4aefm7sap.vault.azure.net/keys/ec-expired/create?api-version=7.1
+ url: https://pb3ak4szgezegnx3inn6gur4.vault.azure.net/keys/rsa-expired/create?api-version=7.1-preview
- request:
- body: '{"kty": "RSA", "attributes": {"nbf": 32503680000, "exp": 32535216000}}'
+ body: '{"attributes": {"nbf": 32503680000, "exp": 32535216000}, "kty": "RSA"}'
headers:
Accept:
- application/json
@@ -182,62 +114,28 @@ interactions:
Content-Type:
- application/json
User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
+ - azsdk-python-keyvault-keys/4.2.0b2 Python/3.5.4 (Windows-10-10.0.19041-SP0)
method: POST
uri: https://vaultname.vault.azure.net/keys/rsa-valid/create?api-version=7.1
response:
body:
- string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/rsa-valid/0145342e9c98451c9a61c19bf88c6124","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"2FF3_H3_pl5AyZi8veVNoTfyHUrNMTVAOTEzOPorxoslTq5XA3S0uQtkQKdKCCHJLovHYqzatrpBAPmWAge-9vDeH7hV4tQ03JStfZQis7NfyubPBoOGMJaafyj6Ed8Jwh-Ybqvfyq3qFbvqcyCmdAZq0onP0Xzw6noNLQA_lib3L1hzJ7NYjt9DdU9FORxFWQMj2orkCQPkYB0FtXPu8QGOk8yZ12Jh9hlBxDzC-rAKprLn256-qKFn079M9y0qK4_eSb7LDKIiwDkW5Bs51_5M11jdhTmT54k8fADYRErEBGAH9PnaqgfZoOo2ldpvjVsx_4ZhlvooiVvVikgcaQ","e":"AQAB"},"attributes":{"enabled":true,"nbf":32503680000,"exp":32535216000,"created":1596039165,"updated":1596039165,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
+ string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/rsa-valid/c811f6e9c6ce4790a30d8f49efa12521","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"oiDcjX5DwrZqApkOXkz5JA8IPxWolhwaKa6JdjZm-GSE5JdVV3nFk98sR1fPJS757mfuNE7P6JF5BDUvDWWsolRZpfuQtqLoUCtVZvklatx3BkOMhUrCKe6zPRnSaamqt015SCNWMtCT7pBzVCzWkl8B2g2CQkx2zdX4vWrRHpiHOHw4Gc8quvx9w6ZKV7Dae9cGC39N_2_KAwnvuo6wKF9mPKH1Y-_KgmPC7BZFt5Zmh_iwq8wtEgthMS5WSmuF32DxZCey28vyeKDvGVKvsW2UsDGnvekvOQK2FxHsNfjkO8JaodALZXFpxlw3QIs8vvAnwyJMxqS2KglABPkl4w","e":"AQAB"},"attributes":{"enabled":true,"nbf":32503680000,"exp":32535216000,"created":1594252585,"updated":1594252585,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
headers:
cache-control: no-cache
content-length: '725'
content-type: application/json; charset=utf-8
- date: Wed, 29 Jul 2020 16:12:45 GMT
- expires: '-1'
- pragma: no-cache
- strict-transport-security: max-age=31536000;includeSubDomains
- x-aspnet-version: 4.0.30319
- x-content-type-options: nosniff
- x-ms-keyvault-network-info: conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
- x-ms-keyvault-region: westus
- x-ms-keyvault-service-version: 1.1.10.0
- x-powered-by: ASP.NET
- status:
- code: 200
- message: OK
- url: https://pemiijtsjrmvajb4aefm7sap.vault.azure.net/keys/rsa-valid/create?api-version=7.1
-- request:
- body: '{"kty": "EC", "attributes": {"nbf": 32503680000, "exp": 32535216000}}'
- headers:
- Accept:
- - application/json
- Content-Length:
- - '69'
- Content-Type:
- - application/json
- User-Agent:
- - azsdk-python-keyvault-keys/4.2.0b2 Python/3.7.7 (Darwin-17.7.0-x86_64-i386-64bit)
- method: POST
- uri: https://vaultname.vault.azure.net/keys/ec-valid/create?api-version=7.1
- response:
- body:
- string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/ec-valid/dff4e7caf0534caaa4403b09d803b745","kty":"EC","key_ops":["sign","verify"],"crv":"P-256","x":"mfupesvKGlPUhPQVocNTkJ31JABm5sK4hk7khF93aEQ","y":"MzDC4LP4G2sOkLRxa1BgPJiLm9qKiCSJPaoSDWuutbc"},"attributes":{"enabled":true,"nbf":32503680000,"exp":32535216000,"created":1596039165,"updated":1596039165,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}'
- headers:
- cache-control: no-cache
- content-length: '435'
- content-type: application/json; charset=utf-8
- date: Wed, 29 Jul 2020 16:12:45 GMT
+ date: Wed, 08 Jul 2020 23:56:25 GMT
expires: '-1'
pragma: no-cache
strict-transport-security: max-age=31536000;includeSubDomains
x-aspnet-version: 4.0.30319
x-content-type-options: nosniff
- x-ms-keyvault-network-info: conn_type=Ipv4;addr=73.135.72.237;act_addr_fam=InterNetwork;
+ x-ms-keyvault-network-info: conn_type=Ipv4;addr=24.17.201.78;act_addr_fam=InterNetwork;
x-ms-keyvault-region: westus
- x-ms-keyvault-service-version: 1.1.10.0
+ x-ms-keyvault-service-version: 1.1.8.0
x-powered-by: ASP.NET
status:
code: 200
message: OK
- url: https://pemiijtsjrmvajb4aefm7sap.vault.azure.net/keys/ec-valid/create?api-version=7.1
+ url: https://pb3ak4szgezegnx3inn6gur4.vault.azure.net/keys/rsa-valid/create?api-version=7.1-preview
version: 1
diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py
index 74862772d9cd..94addf01a0af 100644
--- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py
+++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py
@@ -254,38 +254,20 @@ def test_operations(key, expected_error_substrings, encrypt_algorithms, wrap_alg
the_year_3000 = datetime(3000, 1, 1, tzinfo=_UTC)
rsa_wrap_algorithms = [algo for algo in KeyWrapAlgorithm if algo.startswith("RSA")]
- rsa_not_yet_valid = key_client.create_rsa_key("rsa-not-yet-valid", not_before=the_year_3000)
- test_operations(rsa_not_yet_valid, [str(the_year_3000)], EncryptionAlgorithm, rsa_wrap_algorithms)
-
- ec_not_yet_valid = key_client.create_ec_key("ec-not-yet-valid", not_before=the_year_3000)
- test_operations(
- ec_not_yet_valid, [str(the_year_3000)], encrypt_algorithms=[], wrap_algorithms=[KeyWrapAlgorithm.aes_256]
- )
+ not_yet_valid_key = key_client.create_rsa_key("rsa-not-yet-valid", not_before=the_year_3000)
+ test_operations(not_yet_valid_key, [str(the_year_3000)], EncryptionAlgorithm, rsa_wrap_algorithms)
# nor should they succeed with a key whose exp has passed
the_year_2000 = datetime(2000, 1, 1, tzinfo=_UTC)
- rsa_expired = key_client.create_rsa_key("rsa-expired", expires_on=the_year_2000)
- test_operations(rsa_expired, [str(the_year_2000)], EncryptionAlgorithm, rsa_wrap_algorithms)
-
- ec_expired = key_client.create_ec_key("ec-expired", expires_on=the_year_2000)
- test_operations(
- ec_expired, [str(the_year_2000)], encrypt_algorithms=[], wrap_algorithms=[KeyWrapAlgorithm.aes_256]
- )
+ expired_key = key_client.create_rsa_key("rsa-expired", expires_on=the_year_2000)
+ test_operations(expired_key, [str(the_year_2000)], EncryptionAlgorithm, rsa_wrap_algorithms)
# when exp and nbf are set, error messages should contain both
the_year_3001 = datetime(3001, 1, 1, tzinfo=_UTC)
- rsa_valid = key_client.create_rsa_key("rsa-valid", not_before=the_year_3000, expires_on=the_year_3001)
- test_operations(rsa_valid, (str(the_year_3000), str(the_year_3001)), EncryptionAlgorithm, rsa_wrap_algorithms)
-
- ec_valid = key_client.create_ec_key("ec-valid", not_before=the_year_3000, expires_on=the_year_3001)
- test_operations(
- ec_valid,
- (str(the_year_3000), str(the_year_3001)),
- encrypt_algorithms=[],
- wrap_algorithms=[KeyWrapAlgorithm.aes_256],
- )
+ valid_key = key_client.create_rsa_key("rsa-valid", not_before=the_year_3000, expires_on=the_year_3001)
+ test_operations(valid_key, (str(the_year_3000), str(the_year_3001)), EncryptionAlgorithm, rsa_wrap_algorithms)
class _CustomHookPolicy(object):
pass
diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py
index 15f9a0847da0..644e3ad90515 100644
--- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py
+++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py
@@ -238,39 +238,21 @@ async def test_operations(key, expected_error_substrings, encrypt_algorithms, wr
the_year_3000 = datetime(3000, 1, 1, tzinfo=_UTC)
rsa_wrap_algorithms = [algo for algo in KeyWrapAlgorithm if algo.startswith("RSA")]
- rsa_not_yet_valid = await key_client.create_rsa_key("rsa-not-yet-valid", not_before=the_year_3000)
- await test_operations(rsa_not_yet_valid, [str(the_year_3000)], EncryptionAlgorithm, rsa_wrap_algorithms)
-
- ec_not_yet_valid = await key_client.create_ec_key("ec-not-yet-valid", not_before=the_year_3000)
- await test_operations(
- ec_not_yet_valid, [str(the_year_3000)], encrypt_algorithms=[], wrap_algorithms=[KeyWrapAlgorithm.aes_256]
- )
+ not_yet_valid_key = await key_client.create_rsa_key("rsa-not-yet-valid", not_before=the_year_3000)
+ await test_operations(not_yet_valid_key, [str(the_year_3000)], EncryptionAlgorithm, rsa_wrap_algorithms)
# nor should they succeed with a key whose exp has passed
the_year_2000 = datetime(2000, 1, 1, tzinfo=_UTC)
- rsa_expired = await key_client.create_rsa_key("rsa-expired", expires_on=the_year_2000)
- await test_operations(rsa_expired, [str(the_year_2000)], EncryptionAlgorithm, rsa_wrap_algorithms)
-
- ec_expired = await key_client.create_ec_key("ec-expired", expires_on=the_year_2000)
- await test_operations(
- ec_expired, [str(the_year_2000)], encrypt_algorithms=[], wrap_algorithms=[KeyWrapAlgorithm.aes_256]
- )
+ expired_key = await key_client.create_rsa_key("rsa-expired", expires_on=the_year_2000)
+ await test_operations(expired_key, [str(the_year_2000)], EncryptionAlgorithm, rsa_wrap_algorithms)
# when exp and nbf are set, error messages should contain both
the_year_3001 = datetime(3001, 1, 1, tzinfo=_UTC)
- rsa_valid = await key_client.create_rsa_key("rsa-valid", not_before=the_year_3000, expires_on=the_year_3001)
- await test_operations(
- rsa_valid, (str(the_year_3000), str(the_year_3001)), EncryptionAlgorithm, rsa_wrap_algorithms
- )
-
- ec_valid = await key_client.create_ec_key("ec-valid", not_before=the_year_3000, expires_on=the_year_3001)
+ valid_key = await key_client.create_rsa_key("rsa-valid", not_before=the_year_3000, expires_on=the_year_3001)
await test_operations(
- ec_valid,
- (str(the_year_3000), str(the_year_3001)),
- encrypt_algorithms=[],
- wrap_algorithms=[KeyWrapAlgorithm.aes_256],
+ valid_key, (str(the_year_3000), str(the_year_3001)), EncryptionAlgorithm, rsa_wrap_algorithms
)
class _CustomHookPolicy(object):
diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_local_crypto.py b/sdk/keyvault/azure-keyvault-keys/tests/test_local_crypto.py
new file mode 100644
index 000000000000..22756d7f8405
--- /dev/null
+++ b/sdk/keyvault/azure-keyvault-keys/tests/test_local_crypto.py
@@ -0,0 +1,172 @@
+# ------------------------------------
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+# ------------------------------------
+import hashlib
+import os
+
+from azure.keyvault.keys import KeyCurveName, KeyVaultKey
+from azure.keyvault.keys.crypto import EncryptionAlgorithm, KeyWrapAlgorithm, SignatureAlgorithm
+from azure.keyvault.keys.crypto._providers import get_local_cryptography_provider
+import pytest
+
+from keys import EC_KEYS, RSA_KEYS
+
+
+@pytest.mark.parametrize(
+ "key,algorithm,hash_function",
+ (
+ (EC_KEYS[KeyCurveName.p_256], SignatureAlgorithm.es256, hashlib.sha256),
+ (EC_KEYS[KeyCurveName.p_256_k], SignatureAlgorithm.es256_k, hashlib.sha256),
+ (EC_KEYS[KeyCurveName.p_384], SignatureAlgorithm.es384, hashlib.sha384),
+ (EC_KEYS[KeyCurveName.p_521], SignatureAlgorithm.es512, hashlib.sha512),
+ ),
+)
+def test_ec_sign_verify(key, algorithm, hash_function):
+ provider = get_local_cryptography_provider(key)
+ digest = hash_function(b"message").digest()
+ sign_result = provider.sign(algorithm, digest)
+ verify_result = provider.verify(sign_result.algorithm, digest, sign_result.signature)
+ assert verify_result.is_valid
+
+
+@pytest.mark.parametrize("key", RSA_KEYS.values())
+@pytest.mark.parametrize("algorithm", (a for a in EncryptionAlgorithm if a.startswith("RSA")))
+def test_rsa_encrypt_decrypt(key, algorithm):
+ provider = get_local_cryptography_provider(key)
+ plaintext = b"plaintext"
+ encrypt_result = provider.encrypt(algorithm, plaintext)
+ decrypt_result = provider.decrypt(encrypt_result.algorithm, encrypt_result.ciphertext)
+ assert decrypt_result.plaintext == plaintext
+
+
+@pytest.mark.parametrize("key", RSA_KEYS.values())
+@pytest.mark.parametrize(
+ "algorithm,hash_function",
+ (
+ (
+ (SignatureAlgorithm.ps256, hashlib.sha256),
+ (SignatureAlgorithm.ps384, hashlib.sha384),
+ (SignatureAlgorithm.ps512, hashlib.sha512),
+ (SignatureAlgorithm.rs256, hashlib.sha256),
+ (SignatureAlgorithm.rs384, hashlib.sha384),
+ (SignatureAlgorithm.rs512, hashlib.sha512),
+ )
+ ),
+)
+def test_rsa_sign_verify(key, algorithm, hash_function):
+ message = b"message"
+ provider = get_local_cryptography_provider(key)
+ digest = hash_function(message).digest()
+ sign_result = provider.sign(algorithm, digest)
+ verify_result = provider.verify(sign_result.algorithm, digest, sign_result.signature)
+ assert verify_result.is_valid
+
+
+@pytest.mark.parametrize("key", RSA_KEYS.values())
+@pytest.mark.parametrize("algorithm", (a for a in KeyWrapAlgorithm if a.startswith("RSA")))
+def test_rsa_wrap_unwrap(key, algorithm):
+ plaintext = b"arbitrary bytes"
+ provider = get_local_cryptography_provider(key)
+
+ wrap_result = provider.wrap_key(algorithm, plaintext)
+ assert wrap_result.key_id == key.id
+
+ unwrap_result = provider.unwrap_key(wrap_result.algorithm, wrap_result.encrypted_key)
+ assert unwrap_result.key == plaintext
+
+
+def test_symmetric_wrap_unwrap():
+ jwk = {"k": os.urandom(32), "kty": "oct", "key_ops": ("unwrapKey", "wrapKey")}
+ key = KeyVaultKey(key_id="http://localhost/keys/key/version", jwk=jwk)
+ provider = get_local_cryptography_provider(key)
+ key_bytes = os.urandom(32)
+
+ wrap_result = provider.wrap_key(KeyWrapAlgorithm.aes_256, key_bytes)
+ assert wrap_result.key_id == key.id
+
+ unwrap_result = provider.unwrap_key(wrap_result.algorithm, wrap_result.encrypted_key)
+ assert unwrap_result.key == key_bytes
+
+
+@pytest.mark.parametrize("key", RSA_KEYS.values())
+@pytest.mark.parametrize(
+ "algorithm",
+ [a for a in KeyWrapAlgorithm if not a.startswith("RSA")] + [a for a in SignatureAlgorithm if a.startswith("ES")],
+)
+def test_unsupported_rsa_operations(key, algorithm):
+ """The crypto provider should raise NotImplementedError when a key doesn't support an operation or algorithm"""
+
+ provider = get_local_cryptography_provider(key)
+ if isinstance(algorithm, EncryptionAlgorithm):
+ with pytest.raises(NotImplementedError):
+ provider.encrypt(algorithm, b"...")
+ with pytest.raises(NotImplementedError):
+ provider.decrypt(algorithm, b"...")
+ if isinstance(algorithm, KeyWrapAlgorithm):
+ with pytest.raises(NotImplementedError):
+ provider.wrap_key(algorithm, b"...")
+ with pytest.raises(NotImplementedError):
+ provider.unwrap_key(algorithm, b"...")
+ elif isinstance(algorithm, SignatureAlgorithm):
+ with pytest.raises(NotImplementedError):
+ provider.sign(algorithm, b"...")
+ with pytest.raises(NotImplementedError):
+ provider.verify(algorithm, b"...", b"...")
+
+
+@pytest.mark.parametrize("key", EC_KEYS.values())
+@pytest.mark.parametrize(
+ "algorithm",
+ [a for a in KeyWrapAlgorithm if a.startswith("RSA")]
+ + [a for a in SignatureAlgorithm if not a.startswith("ES")]
+ + list(EncryptionAlgorithm),
+)
+def test_unsupported_ec_operations(key, algorithm):
+ """The crypto provider should raise NotImplementedError when a key doesn't support an operation or algorithm"""
+
+ provider = get_local_cryptography_provider(key)
+ if isinstance(algorithm, EncryptionAlgorithm):
+ with pytest.raises(NotImplementedError):
+ provider.encrypt(algorithm, b"...")
+ with pytest.raises(NotImplementedError):
+ provider.decrypt(algorithm, b"...")
+ if isinstance(algorithm, KeyWrapAlgorithm):
+ with pytest.raises(NotImplementedError):
+ provider.wrap_key(algorithm, b"...")
+ with pytest.raises(NotImplementedError):
+ provider.unwrap_key(algorithm, b"...")
+ elif isinstance(algorithm, SignatureAlgorithm):
+ with pytest.raises(NotImplementedError):
+ provider.sign(algorithm, b"...")
+ with pytest.raises(NotImplementedError):
+ provider.verify(algorithm, b"...", b"...")
+
+
+@pytest.mark.parametrize(
+ "algorithm",
+ [a for a in KeyWrapAlgorithm if a != KeyWrapAlgorithm.aes_256]
+ + list(SignatureAlgorithm)
+ + list(EncryptionAlgorithm),
+)
+def test_unsupported_symmetric_operations(algorithm):
+ """The crypto provider should raise NotImplementedError when a key doesn't support an operation or algorithm"""
+
+ jwk = {"k": os.urandom(32), "kty": "oct", "key_ops": ("unwrapKey", "wrapKey")}
+ key = KeyVaultKey(key_id="http://localhost/keys/key/version", jwk=jwk)
+ provider = get_local_cryptography_provider(key)
+ if isinstance(algorithm, EncryptionAlgorithm):
+ with pytest.raises(NotImplementedError):
+ provider.encrypt(algorithm, b"...")
+ with pytest.raises(NotImplementedError):
+ provider.decrypt(algorithm, b"...")
+ if isinstance(algorithm, KeyWrapAlgorithm):
+ with pytest.raises(NotImplementedError):
+ provider.wrap_key(algorithm, b"...")
+ with pytest.raises(NotImplementedError):
+ provider.unwrap_key(algorithm, b"...")
+ elif isinstance(algorithm, SignatureAlgorithm):
+ with pytest.raises(NotImplementedError):
+ provider.sign(algorithm, b"...")
+ with pytest.raises(NotImplementedError):
+ provider.verify(algorithm, b"...", b"...")