admin管理员组

文章数量:1287581

In Rust I have an impl Hash from a third party crate. How do I calculate a cryptographic hash of it, e.g. SHA1 or SHA3?

As far as I can tell the hasher objects in the sha1 and sha3 crates don't implement the Hasher trait, presumably because it's not really designed for cryptographic purposes (Hasher::finish() returns u64). However I don't see why they can't impl Hasher and then just provide their own finish() methods that return the full hash instead of u64.

Does something like that exist?

Please avoid lectures about security; I am already fully aware.

In Rust I have an impl Hash from a third party crate. How do I calculate a cryptographic hash of it, e.g. SHA1 or SHA3?

As far as I can tell the hasher objects in the sha1 and sha3 crates don't implement the Hasher trait, presumably because it's not really designed for cryptographic purposes (Hasher::finish() returns u64). However I don't see why they can't impl Hasher and then just provide their own finish() methods that return the full hash instead of u64.

Does something like that exist?

Please avoid lectures about security; I am already fully aware.

Share Improve this question edited Feb 23 at 21:46 Timmmm asked Feb 23 at 19:50 TimmmmTimmmm 97k80 gold badges409 silver badges579 bronze badges 7
  • I may be confused but how does the standard library Hash trait come into play here? – squiguy Commented Feb 23 at 21:11
  • The normal way to use std::hash::Hash is to create a std::hash::Hasher (e.g. std::hash::SipHasher) and then call the_std_hash_Hash.hash(&mut the_sip_hasher), then the_sip_hasher.finalize(). std::hash::Hasher has finalize(). Yeah it's kind of confusing. – Timmmm Commented Feb 23 at 21:31
  • That was a typo. Fixed. Why are you downvoting this? – Timmmm Commented Feb 23 at 21:46
  • The only thing I would bring up is Hash's portabilty. It's not really designed to be a stable interface outside of the current running process. How data is passed to the Hasher is generally an implementation detail and not to be replied upon. Could be fine for your use case but I wanted to mention it just in case. – kmdreko Commented Feb 23 at 22:50
  • "Why are you downvoting this?" — I did not... Though if I had to take a guess it contains some fluff that is at best tangential to the question. "Does something like this exists" also comes awefully close to "Seeking recommendations for software libraries, tutorials, tools, books, or other off-site resources" – cafce25 Commented Feb 23 at 23:03
 |  Show 2 more comments

1 Answer 1

Reset to default 5

Ok I figured it out and it wasn't too hard, though I'm kind of surprised I'm the first person to run into this. Anyway...

use std::hash::{Hash, Hasher};

// Note you can import the `digest` crate directly if you don't want to
// depend on sha3. But since I'm using sha3 I just get it via the re-export.
use sha3::digest::{Output, Digest};

pub fn hash_digest<H: Hash, D: Digest>(hash: H, digest: D) -> Output<D> {
    let mut digest_hasher = DigestHasher { digest };
    hash.hash(&mut digest_hasher);
    digest_hasher.digest.finalize()
}

pub struct DigestHasher<D: Digest> {
    digest: D,
}

impl<D: Digest> Hasher for DigestHasher<D> {
    fn finish(&self) -> u64 {
        unimplemented!("Do not call finish()");
    }

    fn write(&mut self, bytes: &[u8]) {
        self.digest.update(bytes);
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[derive(Hash)]
    struct TestHash {
        name: String,
        age: u64,
    }

    #[test]
    fn test_hash_digest() {
        let hash = TestHash { name: "dave".to_string(), age: 5 };
        let digest = sha3::Sha3_256::new();
        let output = hash_digest(hash, digest);
        assert_eq!(format!("{output:#x}"), "8b8ae45bfe6457ca91313ef2dd51b2e94aa93615ab85e2f833f9c8cfaa81c183");
    }
}

本文标签: rustHow to calculate the sha1sha3 hash of an impl HashStack Overflow