Skip to content

Remove (most) cryptographic algorithms from Rust #9744

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

Merged
merged 7 commits into from
Oct 28, 2013

Conversation

DaGenix
Copy link

@DaGenix DaGenix commented Oct 6, 2013

Remove the Sha1, Sha2, MD5, and MD4 algorithms. SipHash is also cryptographically secure hash function and IsaacRng is a cryptographically secure RNG - I left those alone but removed comments that implied they were suitable for cryptographic use. I thought that MD4 was used for something by the compiler, but everything still seems to work with it removed, so, I guess not.

One thing that I'm not sure about - workcache.rs and workcache_support.rs (in librustpkg) both depend on Sha1. Without Sha1, the only hash function left is SipHash, so I switched that code over to use SipHash. The output size of SipHash is only 64-bits, however - much less than 160 for Sha1. I'm not sure this is a problem. Without other cryptographic hashes in the tree, I'm not sure what else to do. I considered moved Sha1 into librustpkg, but I don't know if that makes sense.

If merged, this closes #9300.

@huonw
Copy link
Member

huonw commented Oct 6, 2013

Are you going to make/maintain a third party repo with this stuff in it?

@bluss
Copy link
Member

bluss commented Oct 7, 2013

If the Sha1 was used to create a mapping to a strictly unique ID, then SipHash can't replace it; it is not the same type of cryptographic hash function. Deduplication/Unique IDs (like git) needs a hash function like for example SHA-1, SHA-2 or BLAKE2.

Regarding SipHash, Rust must simply bite the bullet and commit to supporting it right? And if we do that, I think SipHash should be available to rust users as well, with full documentation.

@DaGenix
Copy link
Author

DaGenix commented Oct 7, 2013

I don't know a ton about SipHash, but, besides the small output size of 64 bits, why is it not suitable as a replacement for Sha1 for this particular purpose? As best as I can tell, SipHash is a cryptographically strong MAC function, which I believe implies it has the same basic characteristics of Sha1 (pre-image resistence, 2nd pre-image resistance, and collision resistence). It is a MAC, so it requires a key, but, using a fixed key, AFAIK, it basically acts just like Sha1 or any other cryptographic hash function. As I said, I'm no expert in SipHash, so, please correct me on anything that I'm wrong about!

I certainly agree that Sha1 (or a Sha2 variant) would be a better choice. But, if those are to be removed, I'm not sure what else to use here. I guess other options would be to keep Sha1 around and maybe move it to rustpkg, but, if the goal is to get rid of cryptographic functions in the rust libraries, that doesn't seem ideal. Another option would be to write a wrapper around OpenSSL or NSS or some other library and then integrate that library into Rust. That does feel pretty heavyweight, though.

I believe Rust uses SipHash to prevent DOS attacks on its hash tables. So, I don't think removing it is really possible. I don't think any of these changes increase or decrease the usability of SipHash. Was your comment mostly a general comment or is there something I did accidentally that decreased the usability of SipHash for users?

@DaGenix
Copy link
Author

DaGenix commented Oct 7, 2013

I guess the other weakness of SipHash is that its very new and hasn't received anywhere near the scrutiny of Sha1 or the Sha2 family. Although, I don't know how bad that is for this particular use case.

@dcrewi
Copy link
Contributor

dcrewi commented Oct 7, 2013

I have started writing a wrapper around OpenSSL's libcrypto for my own use. The hashing part of it seems pretty solid now, so it could save someone some time if that's the direction chosen.

@DaGenix
Copy link
Author

DaGenix commented Oct 7, 2013

@huonw If this pull request is merged, I am planning on moving all of the deleted Digest functions (except maybe MD4) to their own separate module.

@bluss
Copy link
Member

bluss commented Oct 7, 2013

SipHash simply doesn't have any security claim about collision resistance. (Authors write We comment that SipHash is not meant to be, and (obviously) is not, collision-resistant.) All applications of SipHash should use a secret key.

