rust-crypto icon indicating copy to clipboard operation
rust-crypto copied to clipboard

(Feature) NaCl compatbile authenticated encryption primitves.

Open Yawning opened this issue 10 years ago • 10 comments

So, I like crypto that's hard(-er, there's still nonce related foot+gun oportunities) to misuse. djb et al's NaCl library provides nifty crypto_box/crypto_secretbox for doing authenticated encryption with a secret key/public key respectfully.

Would people be opposed to having something like this as part of rust-crypto? The issues as far as I am aware are:

  • There's no easy way to generate Curve25519 keypairs (Easily fixed.).
  • HSalsa20 isn't exposed (also easily fixed, though I'd rather wait till after #232 is dealt with).

As a WIP (though functionally complete and tested) implementation, this could look something like https://github.com/Yawning/rust-crypto/compare/nacl (Don't merge that yet, the way HChaCha was exposed is kind of kludgy). The code is modeled off the C++ API (because the C API is quirky), and is byte compatible.

I wouldn't consider the constructs particularly obscure since they're included in NaCl/tweetNaCl/libsodium/Go's crypto extensions/etc.

Yawning avatar Jan 29 '15 07:01 Yawning

Some performance numbers, that should be taken with a huge grain of salt: test nacl::bench::crypto_secretbox_10 ... bench: 767 ns/iter (+/- 100) = 13 MB/s test nacl::bench::crypto_secretbox_1k ... bench: 9994 ns/iter (+/- 156) = 102 MB/s test nacl::bench::crypto_secretbox_64k ... bench: 614535 ns/iter (+/- 18127) = 106 MB/s test nacl::bench::crypto_secretbox_open_10 ... bench: 785 ns/iter (+/- 19) = 12 MB/s test nacl::bench::crypto_secretbox_open_1k ... bench: 10008 ns/iter (+/- 1263) = 102 MB/s test nacl::bench::crypto_secretbox_open_64k ... bench: 631369 ns/iter (+/- 88426) = 103 MB/s

I didn't bother to benchmark crypto_box/crypto_box_open because the only difference is the cost of a single Curve25519 scalar base mult, and 1 HChaCha20 call per box. This is also without the Salsa20 changes from #232 (why yes, this can go much faster).

Yawning avatar Jan 29 '15 07:01 Yawning

This and #237 cover similar ground, so, I'll put most of my thoughts here. My thoughts are also related to #228.

Right now a number of the interfaces in rust-crypto are a bit yucky to use. The streaming AES/CBC interface is an example (which I wrote) - its extremely flexible, but the commong case ("encrypt this set of bytes") is very unergonomic. There are tons of great reasons for having a simple interface to crypto primatives that is very hard to misuse. On the other hand, some use cases call for more powerful yet less ergonomic inerterfaces. The question is: What does rust-crypto want to focus on?

My current thinking is that it makes sense for rust-crypto (as it currently exists) to focus on creating high quality implementations of useful crypto algorithms with idomatic, maximally powerful interfaces without making (too many) concessions to ergonmics. Ergonomics are extremely important, of course. But, what I'm thinking is that if rust-crypto provides sufficiently powerful building blocks, then we can construct easier to use interfaces in higher level crates to make them easier for most developers to leverage. Maybe a rust-crypto-nacl crate to contain NaCL like bindings. We could also have a rust-crypto-openssl crate for OpenSSL compatible bindings. We could then tell developers to use these higher level bindings for their significantly greater ease of use. However, if a developer really has a specialized use case, then they could still fall back on rust-crypto directly to gain maximum power.

If the rust-crypto communitly reaches a concensus that NaCL bindings in rust-crypto propper are the way to go, I could certainly be convinced. However, NaCL is just one higher level abstraction. Its popular right now, but, its not the only possible abstraction. I think it would be nice to have rust-crypto focus on the lowest level parts of the crypto problem and then leave the higher level issues up to different crates which can implement different interfaces to suit different use cases. I would be a bit concerned with the rust-crypto crate trying to do too many things - I'm thinking a focus on the basic building blocks would help keep its scope and mission bounded.

All that being said, I would like rust-crypto to be a community focused around building great crypto code in Rust. Part of that is creating the higher level bindings to make it usable in regular software projects. So, what I think might make sense is to create a "Rust-Crypto" github organization and then to put multiple crates under that organization. The existing rust-crypto crate could continue to be the low level building block of cryptography. Then, we could create higher level crates such as rust-crypto-nacl, rust-crypto-openssl, rust-crypto-tls and the like.

I've been toying around with this idea for a little bit, but up until recently, I've been very concerned about how having multiple crates would impact the maintentance burden for rust-crypto - with Rust changing so frequently, quite a bit of effort goes into just keeping it compiling. However, with Rust starting to stabilize, I think a setup like what I descibe above is starting to become something that could be reasonably maintained.

I'm very interested to hear what everyone thinks or alternate suggestions about how we can support more ergonomic interfaces such as an NaCL like interface.

DaGenix avatar Feb 01 '15 06:02 DaGenix

Related to all this, and supportive of the "provide ergonomic interfaces in some form" general idea, there is this from the Cryptography Coding Standard.

