apple / swift-crypto

Open-source implementation of a substantial portion of the API of Apple CryptoKit suitable for use on Linux platforms.
https://apple.github.io/swift-crypto
Apache License 2.0
1.45k stars 154 forks source link

Noncopyable / moveonly `PrivateKey` API? #188

Open Sajjon opened 1 year ago

Sajjon commented 1 year ago

New API Proposal: Noncopyable PrivateKey

Motivation:

For the past six years I've been working with cryptography and Swift and I've been missing some kind of compiler help regarding my usage of private keys. Rust's powerful ownership model is most likely a strong reason why many crypto project chose Rust as a go to language. With Swift 5.9 we have noncopyable types, along consume/borrow which seem like a nice fit for swift-crypto!

What is Apple's thoughts on including a new API layer to each curve that ships with swift-crypto where the private keys are ~Copyable? I imagine it would be a new namespace, similar to how P256 and SecureEnclave.P256 namespaces exists in parallell. It could be Safe.P26.Signing.PrivateKey, the corresponding PublicKey need not be ~Copyable. An alternative would be to put the non copyable variant in P256.Signing.Safe.PrivateKey or let the type itself be prefix with "Safe", i.e. P256.Signing.SafePrivateKey.

Importance:

Does this API unlock entirely new use-case

YES, it unlocks an entire new use-case for the developer writing the code! Just how async/await offers an entire new way and safer way to write concurrency code in Swift, ~Copyable offers the users of swift-crypto - and CryptoKit - an entire new and safer way of using private keys!

Lukasa commented 1 year ago

Thanks for this suggestion. Can you clarify why having copyable Private Keys is a safety concern?

Sajjon commented 1 year ago

@Lukasa not so much that having copyable being a safety concern as to being able to use non-copyable private keys and thus know that I have not accidentally made a copy somewhere, being kept in memory, that I did not think about. Just like using Implicitly Unwrapped Optionals is not a concern if one always uses them correctly, but the nice thing about Swift (non-Implicitly unwrapped) Optionals is that I get help from the compiler.

Sajjon commented 1 year ago

Case study, e.g. Rust Crate "Dalek" has an EphemeralSecret (PrivateKey) which does not have the Copy "trait", i.e. is move-only https://github.com/dalek-cryptography/x25519-dalek/blob/main/src/x25519.rs#L75

Lukasa commented 1 year ago

You can still arrange to do this by defining wrapper types in your own code that are non-copyable. I'd be fairly nervous about inflicting this constraint on the entire userbase of Crypto, especially as defining these wrappers is a straightforward affair.