Skip to content

Conversation

@Courtcircuits
Copy link
Contributor

This adds support for deep copying keys. This resolves issue #13588.

I tried to follow as close as possible what was done in PR #12110. Hope it fits what was expected for this issue !

Basically, this PR adds deep copy support for :

  • RSA
  • DH
  • DSA
  • EC
  • ED25519
  • ED448
  • X25519
  • X448

slf: pyo3::PyRef<'p, Self>,
_memo: &pyo3::Bound<'p, pyo3::types::PyDict>,
) -> CryptographyResult<Self> {
let new_key = Self {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need to do this, because keys are immutable a version of return self (like __copy__) should be enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I didn't know that, I'll basically use the same as __copy__ then. Thanks for the quick review !

Comment on lines 154 to 156
}

fn __eq__(&self, other: pyo3::PyRef<'_, Self>) -> bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's going on here? Why is this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot to uncommit it. I removed it.

@Courtcircuits Courtcircuits marked this pull request as draft October 30, 2025 10:54
@Courtcircuits Courtcircuits marked this pull request as ready for review October 30, 2025 13:44

fn __deepcopy__<'p>(
slf: pyo3::PyRef<'p, Self>,
_memo: &pyo3::Bound<'p, pyo3::types::PyDict>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: given these are unused, it's probably better to just type them as PyAny

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done !

key2 = copy.deepcopy(key1)
assert key1 == key2

key1 = dsa.generate_private_key(2048).public_key()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC dsa key generation is quite slow, is there some other key we can load to test here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I replaced the generated key by a key in an already existing PEM file (this one : vectors/cryptography_vectors/asymmetric/Traditional_OpenSSL_Serialization/dsa.1024.pem). The goal of this test is mainly to make sure that deepcopy really creates a deep copy of the key. But if I understand correctly, @joakimnordling in issue #13588 is just asking for copy.deepcopy to work on keys.

Comment on lines 2806 to 2808
key1 = generate_private_key(
public_exponent=65537, key_size=2048
).public_key()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same, RSA key gen also takes appreciable time, there should be other vectors available

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this I replaced the generated key with the test fixture rsa_key_512.

@alex alex merged commit 4838a0c into pyca:main Nov 3, 2025
68 checks passed
"""

@abc.abstractmethod
def __deepcopy__(self) -> DHPublicKey:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the __deepcopy__ expected to take in the memo as a second parameter as described on https://docs.python.org/3/library/copy.html#object.__deepcopy__ ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oof yes, not sure how I missed this. Will send a fix.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case you missed it, the version in docs/hazmat/primitives/asymmetric/cloudhsm.rst has a memodict (not sure if anything cares about if it has that name of memo, but I'd at least change it to match the name in the documentation. And also note that the parameter is missing in not just this one I commented on, but all the *.py files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants