Skip to content

Commit da2bf9d

Browse files
PYTHON-2267: Allow UUID key_id to be passed to ClientEncryption.encrypt (#1494)
1 parent c2af3df commit da2bf9d

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

pymongo/encryption.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import contextlib
1919
import enum
2020
import socket
21+
import uuid
2122
import weakref
2223
from copy import deepcopy
2324
from typing import (
@@ -30,6 +31,7 @@
3031
MutableMapping,
3132
Optional,
3233
Sequence,
34+
Union,
3335
cast,
3436
)
3537

@@ -759,14 +761,16 @@ def _encrypt_helper(
759761
self,
760762
value: Any,
761763
algorithm: str,
762-
key_id: Optional[Binary] = None,
764+
key_id: Optional[Union[Binary, uuid.UUID]] = None,
763765
key_alt_name: Optional[str] = None,
764766
query_type: Optional[str] = None,
765767
contention_factor: Optional[int] = None,
766768
range_opts: Optional[RangeOpts] = None,
767769
is_expression: bool = False,
768770
) -> Any:
769771
self._check_closed()
772+
if isinstance(key_id, uuid.UUID):
773+
key_id = Binary.from_uuid(key_id)
770774
if key_id is not None and not (
771775
isinstance(key_id, Binary) and key_id.subtype == UUID_SUBTYPE
772776
):
@@ -799,7 +803,7 @@ def encrypt(
799803
self,
800804
value: Any,
801805
algorithm: str,
802-
key_id: Optional[Binary] = None,
806+
key_id: Optional[Union[Binary, uuid.UUID]] = None,
803807
key_alt_name: Optional[str] = None,
804808
query_type: Optional[str] = None,
805809
contention_factor: Optional[int] = None,
@@ -826,6 +830,9 @@ def encrypt(
826830
827831
:return: The encrypted value, a :class:`~bson.binary.Binary` with subtype 6.
828832
833+
.. versionchanged:: 4.7
834+
``key_id`` can now be passed in as a :class:`uuid.UUID`.
835+
829836
.. versionchanged:: 4.2
830837
Added the `query_type` and `contention_factor` parameters.
831838
"""
@@ -847,7 +854,7 @@ def encrypt_expression(
847854
self,
848855
expression: Mapping[str, Any],
849856
algorithm: str,
850-
key_id: Optional[Binary] = None,
857+
key_id: Optional[Union[Binary, uuid.UUID]] = None,
851858
key_alt_name: Optional[str] = None,
852859
query_type: Optional[str] = None,
853860
contention_factor: Optional[int] = None,
@@ -875,6 +882,9 @@ def encrypt_expression(
875882
876883
:return: The encrypted expression, a :class:`~bson.RawBSONDocument`.
877884
885+
.. versionchanged:: 4.7
886+
``key_id`` can now be passed in as a :class:`uuid.UUID`.
887+
878888
.. versionadded:: 4.4
879889
"""
880890
return cast(

test/test_encryption.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,14 @@ def test_encrypt_decrypt(self):
461461
)
462462
self.assertEqual(encrypted_ssn, encrypted_ssn2)
463463

464+
# Test encryption via UUID
465+
encrypted_ssn3 = client_encryption.encrypt(
466+
doc["ssn"],
467+
Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic,
468+
key_id=key_id.as_uuid(),
469+
)
470+
self.assertEqual(encrypted_ssn, encrypted_ssn3)
471+
464472
# Test decryption.
465473
decrypted_ssn = client_encryption.decrypt(encrypted_ssn)
466474
self.assertEqual(decrypted_ssn, doc["ssn"])
@@ -479,9 +487,6 @@ def test_validation(self):
479487

480488
msg = "key_id must be a bson.binary.Binary with subtype 4"
481489
algo = Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic
482-
uid = uuid.uuid4()
483-
with self.assertRaisesRegex(TypeError, msg):
484-
client_encryption.encrypt("str", algo, key_id=uid) # type: ignore[arg-type]
485490
with self.assertRaisesRegex(TypeError, msg):
486491
client_encryption.encrypt("str", algo, key_id=Binary(b"123"))
487492

0 commit comments

Comments
 (0)