What I meant was that the big disclaimer inserted in the siphash docs shouldn't be necessary. Protection against hash-flooding is a feature of Rust and it should be supported fully IMO, so no need to disclaim siphash, just describe it for what it is in the docs.

@DaGenix
Copy link
Author

DaGenix commented Oct 7, 2013

OK, I'm convinced. SipHash is not a good choice. What's to be done then? Leave in the algorithms until someone merges in an OpenSSL wrapper? Something else?

@alexcrichton
Copy link
Member

I'm attempting to get in contact with some security folks at Mozilla to get their opinions on what we should do about these digest functions. Let's hold off on merging until I get a response back from them.

@huonw
Copy link
Member

huonw commented Oct 15, 2013

(If this crypto stuff does get moved into an external repo, adding it to Rust CI would make sure it stays up-to-date; or, at least, one is alerted to breaking changes at most 24 hours after they happen.)

@DaGenix
Copy link
Author

DaGenix commented Oct 16, 2013

@huonw Rust CI does look pretty cool. I've gone ahead and created a project that has all the Digests and other crypto related work that I've done: https://github.com/DaGenix/rust-crypto. I also added it to Rust CI.

@alexcrichton
Copy link
Member

I haven't forgotten about this! My emails aren't getting responded to much, but I plan on bringing this up at the next meeting again.

@alexcrichton
Copy link
Member

Alright, the consensus at today's meeting was to remove all hashing algorithms that aren't used by the compiler itself, but leave the ones that are used by the compiler. I believe that this would leave sha1 around while jettisoning all of the other ones.

I think we should also have a comment on the module saying that it's probably not suitable for crypto purposes, but that it will be maintained by us to fix bugs in the implementation (not security bugs).

If you've run out of time recently, I can open an issue for this, but otherwise thanks for being patient!

@DaGenix
Copy link
Author

DaGenix commented Oct 23, 2013

