-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Figure out in-tree crypto story #14655
Comments
There's some pure-Rust work on https://github.com/DaGenix/rust-crypto. http://nacl.cr.yp.to/ is probably among the most trustworthy libraries at this point, but hasn't been (to my knowledge) widely deployed. |
Oh, and I almost forgot about https://github.com/dnaq/sodiumoxide, which is an initial attempt at binding libsodium |
Is the goal of the crypto library to provide rust interfaces to a wide set of commonly used algorithms? If so, I don't think NaCL / libsodium are a great fit since I don't believe they include algorithms such as MD5 or TLS. |
For just making things secure NaCL seems to be the go to library, but it only supports certain cryptographic primitives which make it not at all useful for a library that wants to provide general cryptographic code. It is not designed to be a general purpose one stop shop cryptographic library. For example it will be impossible to create a standards complying TLS implementation with NaCL because it does not provide AES CBC. Some cryptographic functions that NaCL does not support:
For what its worth Go implements most of their cryptographic code in Go (however Adam Langley has admitted that they have not mitigated timing attacks in their crypto/rsa package). |
FWIW, I am contributor to the cryptography library for Python. You can consider taking the approach we did here and design a "pluggable" API that bindings existing C libraries. For a general purpose crypto library, NaCL is almost definitely not a good fit because common algorithms aren't present in it. While there has been much bad press about OpenSSL lately, it is really the most viable library to wrap since it is available on all common platforms and almost certainly already installed on Linux distros. The current scrutiny on it should do well to turn up security bugs as well. Our API also allows other C libraries to be used (we bind commoncrypto on OS X as well, and I have PolarSSL bindings in the works.) If designed well, I can see the potential Rust crypto library at first being dependent on C bindings but eventually gets seamlessly replaced by Rust code without much backwards incompatibility. |
I highly recommend you package something like NaCl as a high-level crypto interface - call it "crypto/box" or similar. This is the package you want the vast majority of application developers to use. Other specific protocols should similarly be packaged in high-level interfaces when it makes sense to provide them, e.g. "crypto/tls". While a lower-level set of primitives is necessary for protocol implementers, documentation and naming conventions should steer people away from them. Call this package "crypto/low-level" or "crypto/arcane" or something like that. |
This Rust crypto library should be mentioned (surprised it hasn't been): ClearCrypt |
ClearCrypt is not a general-purpose crypto library but an implementation of On Thu, Jun 5, 2014 at 10:04 AM, Greg Slepak [email protected]
|
@cmr: ClearCrypt contains many parts of a general-purpose crypto library, similar to how OpenSSL does (though it's an implementation of the SSL/TLS protocol). |
It doesn't now, and since it won't have the mess of supported ciphers etc On Thu, Jun 5, 2014 at 10:14 AM, Greg Slepak [email protected]
|
Right, it's a WIP, I just wanted to mention it. I hope I didn't offend you by doing so. ;) |
We do also have the https://github.com/sfackler/rust-openssl bindings, maintained by @sfackler and myself. |
I would also like to point out the silliness of inventing a safe programming language only to encourage writing bindings back to C. HT to @dchest for phrasing that so well. |
The "sillyness" comes from new crypto requiring audits by cyptographers. The Rust team doesn't have any dedicated at the moment. So it's "safer" to use already-audited code in C. |
Uh huh. And which code would that be? |
Hopefully LibreSSL in the not so distant future? |
LibreSSL is only going to be portable if and when OpenBSD starts receiving funding for it, and there's not a great history of OpenBSD projects receiving funding. |
NSS would fit the cross-platform bill too. It's used in Firefox, after all.
I can understand why for some things, but then choosing OpenSSL at this point would make most people wonder what's the point of Rust after all. |
Most of the flaws in the most recent OpenSSL security advisory are not related to memory safety. |
Just to put it on the record, I am one of those people. 👍 |
Also, sorry to be off-topic, but @glandium, have you realized that your "randomly generated" GitHub profile picture is flipping all of us off? ;) |
SUPERCOP includes many highly optimized implementations of a wide variety of crypto primitives. The trouble is that it is absolutely not designed to make them available to programming languages, only to benchmark them. Using them is hard work! I wrote this tool which builds a shared library out of SUPERCOP primitives - it was not straightforward: http://hg.opensource.lshift.net/bletchley-primitives/file/tip |
In a perfect world, I think Rust would provide an abstract, high-level API for encryption backed by multiple "providers" ala the Java Cryptography Architecture: http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#Design This approach would allow Rust to have a cryptography story without actually having to vendor or otherwise ship actual encryption code as part of the core distribution. Instead, ship the multi-provider API as part of core Rust, and developers can plug in the provider modules that are appropriate to a particular purpose. |
@tarcieri That's a good idea. Seems like the right approach. 👍 |
In what way is crypto different from other algorithms provided in standard libraries, that crypto needs a provider architecture but other algorithms don't? I think JCA exists because of legal problems at the time with directly shipping crypto libraries, not some technical reason. |
Agility around algorithms is more important in crypto than it is with your average data structure. A multi-provider architecture lets you supply a wider range of algorithms than are available in a single library under a single API, and likewise swap out bad algorithms for good ones in the future. |
I can see the advantages of being able to naturally express things like "this block cipher used in counter mode provides a stream cipher" but that seems like an application for subtyping/trait implementation rather than for a provider architecture. Can you give an example of the kind of scenario where you're glad you used a provider architecture? |
I made a remark about this issue in my talk at Mozilla SF in December 2014 and I just wanted to clarify. My remark was specifically that Rust should not have an in-tree crypto story, and it highlighted this issue. This comes with some caveats. My intended point was about implementing ciphers (and crypto-protocols built on them) in-tree, and saying I thought that was a bad idea. My analogy was to Ruby's OpenSSL extension, which is a binding to OpenSSL that is an intractable part of the standard library. There is an effort underway to rip OpenSSL out of the Ruby standard library and move it into an out-of-tree external package. Rust has various in-tree APIs for hash functions (e.g. tl;dr: hash functions are fine, but please leave encryption ciphers and public-key digital signature algorithms (and especially crypto protocols!) to out-of-tree libraries developed by crypto experts. |
Say a little more about why hash functions are an exception? Thanks! |
First, there is one hash function you absolutely do want in the standard library: something like SipHash to use as the basis of a (hashDoS-resistant) hashing function: http://doc.rust-lang.org/0.11.0/collections/hash/sip/fn.hash.html Without a cryptographically secure hash function like SipHash, any time an attacker provides the data to be put into e.g. a Secondly, having hash functions in the standard library also gets you around the bootstrapping problem of how to verify artifacts in the package manager for the language itself. |
It's very easy verify that a custom hash implementation is correct, especially in rust where you don't have to worry about memory safety as much. Checking an entire protocol or cipher is much more difficult, because there are so many possible execution paths. |
Modern block ciphers and stream ciphers both tend to be incredibly simple, and there aren't multiple execution paths in general. It's not significantly different from hashes. |
@tarcieri: Having a secure random number generator for the hash seeds and other use cases means having a stream cipher implementation too. |
@thestinger you need an API for getting cryptographic randomness, but you only need to use it once at the time the program starts. Once you have the key for SipHash seeded you can reuse the same key for all hashing operations globally. I say this specifically in regard to hashDoS. |
Totally support SipHash. But I'm not sure I see the point of including other hash functions. Without a public key signature scheme, you can only verify hashes you already hold, which seems pretty limiting for the applications you set out. A secure random number generator does seem desirable, but it's a very tricky proposition—it's very platform dependent, it's likely to depend on a good stream cipher and a good hash function, and if there's any platform on which you find you need to do your own entropy management you'll end up in deep water fast. I'm not sure it's a good feature to try to standardize for the 1.0 release. |
Also small terminological note: SipHash is a PRF, not a message digest function like SHA-2/Blake2. |
It's not a hash function, it's a PRF? Really? Next you'll be telling me it's not a block cipher, it's a PRP 😉 Anyway, I think your point was that people shouldn't be using SipHash for anything other than the hash function driving e.g. a HashMap data structure, in which case, yes, that's true. SipHash is definitely not fungible with e.g. SHA-2/Blake2 and people shouldn't be using it unless they know what they're doing. |
@ciphergoth: SipHash is useless without a seed, so the OS requirements are the same for both SipHash and a CSPRNG... the requirements are there on every platform Rust supports. |
@ciphergoth: A stream cipher is trivially a CSPRNG. There's nothing else that's required. You need to retrieve an initial seed from the operating system, as you do for any kind of DoS secure hashing scheme. Re-seeding it is optional and can actually hurt rather than helping. Not providing a fast CSPRNG means that people are going to use an insecure RNG for cases where they should not... the absence of the feature is a security vulnerability in practice. |
@ciphergoth re: verifying artifacts, what you said is true, however even with just hash functions you can decompose the dependencies into a Merkle tree, so for example a bootstrapping tool can pull in all of its subresources and confirm their integrity, with each of them pinned to specific digests. With something like that, rustc bootstrap could have cryptographic integrity. |
If all the platforms you need to run on can provide a good seed then I take it all back, including an RNG is very desirable. I still feel there's a very strong presumption against including things in 1.0, since if you leave something out and it was a mistake you can include it later, but if you put it in or give it the wrong API you are in big trouble. Since Rust has a good dependency management story it doesn't seem like a big problem to use that to get hold of the functions you need. |
A seed is obviously needed for SipHash to be worth anything so I don't understand the distinction you're making. |
It really doesn't. The most that can be said is that it has one. It's awful at doing proper reproducible releases and is yet another insecure packager manager without a package signing story or proper system integration. Of course, you can't expect much when compiler snapshots are built on third party cloud infrastructure. Each Xen vulnerability leaves Rust's compiler snapshots wide open to attacks from anything else on those machines. |
OT: @thestinger I would be keen to read a detailed blog post by you containing all Rust-related issues you have. You notice a lot, and the one about package signing is quite interesting. |
@tshepang FWIW I made an issue about that here: rust-lang/crates.io#75 |
Are you saying that the issues you raise with Crate are a reason to put things in-tree? |
@ciphergoth no, I already gave my rationale for that above (see rustc bootstrap and subresource integrity) |
Can you describe the sort of scenario you're thinking of in more detail? The hash of some other resource is included in the Rust sources themselves—what sort of resource do you have in mind and at what stage is it fetched? Also note that you currently have to have Python installed to build rustc; at a pinch you could use a hash function built into Python as a bootstrapping aid. I don't yet see a compelling enough picture to overcome the leave-things-out presumption, but it's very possible you're right and I'm just not seeing the whole picture. |
I was really making a more general statement about the utility. I don't have some master plan mapped out in my head. |
I think it would probably be safe to add the hash function to the sources in the same change that makes use of it. |
Sure, my point wasn't that hash functions should be included right now, merely that they should be "allowed" FWIW, SHA256 already appears to be in the rustc sources: |
Oh interesting, thanks! It's used here as part of a mangling strategy for symbols and crate names. https://github.com/rust-lang/rust/blob/master/src/librustc_trans/back/link.rs#L75 I share your sense that I'm less alarmed at seeing a hash function in the sources than pretty much any other cryptographic primitive! |
Hmm, I see that Rust vendors a Rust implementation of ChaCha20 for use as a PRNG: https://github.com/rust-lang/rust/blob/master/src/librand/chacha.rs Hard to say how I feel about that. I'm curious if anyone knows if that gets exposed with the name "secure" on it anywhere, or how the key is generated? This is all I could find on it: |
I'm pulling a massive triage effort to get us ready for 1.0. As part of this, I'm moving stuff that's wishlist-like to the RFCs repo, as that's where major new things should get discussed/prioritized. This issue has been moved to the RFCs repo: rust-lang/rfcs#766 |
We've previously made the decision not to distribute any crypto with Rust at all, but this is probably not tenable since crypto is used everywhere. My current opinion is that we should not distribute any crypto written in Rust, but that distributing bindings to well-regarded crypto is fine.
Figure out a strategy here, build consensus, then start implementing a robust crypto library out of tree, with the goal of merging into the main distribution someday. There are some existing efforts along these lines that should be evaluated for this purpose.
The text was updated successfully, but these errors were encountered: