0
# Key Import and Export
1
2
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.
3
4
## Capabilities
5
6
### Key Import
7
8
Import cryptographic key material from external sources into Azure Key Vault.
9
10
```python { .api }
11
def import_key(
12
name: str,
13
key: JsonWebKey,
14
*,
15
hardware_protected: bool = None,
16
enabled: bool = None,
17
tags: Dict[str, str] = None,
18
not_before: datetime = None,
19
expires_on: datetime = None,
20
exportable: bool = None,
21
release_policy: KeyReleasePolicy = None,
22
**kwargs
23
) -> KeyVaultKey:
24
"""
25
Import a key into the Key Vault.
26
27
Parameters:
28
- name: The name for the imported key
29
- key: The JSON Web Key to import
30
- hardware_protected: Whether to store in HSM (True) or software (False)
31
- enabled: Whether the key should be enabled
32
- tags: Application-specific metadata
33
- not_before: Key not valid before this date
34
- expires_on: Key expiration date
35
- exportable: Whether the private key can be exported
36
- release_policy: Policy rules for key release
37
38
Returns:
39
KeyVaultKey: The imported key
40
41
Raises:
42
- InvalidArgumentError: If key format is invalid
43
- ConflictError: If key with same name already exists
44
- ForbiddenError: If import permission is not granted
45
"""
46
```
47
48
#### Usage Examples
49
50
```python
51
from azure.keyvault.keys import KeyClient, JsonWebKey, KeyType, KeyOperation
52
from azure.identity import DefaultAzureCredential
53
54
client = KeyClient("https://vault.vault.azure.net/", DefaultAzureCredential())
55
56
# Import RSA key from JWK
57
rsa_jwk = JsonWebKey(
58
kty=KeyType.rsa,
59
n=b"...", # RSA modulus (base64url decoded)
60
e=b"AQAB", # RSA public exponent (base64url decoded)
61
d=b"...", # RSA private exponent (base64url decoded)
62
p=b"...", # RSA prime p
63
q=b"...", # RSA prime q
64
dp=b"...", # RSA private key parameter
65
dq=b"...", # RSA private key parameter
66
qi=b"...", # RSA private key parameter
67
key_ops=[KeyOperation.encrypt, KeyOperation.decrypt, KeyOperation.sign, KeyOperation.verify]
68
)
69
70
imported_key = client.import_key(
71
"imported-rsa-key",
72
rsa_jwk,
73
hardware_protected=False,
74
tags={"source": "external", "imported": "true"}
75
)
76
print(f"Imported key: {imported_key.name}")
77
78
# Import EC key from JWK
79
from azure.keyvault.keys import KeyCurveName
80
81
ec_jwk = JsonWebKey(
82
kty=KeyType.ec,
83
crv=KeyCurveName.p_256,
84
x=b"...", # X coordinate (base64url decoded)
85
y=b"...", # Y coordinate (base64url decoded)
86
d=b"...", # Private key (base64url decoded)
87
key_ops=[KeyOperation.sign, KeyOperation.verify]
88
)
89
90
imported_ec_key = client.import_key(
91
"imported-ec-key",
92
ec_jwk,
93
hardware_protected=True # Store in HSM
94
)
95
96
# Import symmetric key from JWK
97
symmetric_jwk = JsonWebKey(
98
kty=KeyType.oct,
99
k=b"...", # Symmetric key material (base64url decoded)
100
key_ops=[KeyOperation.encrypt, KeyOperation.decrypt]
101
)
102
103
imported_symmetric_key = client.import_key(
104
"imported-symmetric-key",
105
symmetric_jwk
106
)
107
```
108
109
### Key Release
110
111
Release keys from Azure Key Vault with attestation-based security policies.
112
113
```python { .api }
114
def release_key(
115
name: str,
116
target_attestation_token: str,
117
*,
118
version: str = None,
119
algorithm: KeyExportEncryptionAlgorithm = None,
120
nonce: str = None,
121
**kwargs
122
) -> ReleaseKeyResult:
123
"""
124
Release a key using an attestation token.
125
126
Parameters:
127
- name: The name of the key to release
128
- target_attestation_token: Attestation token proving target environment security
129
- version: Specific version of the key (optional, uses latest if omitted)
130
- algorithm: Encryption algorithm for key export protection
131
- nonce: Cryptographic nonce for freshness
132
133
Returns:
134
ReleaseKeyResult: The released key wrapped according to policy
135
136
Raises:
137
- ResourceNotFoundError: If the key doesn't exist
138
- ForbiddenError: If key release policy requirements not met
139
- InvalidArgumentError: If attestation token is invalid
140
"""
141
```
142
143
#### Usage Examples
144
145
```python
146
from azure.keyvault.keys import KeyExportEncryptionAlgorithm
147
148
# Release a key with attestation token
149
attestation_token = "eyJ..." # Attestation token from trusted execution environment
150
151
release_result = client.release_key(
152
"confidential-key",
153
attestation_token,
154
algorithm=KeyExportEncryptionAlgorithm.rsa_aes_key_wrap_256
155
)
156
157
print(f"Released key value: {release_result.value}")
158
159
# The released key is encrypted and can only be decrypted in the attested environment
160
```
161
162
### Key Release Policies
163
164
Configure and manage key release policies for secure key export.
165
166
```python { .api }
167
class KeyReleasePolicy:
168
"""Policy rules under which a key can be exported."""
169
encoded_policy: bytes
170
content_type: str
171
immutable: bool
172
```
173
174
#### Usage Examples
175
176
```python
177
import json
178
import base64
179
180
# Define a key release policy
181
policy_document = {
182
"version": "1.0",
183
"attestation": {
184
"type": "SGX",
185
"measurement": "abc123...", # Expected enclave measurement
186
"mrenclave": "def456...", # Expected enclave hash
187
},
188
"rules": [
189
{
190
"claim": "is-debuggable",
191
"equals": False
192
},
193
{
194
"claim": "product-id",
195
"equals": 1
196
}
197
]
198
}
199
200
# Encode policy as base64
201
policy_json = json.dumps(policy_document)
202
encoded_policy = base64.b64encode(policy_json.encode()).decode()
203
204
# Create key release policy
205
from azure.keyvault.keys import KeyReleasePolicy
206
207
release_policy = KeyReleasePolicy(
208
encoded_policy=encoded_policy.encode(),
209
content_type="application/json; charset=utf-8"
210
)
211
212
# Create key with release policy
213
key_with_policy = client.create_rsa_key(
214
"confidential-key-with-policy",
215
size=2048,
216
exportable=True,
217
release_policy=release_policy
218
)
219
```
220
221
### Import from External Key Management Systems
222
223
Common patterns for importing keys from various external sources.
224
225
#### Import from OpenSSL
226
227
```python
228
import base64
229
from cryptography.hazmat.primitives import serialization
230
from cryptography.hazmat.primitives.asymmetric import rsa
231
232
def import_from_pem(client: KeyClient, key_name: str, pem_data: bytes, password: bytes = None):
233
"""Import a key from PEM format."""
234
235
# Load private key from PEM
236
private_key = serialization.load_pem_private_key(pem_data, password=password)
237
238
if isinstance(private_key, rsa.RSAPrivateKey):
239
# Extract RSA parameters
240
private_numbers = private_key.private_numbers()
241
public_numbers = private_numbers.public_numbers
242
243
# Create JWK
244
jwk = JsonWebKey(
245
kty=KeyType.rsa,
246
n=public_numbers.n.to_bytes((public_numbers.n.bit_length() + 7) // 8, 'big'),
247
e=public_numbers.e.to_bytes((public_numbers.e.bit_length() + 7) // 8, 'big'),
248
d=private_numbers.private_exponent.to_bytes((private_numbers.private_exponent.bit_length() + 7) // 8, 'big'),
249
p=private_numbers.p.to_bytes((private_numbers.p.bit_length() + 7) // 8, 'big'),
250
q=private_numbers.q.to_bytes((private_numbers.q.bit_length() + 7) // 8, 'big'),
251
dp=private_numbers.dmp1.to_bytes((private_numbers.dmp1.bit_length() + 7) // 8, 'big'),
252
dq=private_numbers.dmq1.to_bytes((private_numbers.dmq1.bit_length() + 7) // 8, 'big'),
253
qi=private_numbers.iqmp.to_bytes((private_numbers.iqmp.bit_length() + 7) // 8, 'big')
254
)
255
256
# Import to Key Vault
257
return client.import_key(key_name, jwk)
258
else:
259
raise ValueError("Only RSA keys are supported in this example")
260
261
# Usage
262
with open("private-key.pem", "rb") as f:
263
pem_data = f.read()
264
265
imported_key = import_from_pem(client, "imported-from-pem", pem_data)
266
```
267
268
#### Import from PKCS#12
269
270
```python
271
from cryptography.hazmat.primitives import serialization
272
273
def import_from_pkcs12(client: KeyClient, key_name: str, p12_data: bytes, password: bytes):
274
"""Import a key from PKCS#12 format."""
275
276
# Load PKCS#12
277
private_key, certificate, additional_certificates = serialization.pkcs12.load_key_and_certificates(
278
p12_data, password
279
)
280
281
# Convert to JWK and import (similar to PEM example above)
282
# ... implementation details ...
283
284
return client.import_key(key_name, jwk, tags={"format": "pkcs12"})
285
```
286
287
## Types
288
289
```python { .api }
290
class JsonWebKey:
291
"""JSON Web Key representation as defined in RFC 7517."""
292
kid: str # Key identifier
293
kty: KeyType # Key type
294
key_ops: List[KeyOperation] # Allowed operations
295
296
# RSA parameters
297
n: bytes # RSA modulus
298
e: bytes # RSA public exponent
299
d: bytes # RSA private exponent
300
dp: bytes # RSA private key parameter
301
dq: bytes # RSA private key parameter
302
qi: bytes # RSA private key parameter
303
p: bytes # RSA secret prime
304
q: bytes # RSA secret prime
305
306
# EC parameters
307
crv: KeyCurveName # Elliptic curve name
308
x: bytes # X component of EC public key
309
y: bytes # Y component of EC public key
310
d: bytes # D component of EC private key
311
312
# Symmetric key parameters
313
k: bytes # Symmetric key material
314
315
# HSM parameters
316
t: bytes # HSM Token for Bring Your Own Key
317
318
class ReleaseKeyResult:
319
"""Result of a key release operation."""
320
value: str # The released key material (encrypted according to policy)
321
322
class KeyReleasePolicy:
323
"""Policy rules under which a key can be exported."""
324
encoded_policy: bytes # Base64-encoded policy document
325
content_type: str # MIME type of policy (e.g., "application/json; charset=utf-8")
326
immutable: bool # Whether policy can be changed after creation
327
328
class KeyExportEncryptionAlgorithm(str, Enum):
329
"""Supported algorithms for protecting exported key material."""
330
ckm_rsa_aes_key_wrap = "CKM_RSA_AES_KEY_WRAP" # CKM RSA AES Key Wrap
331
rsa_aes_key_wrap_256 = "RSA_AES_KEY_WRAP_256" # RSA AES Key Wrap with SHA-256
332
rsa_aes_key_wrap_384 = "RSA_AES_KEY_WRAP_384" # RSA AES Key Wrap with SHA-384
333
```
334
335
## Security Considerations
336
337
### Import Security
338
339
- **Key Material Handling**: Ensure imported key material is from trusted sources
340
- **Transport Security**: Use secure channels when transferring keys to import
341
- **Key Validation**: Validate key parameters before import
342
- **Access Control**: Restrict import permissions to authorized personnel only
343
344
### Export Security
345
346
- **Attestation Verification**: Verify attestation tokens are from trusted execution environments
347
- **Policy Enforcement**: Ensure release policies meet organizational security requirements
348
- **Audit Logging**: Monitor and log all key release operations
349
- **Least Privilege**: Grant release permissions only when necessary
350
351
### Best Practices
352
353
```python
354
# Example secure import pattern
355
def secure_import_key(client: KeyClient, key_name: str, jwk: JsonWebKey):
356
"""Securely import a key with validation and audit."""
357
358
# Validate key before import
359
if not jwk.kty or not jwk.key_ops:
360
raise ValueError("Key type and operations must be specified")
361
362
# Import with restrictive settings
363
imported_key = client.import_key(
364
key_name,
365
jwk,
366
enabled=False, # Start disabled for review
367
tags={
368
"imported": "true",
369
"import_date": datetime.utcnow().isoformat(),
370
"requires_review": "true"
371
}
372
)
373
374
# Log the import
375
print(f"Key {key_name} imported successfully, requires review before enabling")
376
377
return imported_key
378
```