Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clone_key() method to private key types #26

Merged
merged 2 commits into from
Dec 22, 2023
Merged

Add clone_key() method to private key types #26

merged 2 commits into from
Dec 22, 2023

Conversation

djc
Copy link
Member

@djc djc commented Dec 22, 2023

Right now it's possible to clone a PrivateKeyDer, but it's pretty unergonomic. I added this in a work repo:

// `PrivateKeyDer` doesn't implement `Clone` to help avoid accental leaking of the secret key.
// Unfortunately working around this is a bit involved.
fn clone_key(key: &PrivateKeyDer<'_>) -> PrivateKeyDer<'static> {
    match &key {
        PrivateKeyDer::Pkcs1(key) => {
            PrivateKeyDer::from(PrivatePkcs1KeyDer::from(key.secret_pkcs1_der().to_vec()))
        }
        PrivateKeyDer::Sec1(key) => {
            PrivateKeyDer::from(PrivateSec1KeyDer::from(key.secret_sec1_der().to_vec()))
        }
        PrivateKeyDer::Pkcs8(key) => {
            PrivateKeyDer::from(PrivatePkcs8KeyDer::from(key.secret_pkcs8_der().to_vec()))
        }
        _ => unreachable!(),
    }
}

Pave this path, while still avoiding a Clone impl that would make it easy to leak private key material.

Fixes #25.

@ctz
Copy link
Member

ctz commented Dec 22, 2023

Is the theory that making people write clone_key() (instead of clone() via std::clone::Clone) will give them more pause to consider if it is really needed? I can be down with that, just want to ensure I'm not missing anything.

@djc
Copy link
Member Author

djc commented Dec 22, 2023

Is the theory that making people write clone_key() (instead of clone() via std::clone::Clone) will give them more pause to consider if it is really needed? I can be down with that, just want to ensure I'm not missing anything.

Yes, that is the theory. In particular, while .clone() might still be something to pay attention to especially when applied to a binding called key or private_key, it can be quite easy to slap a derive(Clone) on a type which might include the key, which wouldn't work in this case and require a manual Clone implementation. This is analogous to how we don't have an AsRef<[u8]> implementation for the private key types but we do have a secret_*der() method.

ring AFAICT doesn't expose any way of getting at the internals of private keys except for directly after generating one, so it is more strict. I'm hoping to strike a balance that does make it possible but that triggers enough thinking to consider whether it's the right thing to do in context.

@@ -1,6 +1,6 @@
[package]
name = "rustls-pki-types"
version = "1.0.1"
version = "1.1.0"
Copy link
Member Author

@djc djc Dec 22, 2023

Choose a reason for hiding this comment

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

For crates that have a non-zero major version, ideally we should bump the minor version when new API is added. This is not as strict of a cultural norm in the crates ecosystem as the semver-compatibility rules, but it can help to distinguish when you can downgrade (I'm a little fuzzy on the details right now).

Copy link
Member

@cpu cpu left a comment

Choose a reason for hiding this comment

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

Thanks, this seems reasonable to me. If both you and the OP have needed this it's fair to assume others will too.

@djc djc added this pull request to the merge queue Dec 22, 2023
Merged via the queue into main with commit 53d49b1 Dec 22, 2023
22 checks passed
@djc djc deleted the clone-key branch December 22, 2023 15:05
@eric-seppanen
Copy link

In my case, I didn't want access to the internals of the key, I just had a few layers of abstraction between the place where I acquired the private key and where it gets used. Those intermediate layers generated borrow check errors (because they were async fns that needed to be 'static), so I needed a way to jump from maybe-borrowed to owned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

How to go from PrivateKeyDer<'a> to PrivateKeyDer<'static> ?
4 participants