-
-
Notifications
You must be signed in to change notification settings - Fork 761
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
Improve Hasher and HMAC APIs #141
Conversation
Hmm, also thinking of renaming update() to push() because the name doesn't seem to make much sense in its new context. |
Sorry for the delay on getting to this. Could this be adjusted to implement libstd's redesigned |
I'll look into it. |
The way Hash is implemented for &str and &[T] makes me question this idea: it mixes extra data into the input so the Hasher results would be incompatible with everyone else. impl<S: Writer + Hasher> Hash<S> for str {
#[inline]
fn hash(&self, state: &mut S) {
state.write(self.as_bytes());
0xffu8.hash(state)
}
}
impl<S: Writer + Hasher, T: Hash<S>> Hash<S> for [T] {
#[inline]
fn hash(&self, state: &mut S) {
self.len().hash(state);
for elt in self.iter() {
elt.hash(state);
}
}
} EDIT: Unless we can specialize the Hash impls to do the right thing maybe... But we don't seem to be allowed that.
|
What do you mean by "incompatible with everyone else"? Hash functions typically act on byte streams, not strings. If you want to pass the underlying byte slice of a str to a Hasher, you can call |
I'm missing the reason to implement it then. I assumed that the purpose of let md = std::hash::hash::<_, openssl::crypto::hash::Hasher>(str_or_byte_slice); but the result would be incorrect. Not to mention the |
Here's the |
We can get around the &mut self/&self restrictions since we're only passing raw pointers around. We can grab const pointers and then cast to a mut pointer. |
There's nothing preventing users from invoking |
Hmm, yeah that's true. In that case, I think the most reasonable thing to do is to not implement The Thanks! |
Sounds like a plan! |
It should be noted that the |
I'd have to check the OpenSSL source (shudder), but my guess is that |
Isn't it ridiculous though that eventually one would have to put use std::io::Writer;
use std::hash::Hasher;
use openssl::crypto::hash::Hasher; in order to call Could this be a shortcoming in Rust? Maybe implementing a trait shouldn't unconditionally hide the methods that are essential to the struct. What if there was something like trait T { pub fn smth(); };
struct S;
impl S {
pub fn smth() { /* do smth */ }
}
impl T for S {
#[take_from_struct]
fn smth();
} I bet there's a discussion or an RFC about it somewhere. |
@gankro and I have talked about the addition of "inherent" implementations of traits, where the methods on that trait would always be callable on the type without having to import it. I expect an RFC should be landing about it from someone shortly after 1.0 releases. |
That's good to know :) |
|
Scratch that. |
@alexcrichton may be interested in this information |
Python works around this limitation by providing
|
So the incompatibility might not be a fundamental one after all... ducks |
The latest version drops |
This seems good to me. Do you think this is ready to go? |
For a more consistent experience |
I've just remembered a slight issue with using asserts to check the return values. |
There, |
Cool. I think I'll merge this after the big io -> old_io change lands to avoid having to bump major versions twice in a row: rust-lang/rust#21543 |
Okay. I'm adding the |
👍 |
- Implement Clone and std::io::Writer. - Reduce the API to write() and finish(). Contrary to std::hash, finish() resets the hasher immediately. - Add hmac::hmac() convenience fn. - Replace hash::evpmd() with HashType methods. - Add assertions as a crude check for failed calls into openssl. - Add examples and some tests. [breaking-change]
s/HashType/Type/ to follow the current Rust style. Import Type as HashType in modules where the name might be ambiguous. [breaking change]
Rebased. |
Thanks! |
The reuse API I implemented for Hasher the last time proved to be very hard to use. Here's a better approach that relies on the borrow checker by using a mut reference. This time it's both Hasher and HMAC.
Note that Accumulator now has very similar methods update() and write(). It could make sense to drop update(), although write() requires checking the return value...