@alexcrichton - A couple questions:

  1. The meeting minutes (https://github.com/mozilla/rust/wiki/Meeting-weekly-2013-10-22) say to leave in the Sha variants - does that mean leaving in Sha2 as well as Sha1?
  2. If Sha2 is to be removed, the only remaining user of Sha1 that I can find in the tree is workcache. I'm not super familiar with the workcache code, but, is it used by anything except ruskpkg? If its only used for ruskpkg, workcache and Sha1 could both be moved out of libextra and made private parts of rustpkg. If workcache does need to stay in libextra, what about allowing it to accept a hash function to use as a parameter, thus also allowing Sha1 to move out of libextra and into rustpkg?
  3. If comments should be added to Sha1 that its not suitable for cryptographic purposes, what about adding similar comments to SipHash? One use of SipHash is to prevent DOS attacks on hash tables - which is how Rust uses it. However, another use is as a MAC on short messages (https://en.wikipedia.org/wiki/SipHash), which seems to be a cryptographic use. Should SipHash have comments added that its not suitable for crypotgraphic purposes? If I'm understanding what @blake2-ppc is saying, he advocates that such comments are not necessary, but that seems inconsistent with the direction to add those types of comments to Sha1. Maybe I'm misunderstanding something, though.

@alexcrichton
Copy link
Member

@catamorphism would know more about the direction that rustpkg is going in. I think that we intend for workcache to remain part of libextra (or whatever libextra becomes), but taking a hash as a parameter and moving sha1 into rustpkg seems like a good idea to me. That being said, it certainly doesn't have to get done in this pull request, we can open an issue on this migration.

I personally cannot say with 100% certainty that I'm confident that our SipHash implementation can be used for cryptographic purposes (like MACs as you mentioned), so I would be more comfortable with a message saying that we have not verified these for cryptographic use.

We will continue to fix bugs and maintain these implementations, but there's no goal for us to verify the rust codebase as suitable for crypto purposes. (or at comment along the lines of that).

@DaGenix
Copy link
Author

DaGenix commented Oct 23, 2013

Updated the pull request. It turns out that its easier than I though to remove the uses of Sha1 from workcache - Sha1 was only being used by two functions: one of which was unused (are there plans to add a warning for unused private functions?) and the other was only used by a test. I believe that that test was just hashing small files, so, instead of hashing the file contents, I just modified the test to use the file contents directly. This wouldn't be practical for larger files, of course. But, I think its fine for the test. I moved Sha1 and supporting code over to librustpkg. I've left in the patches that add comments to the SipHash and IsaacRng code, but I'm happy to remove those patches if that's not desired. While I was making changes, I also updated workcache_support to allocate Sha1 instances on the stack instead of the heap.

@huonw
Copy link
Member

huonw commented Oct 23, 2013

I've left in the patches that add comments to the [...] IsaacRng code, but I'm happy to remove those patches if that's not desired

I've put some comments about cryptographic security in #9810 (e.g. general overview and ISAAC specific), so feel free to drop the std::rand comments if you think I've worded it strong enough (or drop it anyway and tell me to word mine stronger, or don't drop them at all and let me rebase on top of these changes).

(On that note, this one needs a rebase too.)

@DaGenix
Copy link
Author

DaGenix commented Oct 24, 2013

Rebased. Dropped the patch that added comments to the rand module and also the patch that changed workcache_support since both are no longer necessary.

@@ -523,7 +508,7 @@ fn test() {
let pth = pth.clone();

// FIXME (#9639): This needs to handle non-utf8 paths
prep.declare_input("file", pth.as_str().unwrap(), digest_file(&pth));
prep.declare_input("file", pth.as_str().unwrap(), io::read_whole_file_str(&pth).unwrap());
Copy link
Member

Choose a reason for hiding this comment

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

Is this intended? This doesn't seem to be calculating the hash on the contents anywhere else?

Copy link
Author

Choose a reason for hiding this comment

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

This is the only place in libextra that Sha1 (or any other hash) is being used. The declare_input() function takes 3 parameters - a kind ("file"), name, and a value which was previously the Sha1 digest of the file. Nothing I can see in the workcache code requires that the 3rd argument be a Sha1 Digest, however. Since this is just a test case and we know that the file is going to be pretty small, what I'm thinking is that we can just use the file contents directly instead of hashing them first. If Sha1 were still in libextra, this would be a bit silly of course. But, it also seems to be a bit overkill to keep Sha1 in libextra just to support this one test case.

Copy link
Member

Choose a reason for hiding this comment

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

Oh sorry about that! I didn't even realize that this was in a test case. Yeah this is totally not a reason to keep sha1 sticking around in libextra.

@DaGenix
Copy link
Author

DaGenix commented Oct 26, 2013

Rebased. Also, added a patch to fold the cryptoutil and digest modules into the sha1 module.

@DaGenix
Copy link
Author

DaGenix commented Oct 28, 2013

Rebased to replace calls to io::read_whole_file_str() which no longer exists.

bors added a commit that referenced this pull request Oct 28, 2013
Remove the Sha1, Sha2, MD5, and MD4 algorithms. SipHash is also cryptographically secure hash function and IsaacRng is a cryptographically secure RNG - I left those alone but removed comments that implied they were suitable for cryptographic use. I thought that MD4 was used for something by the compiler, but everything still seems to work with it removed, so, I guess not.

One thing that I'm not sure about - workcache.rs and workcache_support.rs (in librustpkg) both depend on Sha1. Without Sha1, the only hash function left is SipHash, so I switched that code over to use SipHash. The output size of SipHash is only 64-bits, however - much less than 160 for Sha1. I'm not sure this is a problem. Without other cryptographic hashes in the tree, I'm not sure what else to do. I considered moved Sha1 into librustpkg, but I don't know if that makes sense.

If merged, this closes #9300.
@bors bors closed this Oct 28, 2013
@bors bors merged commit 2d5cb5d into rust-lang:master Oct 28, 2013
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.

Reconsider distribution of cryptographic hash functions
6 participants