Microsoft Azure Key Vault Keys client library for Python providing cryptographic key management operations
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Import keys from external sources and export keys with secure release policies. Azure Key Vault supports importing keys in JSON Web Key (JWK) format and provides secure key release mechanisms for data protection and compliance scenarios with attestation-based key release policies.
Import cryptographic key material from external sources into Azure Key Vault.
def import_key(
name: str,
key: JsonWebKey,
*,
hardware_protected: bool = None,
enabled: bool = None,
tags: Dict[str, str] = None,
not_before: datetime = None,
expires_on: datetime = None,
exportable: bool = None,
release_policy: KeyReleasePolicy = None,
**kwargs
) -> KeyVaultKey:
"""
Import a key into the Key Vault.
Parameters:
- name: The name for the imported key
- key: The JSON Web Key to import
- hardware_protected: Whether to store in HSM (True) or software (False)
- enabled: Whether the key should be enabled
- tags: Application-specific metadata
- not_before: Key not valid before this date
- expires_on: Key expiration date
- exportable: Whether the private key can be exported
- release_policy: Policy rules for key release
Returns:
KeyVaultKey: The imported key
Raises:
- InvalidArgumentError: If key format is invalid
- ConflictError: If key with same name already exists
- ForbiddenError: If import permission is not granted
"""from azure.keyvault.keys import KeyClient, JsonWebKey, KeyType, KeyOperation
from azure.identity import DefaultAzureCredential
client = KeyClient("https://vault.vault.azure.net/", DefaultAzureCredential())
# Import RSA key from JWK
rsa_jwk = JsonWebKey(
kty=KeyType.rsa,
n=b"...", # RSA modulus (base64url decoded)
e=b"AQAB", # RSA public exponent (base64url decoded)
d=b"...", # RSA private exponent (base64url decoded)
p=b"...", # RSA prime p
q=b"...", # RSA prime q
dp=b"...", # RSA private key parameter
dq=b"...", # RSA private key parameter
qi=b"...", # RSA private key parameter
key_ops=[KeyOperation.encrypt, KeyOperation.decrypt, KeyOperation.sign, KeyOperation.verify]
)
imported_key = client.import_key(
"imported-rsa-key",
rsa_jwk,
hardware_protected=False,
tags={"source": "external", "imported": "true"}
)
print(f"Imported key: {imported_key.name}")
# Import EC key from JWK
from azure.keyvault.keys import KeyCurveName
ec_jwk = JsonWebKey(
kty=KeyType.ec,
crv=KeyCurveName.p_256,
x=b"...", # X coordinate (base64url decoded)
y=b"...", # Y coordinate (base64url decoded)
d=b"...", # Private key (base64url decoded)
key_ops=[KeyOperation.sign, KeyOperation.verify]
)
imported_ec_key = client.import_key(
"imported-ec-key",
ec_jwk,
hardware_protected=True # Store in HSM
)
# Import symmetric key from JWK
symmetric_jwk = JsonWebKey(
kty=KeyType.oct,
k=b"...", # Symmetric key material (base64url decoded)
key_ops=[KeyOperation.encrypt, KeyOperation.decrypt]
)
imported_symmetric_key = client.import_key(
"imported-symmetric-key",
symmetric_jwk
)Release keys from Azure Key Vault with attestation-based security policies.
def release_key(
name: str,
target_attestation_token: str,
*,
version: str = None,
algorithm: KeyExportEncryptionAlgorithm = None,
nonce: str = None,
**kwargs
) -> ReleaseKeyResult:
"""
Release a key using an attestation token.
Parameters:
- name: The name of the key to release
- target_attestation_token: Attestation token proving target environment security
- version: Specific version of the key (optional, uses latest if omitted)
- algorithm: Encryption algorithm for key export protection
- nonce: Cryptographic nonce for freshness
Returns:
ReleaseKeyResult: The released key wrapped according to policy
Raises:
- ResourceNotFoundError: If the key doesn't exist
- ForbiddenError: If key release policy requirements not met
- InvalidArgumentError: If attestation token is invalid
"""from azure.keyvault.keys import KeyExportEncryptionAlgorithm
# Release a key with attestation token
attestation_token = "eyJ..." # Attestation token from trusted execution environment
release_result = client.release_key(
"confidential-key",
attestation_token,
algorithm=KeyExportEncryptionAlgorithm.rsa_aes_key_wrap_256
)
print(f"Released key value: {release_result.value}")
# The released key is encrypted and can only be decrypted in the attested environmentConfigure and manage key release policies for secure key export.
class KeyReleasePolicy:
"""Policy rules under which a key can be exported."""
encoded_policy: bytes
content_type: str
immutable: boolimport json
import base64
# Define a key release policy
policy_document = {
"version": "1.0",
"attestation": {
"type": "SGX",
"measurement": "abc123...", # Expected enclave measurement
"mrenclave": "def456...", # Expected enclave hash
},
"rules": [
{
"claim": "is-debuggable",
"equals": False
},
{
"claim": "product-id",
"equals": 1
}
]
}
# Encode policy as base64
policy_json = json.dumps(policy_document)
encoded_policy = base64.b64encode(policy_json.encode()).decode()
# Create key release policy
from azure.keyvault.keys import KeyReleasePolicy
release_policy = KeyReleasePolicy(
encoded_policy=encoded_policy.encode(),
content_type="application/json; charset=utf-8"
)
# Create key with release policy
key_with_policy = client.create_rsa_key(
"confidential-key-with-policy",
size=2048,
exportable=True,
release_policy=release_policy
)Common patterns for importing keys from various external sources.
import base64
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
def import_from_pem(client: KeyClient, key_name: str, pem_data: bytes, password: bytes = None):
"""Import a key from PEM format."""
# Load private key from PEM
private_key = serialization.load_pem_private_key(pem_data, password=password)
if isinstance(private_key, rsa.RSAPrivateKey):
# Extract RSA parameters
private_numbers = private_key.private_numbers()
public_numbers = private_numbers.public_numbers
# Create JWK
jwk = JsonWebKey(
kty=KeyType.rsa,
n=public_numbers.n.to_bytes((public_numbers.n.bit_length() + 7) // 8, 'big'),
e=public_numbers.e.to_bytes((public_numbers.e.bit_length() + 7) // 8, 'big'),
d=private_numbers.private_exponent.to_bytes((private_numbers.private_exponent.bit_length() + 7) // 8, 'big'),
p=private_numbers.p.to_bytes((private_numbers.p.bit_length() + 7) // 8, 'big'),
q=private_numbers.q.to_bytes((private_numbers.q.bit_length() + 7) // 8, 'big'),
dp=private_numbers.dmp1.to_bytes((private_numbers.dmp1.bit_length() + 7) // 8, 'big'),
dq=private_numbers.dmq1.to_bytes((private_numbers.dmq1.bit_length() + 7) // 8, 'big'),
qi=private_numbers.iqmp.to_bytes((private_numbers.iqmp.bit_length() + 7) // 8, 'big')
)
# Import to Key Vault
return client.import_key(key_name, jwk)
else:
raise ValueError("Only RSA keys are supported in this example")
# Usage
with open("private-key.pem", "rb") as f:
pem_data = f.read()
imported_key = import_from_pem(client, "imported-from-pem", pem_data)from cryptography.hazmat.primitives import serialization
def import_from_pkcs12(client: KeyClient, key_name: str, p12_data: bytes, password: bytes):
"""Import a key from PKCS#12 format."""
# Load PKCS#12
private_key, certificate, additional_certificates = serialization.pkcs12.load_key_and_certificates(
p12_data, password
)
# Convert to JWK and import (similar to PEM example above)
# ... implementation details ...
return client.import_key(key_name, jwk, tags={"format": "pkcs12"})class JsonWebKey:
"""JSON Web Key representation as defined in RFC 7517."""
kid: str # Key identifier
kty: KeyType # Key type
key_ops: List[KeyOperation] # Allowed operations
# RSA parameters
n: bytes # RSA modulus
e: bytes # RSA public exponent
d: bytes # RSA private exponent
dp: bytes # RSA private key parameter
dq: bytes # RSA private key parameter
qi: bytes # RSA private key parameter
p: bytes # RSA secret prime
q: bytes # RSA secret prime
# EC parameters
crv: KeyCurveName # Elliptic curve name
x: bytes # X component of EC public key
y: bytes # Y component of EC public key
d: bytes # D component of EC private key
# Symmetric key parameters
k: bytes # Symmetric key material
# HSM parameters
t: bytes # HSM Token for Bring Your Own Key
class ReleaseKeyResult:
"""Result of a key release operation."""
value: str # The released key material (encrypted according to policy)
class KeyReleasePolicy:
"""Policy rules under which a key can be exported."""
encoded_policy: bytes # Base64-encoded policy document
content_type: str # MIME type of policy (e.g., "application/json; charset=utf-8")
immutable: bool # Whether policy can be changed after creation
class KeyExportEncryptionAlgorithm(str, Enum):
"""Supported algorithms for protecting exported key material."""
ckm_rsa_aes_key_wrap = "CKM_RSA_AES_KEY_WRAP" # CKM RSA AES Key Wrap
rsa_aes_key_wrap_256 = "RSA_AES_KEY_WRAP_256" # RSA AES Key Wrap with SHA-256
rsa_aes_key_wrap_384 = "RSA_AES_KEY_WRAP_384" # RSA AES Key Wrap with SHA-384# Example secure import pattern
def secure_import_key(client: KeyClient, key_name: str, jwk: JsonWebKey):
"""Securely import a key with validation and audit."""
# Validate key before import
if not jwk.kty or not jwk.key_ops:
raise ValueError("Key type and operations must be specified")
# Import with restrictive settings
imported_key = client.import_key(
key_name,
jwk,
enabled=False, # Start disabled for review
tags={
"imported": "true",
"import_date": datetime.utcnow().isoformat(),
"requires_review": "true"
}
)
# Log the import
print(f"Key {key_name} imported successfully, requires review before enabling")
return imported_keyInstall with Tessl CLI
npx tessl i tessl/pypi-azure-keyvault-keys