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
Comprehensive cryptographic operations using Azure Key Vault keys including encryption, decryption, digital signing, signature verification, and key wrapping. The CryptographyClient provides a high-level interface for performing cryptographic operations with keys stored in Azure Key Vault, integrating seamlessly with Python's cryptography library.
Encrypt and decrypt data using various symmetric and asymmetric algorithms.
def encrypt(
algorithm: EncryptionAlgorithm,
plaintext: bytes,
*,
iv: bytes = None,
additional_authenticated_data: bytes = None,
**kwargs
) -> EncryptResult:
"""
Encrypt data using the key.
Parameters:
- algorithm: Encryption algorithm to use
- plaintext: Data to encrypt
- iv: Initialization vector (required for some algorithms)
- additional_authenticated_data: Additional data for authenticated encryption
Returns:
EncryptResult: Encryption result with ciphertext and metadata
"""
def decrypt(
algorithm: EncryptionAlgorithm,
ciphertext: bytes,
*,
iv: bytes = None,
authentication_tag: bytes = None,
additional_authenticated_data: bytes = None,
**kwargs
) -> DecryptResult:
"""
Decrypt data using the key.
Parameters:
- algorithm: Encryption algorithm used for encryption
- ciphertext: Data to decrypt
- iv: Initialization vector (if used during encryption)
- authentication_tag: Authentication tag (for authenticated encryption)
- additional_authenticated_data: Additional data (if used during encryption)
Returns:
DecryptResult: Decryption result with plaintext
"""from azure.keyvault.keys.crypto import CryptographyClient, EncryptionAlgorithm
from azure.identity import DefaultAzureCredential
# Create crypto client
key_id = "https://vault.vault.azure.net/keys/my-key/version"
crypto_client = CryptographyClient(key_id, DefaultAzureCredential())
# RSA encryption
plaintext = b"Hello, World!"
encrypt_result = crypto_client.encrypt(EncryptionAlgorithm.rsa_oaep_256, plaintext)
decrypt_result = crypto_client.decrypt(EncryptionAlgorithm.rsa_oaep_256, encrypt_result.ciphertext)
# AES-GCM encryption
import os
plaintext = b"Sensitive data"
encrypt_result = crypto_client.encrypt(
EncryptionAlgorithm.a256_gcm,
plaintext,
iv=os.urandom(12) # 96-bit IV for GCM
)
decrypt_result = crypto_client.decrypt(
EncryptionAlgorithm.a256_gcm,
encrypt_result.ciphertext,
iv=encrypt_result.iv,
authentication_tag=encrypt_result.tag
)Create and verify digital signatures using asymmetric keys.
def sign(algorithm: SignatureAlgorithm, digest: bytes, **kwargs) -> SignResult:
"""
Sign a digest using the key.
Parameters:
- algorithm: Signature algorithm to use
- digest: Pre-computed hash digest to sign
Returns:
SignResult: Signature result
"""
def verify(
algorithm: SignatureAlgorithm,
digest: bytes,
signature: bytes,
**kwargs
) -> VerifyResult:
"""
Verify a signature using the key.
Parameters:
- algorithm: Signature algorithm used for signing
- digest: Original hash digest that was signed
- signature: Signature to verify
Returns:
VerifyResult: Verification result indicating validity
"""import hashlib
from azure.keyvault.keys.crypto import SignatureAlgorithm
# Create a hash digest
data = b"Important document content"
digest = hashlib.sha256(data).digest()
# Sign the digest
sign_result = crypto_client.sign(SignatureAlgorithm.rs256, digest)
print(f"Signature: {sign_result.signature.hex()}")
# Verify the signature
verify_result = crypto_client.verify(SignatureAlgorithm.rs256, digest, sign_result.signature)
print(f"Signature valid: {verify_result.is_valid}")
# ECDSA signing
ec_crypto_client = CryptographyClient("https://vault.vault.azure.net/keys/my-ec-key/version", credential)
sign_result = ec_crypto_client.sign(SignatureAlgorithm.es256, digest)
verify_result = ec_crypto_client.verify(SignatureAlgorithm.es256, digest, sign_result.signature)Wrap (encrypt) and unwrap (decrypt) symmetric keys using key encryption keys.
def wrap_key(algorithm: KeyWrapAlgorithm, key: bytes, **kwargs) -> WrapResult:
"""
Wrap (encrypt) a key using a key encryption key.
Parameters:
- algorithm: Key wrap algorithm to use
- key: Key material to wrap
Returns:
WrapResult: Wrapped key result
"""
def unwrap_key(algorithm: KeyWrapAlgorithm, encrypted_key: bytes, **kwargs) -> UnwrapResult:
"""
Unwrap (decrypt) a key using a key encryption key.
Parameters:
- algorithm: Key wrap algorithm used for wrapping
- encrypted_key: Wrapped key material to unwrap
Returns:
UnwrapResult: Unwrapped key result
"""from azure.keyvault.keys.crypto import KeyWrapAlgorithm
import os
# Generate a data encryption key
data_key = os.urandom(32) # 256-bit key
# Wrap the key
wrap_result = crypto_client.wrap_key(KeyWrapAlgorithm.rsa_oaep_256, data_key)
print(f"Wrapped key: {wrap_result.encrypted_key.hex()}")
# Unwrap the key
unwrap_result = crypto_client.unwrap_key(KeyWrapAlgorithm.rsa_oaep_256, wrap_result.encrypted_key)
print(f"Keys match: {unwrap_result.key == data_key}")
# AES key wrapping
aes_kek_client = CryptographyClient("https://vault.vault.azure.net/keys/my-aes-key/version", credential)
wrap_result = aes_kek_client.wrap_key(KeyWrapAlgorithm.aes_256, data_key)
unwrap_result = aes_kek_client.unwrap_key(KeyWrapAlgorithm.aes_256, wrap_result.encrypted_key)Create RSA key objects compatible with Python's cryptography library.
def create_rsa_private_key(**kwargs) -> KeyVaultRSAPrivateKey:
"""
Create an RSA private key object backed by Key Vault.
Returns:
KeyVaultRSAPrivateKey: RSA private key implementation using Key Vault
"""
def create_rsa_public_key(**kwargs) -> KeyVaultRSAPublicKey:
"""
Create an RSA public key object backed by Key Vault.
Returns:
KeyVaultRSAPublicKey: RSA public key implementation using Key Vault
"""from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
# Create Key Vault-backed RSA key objects
private_key = crypto_client.create_rsa_private_key()
public_key = private_key.public_key()
# Use with cryptography library patterns
message = b"Hello from cryptography library!"
# Encrypt using public key
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Decrypt using private key
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Serialize public key
public_pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)Various methods for creating CryptographyClient instances.
def __init__(
key: Union[KeyVaultKey, str],
credential: TokenCredential,
**kwargs
):
"""
Create a CryptographyClient.
Parameters:
- key: KeyVaultKey object or key identifier URL
- credential: Azure credential for authentication
"""
@classmethod
def from_jwk(cls, jwk: Union[JsonWebKey, Dict[str, Any]], **kwargs) -> "CryptographyClient":
"""
Create a CryptographyClient from a JSON Web Key for local cryptographic operations.
Parameters:
- jwk: JSON Web Key containing cryptographic material
Returns:
CryptographyClient: Client for local cryptographic operations
"""from azure.keyvault.keys import KeyClient
from azure.keyvault.keys.crypto import CryptographyClient
# From key ID
crypto_client = CryptographyClient("https://vault.vault.azure.net/keys/my-key/version", credential)
# From KeyVaultKey object
key_client = KeyClient("https://vault.vault.azure.net/", credential)
key = key_client.get_key("my-key")
crypto_client = CryptographyClient(key, credential)
# From JWK for local operations
jwk = {
"kty": "RSA",
"n": "...", # RSA modulus
"e": "AQAB", # RSA public exponent
# ... other parameters
}
local_crypto_client = CryptographyClient.from_jwk(jwk)class CryptographyClient:
"""Client for performing cryptographic operations with Azure Key Vault keys."""
key_id: str
vault_url: str
class EncryptResult:
"""Result of an encrypt operation."""
key_id: str
algorithm: EncryptionAlgorithm
ciphertext: bytes
iv: bytes
tag: bytes
aad: bytes
class DecryptResult:
"""Result of a decrypt operation."""
key_id: str
algorithm: EncryptionAlgorithm
plaintext: bytes
class SignResult:
"""Result of a sign operation."""
key_id: str
algorithm: SignatureAlgorithm
signature: bytes
class VerifyResult:
"""Result of a verify operation."""
key_id: str
algorithm: SignatureAlgorithm
is_valid: bool
class WrapResult:
"""Result of a wrap key operation."""
key_id: str
algorithm: KeyWrapAlgorithm
encrypted_key: bytes
class UnwrapResult:
"""Result of an unwrap key operation."""
key_id: str
algorithm: KeyWrapAlgorithm
key: bytes
class KeyVaultRSAPrivateKey:
"""RSA private key implementation backed by Key Vault."""
key_size: int
def decrypt(ciphertext: bytes, padding) -> bytes: ...
def sign(data: bytes, padding, algorithm) -> bytes: ...
def public_key() -> KeyVaultRSAPublicKey: ...
def private_numbers() -> RSAPrivateNumbers: ...
def private_bytes(encoding, format, encryption_algorithm) -> bytes: ...
class KeyVaultRSAPublicKey:
"""RSA public key implementation backed by Key Vault."""
key_size: int
def encrypt(plaintext: bytes, padding) -> bytes: ...
def verify(signature: bytes, data: bytes, padding, algorithm) -> None: ...
def public_numbers() -> RSAPublicNumbers: ...
def public_bytes(encoding, format) -> bytes: ...
class EncryptionAlgorithm(str, Enum):
"""Encryption algorithms."""
# RSA algorithms
rsa_oaep = "RSA-OAEP"
rsa_oaep_256 = "RSA-OAEP-256"
rsa1_5 = "RSA1_5"
# AES GCM algorithms
a128_gcm = "A128GCM"
a192_gcm = "A192GCM"
a256_gcm = "A256GCM"
# AES CBC algorithms
a128_cbc = "A128CBC"
a192_cbc = "A192CBC"
a256_cbc = "A256CBC"
# AES CBC with PKCS7 padding
a128_cbcpad = "A128CBCPAD"
a192_cbcpad = "A192CBCPAD"
a256_cbcpad = "A256CBCPAD"
class KeyWrapAlgorithm(str, Enum):
"""Key wrapping algorithms."""
# AES key wrap algorithms
aes_128 = "A128KW"
aes_192 = "A192KW"
aes_256 = "A256KW"
# RSA key wrap algorithms
rsa_oaep = "RSA-OAEP"
rsa_oaep_256 = "RSA-OAEP-256"
rsa1_5 = "RSA1_5"
# PKCS#11 mechanisms
ckm_aes_key_wrap = "CKM_AES_KEY_WRAP"
ckm_aes_key_wrap_pad = "CKM_AES_KEY_WRAP_PAD"
class SignatureAlgorithm(str, Enum):
"""Signature algorithms."""
# RSA PSS algorithms
ps256 = "PS256" # RSASSA-PSS using SHA-256
ps384 = "PS384" # RSASSA-PSS using SHA-384
ps512 = "PS512" # RSASSA-PSS using SHA-512
# RSA PKCS#1 v1.5 algorithms
rs256 = "RS256" # RSASSA-PKCS1-v1_5 using SHA-256
rs384 = "RS384" # RSASSA-PKCS1-v1_5 using SHA-384
rs512 = "RS512" # RSASSA-PKCS1-v1_5 using SHA-512
# ECDSA algorithms
es256 = "ES256" # ECDSA using P-256 and SHA-256
es384 = "ES384" # ECDSA using P-384 and SHA-384
es512 = "ES512" # ECDSA using P-521 and SHA-512
es256_k = "ES256K" # ECDSA using P-256K and SHA-256
# HMAC algorithms
hs256 = "HS256" # HMAC using SHA-256
hs384 = "HS384" # HMAC using SHA-384
hs512 = "HS512" # HMAC using SHA-512Install with Tessl CLI
npx tessl i tessl/pypi-azure-keyvault-keys