Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -223,14 +223,14 @@ def encrypt(self, algorithm, plaintext, **kwargs):
:type algorithm: :class:`~azure.keyvault.keys.crypto.EncryptionAlgorithm`
:param bytes plaintext: Bytes to encrypt
:keyword bytes iv: Initialization vector. Required for only AES-CBC(PAD) encryption. If you pass your own IV,
make sure you use a cryptographically random, non-repeating IV. If omitted for remote cryptography, Key
Vault will generate an IV.
make sure you use a cryptographically random, non-repeating IV. If omitted, an attempt will be made to
generate an IV via `os.urandom <https://docs.python.org/library/os.html#os.urandom>`_ for local
cryptography; for remote cryptography, Key Vault will generate an IV.
:keyword bytes additional_authenticated_data: Optional data that is authenticated but not encrypted. For use
with AES-GCM encryption.
:rtype: :class:`~azure.keyvault.keys.crypto.EncryptResult`
:raises:
ValueError if parameters that are incompatible with the specified algorithm are provided,
RuntimeError if an IV cannot be generated
:raises ValueError: if parameters that are incompatible with the specified algorithm are provided, or if
generating an IV fails on the current platform.

.. literalinclude:: ../tests/test_examples_crypto.py
:start-after: [START encrypt]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Licensed under the MIT License.
# ------------------------------------
import abc
import os
from typing import TYPE_CHECKING

from azure.core.exceptions import AzureError
Expand Down Expand Up @@ -63,6 +64,17 @@ def _raise_if_unsupported(self, operation, algorithm):
def encrypt(self, algorithm, plaintext, iv=None):
# type: (EncryptionAlgorithm, bytes, Optional[bytes]) -> EncryptResult
self._raise_if_unsupported(KeyOperation.encrypt, algorithm)

# If an IV isn't provided with AES-CBCPAD encryption, try to create one
if iv is None and algorithm.value.endswith("CBCPAD"):
try:
iv = os.urandom(16)
except NotImplementedError as ex:
raise ValueError(
"An IV could not be generated on this OS. Please provide your own cryptographically random, "
"non-repeating IV for local cryptography."
) from ex

ciphertext = self._internal_key.encrypt(plaintext, algorithm=algorithm.value, iv=iv)
return EncryptResult(
key_id=self._key.kid, algorithm=algorithm, ciphertext=ciphertext, iv=iv # type: ignore[attr-defined]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,14 @@ async def encrypt(self, algorithm: "EncryptionAlgorithm", plaintext: bytes, **kw
:type algorithm: :class:`~azure.keyvault.keys.crypto.EncryptionAlgorithm`
:param bytes plaintext: Bytes to encrypt
:keyword bytes iv: Initialization vector. Required for only AES-CBC(PAD) encryption. If you pass your own IV,
make sure you use a cryptographically random, non-repeating IV. If omitted for remote cryptography, Key
Vault will generate an IV.
make sure you use a cryptographically random, non-repeating IV. If omitted, an attempt will be made to
generate an IV via `os.urandom <https://docs.python.org/library/os.html#os.urandom>`_ for local
cryptography; for remote cryptography, Key Vault will generate an IV.
:keyword bytes additional_authenticated_data: Optional data that is authenticated but not encrypted. For use
with AES-GCM encryption.
:rtype: :class:`~azure.keyvault.keys.crypto.EncryptResult`
:raises:
ValueError if parameters that are incompatible with the specified algorithm are provided,
RuntimeError if an IV cannot be generated
:raises ValueError: if parameters that are incompatible with the specified algorithm are provided, or if
generating an IV fails on the current platform.

.. literalinclude:: ../tests/test_examples_crypto_async.py
:start-after: [START encrypt]
Expand Down
9 changes: 9 additions & 0 deletions sdk/keyvault/azure-keyvault-keys/tests/test_local_crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ def test_symmetric_encrypt_decrypt(algorithm, key_size):

encrypt_result = provider.encrypt(algorithm, plaintext, iv=iv)
assert encrypt_result.key_id == key.id
assert encrypt_result.iv == iv

decrypt_result = provider.decrypt(encrypt_result.algorithm, encrypt_result.ciphertext, iv=encrypt_result.iv)
assert decrypt_result.plaintext == plaintext

# Try with no IV to verify that we generate one for local crypto
encrypt_result = provider.encrypt(algorithm, plaintext, iv=None)
assert encrypt_result.key_id == key.id
assert len(encrypt_result.iv) == 16

decrypt_result = provider.decrypt(encrypt_result.algorithm, encrypt_result.ciphertext, iv=encrypt_result.iv)
assert decrypt_result.plaintext == plaintext
Expand Down