I think that providing and pointing people at separate well maintained, user friendly crate(s) is a fine solution to this sort of thing, and the maintenance burden shouldn't be too big as long as the rust-crypto interface is stable. Once such crates exist, the documentation should strongly encorage the bulk of the users to consider such things.

For what it's worth, I'd be up for fleshing out rust-crypto-nacl and maintaining it, if that affects the decision process any.

Yawning avatar Feb 01 '15 09:02 Yawning

What if the low level crypto primitives that are exposed where made unsafe. Having to put it in an unsafe block would be a very explicit indicater for the user.

calvinmetcalf avatar Feb 01 '15 15:02 calvinmetcalf

Back on the NaCl side of things: https://github.com/Yawning/rust-crypto-nacl

It's not registered on crates.io yet since it requires the changes in #245 to not crash with the latest nightly, and for box to work. It's mostly self explanatory, and even has examples that cover the common use cases. I went against the trend and CC0ed the example code in rust-crypto-nacl because trivial "do this to encrypt/decrypt data" code snippets are trivial.

Does carving out an org for these sort of packages make sense? If not, I can just maintain this on my own (unless rust-crypto changes this sort of code shouldn't break that often).

@calvinmetcalf How far would you want to go? At a minimum (in my opinion) RC4, MD5, SHA1, and ECB mode should require special thought (maybe not SHA1, just because tons of thing still use it, but in the near future, the algorithm should be avoided). Part of me almost wants to heavily discourage using non authenticated encryption/decryption (since the library provides AEAD modes), but that would probably be overly painful to users...

Yawning avatar Feb 07 '15 09:02 Yawning

raw results from hmacs too. I could non authenticated being unsafe brings a good idea

On Sat, Feb 7, 2015, 4:04 AM Yawning Angel [email protected] wrote:

Back on the NaCl side of things: https://github.com/Yawning/rust-crypto-nacl

It's not registered on crates.io yet since it requires the changes in #245 https://github.com/DaGenix/rust-crypto/pull/245 to not crash with the latest nightly, and for box to work. It's mostly self explanatory, and even has examples that cover the common use cases. I went against the trend and CC0ed the example code in rust-crypto-nacl because trivial "do this to encrypt/decrypt data" code snippets are trivial.

Does carving out an org for these sort of packages make sense? If not, I can just maintain this on my own (unless rust-crypto changes this sort of code shouldn't break that often).

@calvinmetcalf https://github.com/calvinmetcalf How far would you want to go? At a minimum (in my opinion) RC4, MD5, SHA1, and ECB mode should require special thought (maybe not SHA1, just because tons of thing still use it, but in the near future, the algorithm should be avoided). Part of me almost wants to heavily discourage using non authenticated encryption/decryption (since the library provides AEAD modes), but that would probably be overly painful to users...

— Reply to this email directly or view it on GitHub https://github.com/DaGenix/rust-crypto/issues/236#issuecomment-73356488.

calvinmetcalf avatar Feb 07 '15 14:02 calvinmetcalf

@calvinmetcalf Hmm. I'm somewhat torn between "unsafe" vs "feature gating" as being better. Unsafe blocks allow the developer to do an awful lot of things that are scary that don't really have anything to do with "the cryptographic soundness of various primitives".

The only AEAD mode that has decent-ish performance right now is chacha20poly1305 as well, which is probably somewhat limiting to people (GCM-AES would probably be usable if the GHASH code used PCLMULQDQ, but to make it go really fast requires a gigantic blob of assembly because stiching is a big boost).

Maybe this discussion should be carved out into a separate issue "How to mark weak/questionable/dangerous routines"...

Yawning avatar Feb 07 '15 15:02 Yawning

Too bad the only other hmacs that is standardized is cbc sha hmac as cbc could be considered unsafe, maybe hold off on unauthenticated encryption for now

On Sat, Feb 7, 2015, 10:31 AM Yawning Angel [email protected] wrote:

@calvinmetcalf https://github.com/calvinmetcalf Hmm. I'm somewhat torn between "unsafe" vs "feature gating" as being better. Unsafe blocks allow the developer to do an awful lot of things that are scary that don't really have anything to do with "the cryptographic soundness of various primitives".

The only AEAD mode that has decent-ish performance right now is chacha20poly1305 as well, which is probably somewhat limiting to people (GCM-AES would probably be usable if the GHASH code used PCLMULQDQ, but to make it go really fast requires a gigantic blob of assembly https://www-ssl.intel.com/content/dam/www/public/us/en/documents/white-papers/communications-ia-galois-counter-mode-paper.pdf because stiching is a big boost).

Maybe this discussion should be carved out into a separate issue "How to mark weak/questionable/dangerous routines"...

— Reply to this email directly or view it on GitHub https://github.com/DaGenix/rust-crypto/issues/236#issuecomment-73368756.

calvinmetcalf avatar Feb 07 '15 17:02 calvinmetcalf

How could dnaq/sodiumoxide fit with this issue and rust-crypto?

naturallymitchell avatar Mar 13 '16 15:03 naturallymitchell

Any follow-up on this issue? I'm interested in crypto_box / crypto_secretbox API. The hsalsa20 is already exported. Is this still seems out of scope for this crate? (or is this crate maintained at all?)

tailhook avatar Apr 10 '18 11:04 tailhook