Collection of cryptographic hash functions written in pure Rust

Overview

RustCrypto: hashes Project Chat dependency status

Collection of cryptographic hash functions written in pure Rust.

All algorithms reside in the separate crates and implemented using traits from digest crate. Additionally all crates do not require the standard library (i.e. no_std capable) and can be easily used for bare-metal or WebAssembly programming.

Supported algorithms

Note: For new applications, or where compatibility with other existing standards is not a primary concern, we strongly recommend to use either BLAKE2, SHA-2 or SHA-3.

Name Algorithm Crates.io Documentation Build Status Security
blake2 BLAKE2 crates.io Documentation build ๐Ÿ’š
gost94 GOST94 (GOST R 34.11-94) crates.io Documentation build ๐Ÿ’›
groestl Grรธstl (Groestl) crates.io Documentation build ๐Ÿ’š
k12 KangarooTwelve crates.io Documentation build ๐Ÿ’š
md2 MD2 crates.io Documentation build ๐Ÿ’”
md4 MD4 crates.io Documentation build ๐Ÿ’”
md-5 โ— MD5 crates.io Documentation build ๐Ÿ’”
ripemd160 RIPEMD-160 crates.io Documentation build ๐Ÿ’š
ripemd320 RIPEMD-320 crates.io Documentation build ๐Ÿ’š *
sha-1 โ— SHA-1 crates.io Documentation build ๐Ÿ’”
sha2 SHA-2 crates.io Documentation build ๐Ÿ’š
sha3 SHA-3 (Keccak) crates.io Documentation build ๐Ÿ’š
shabal SHABAL crates.io Documentation build ๐Ÿ’š
streebog Streebog (GOST R 34.11-2012) crates.io Documentation build ๐Ÿ’›
tiger Tiger crates.io Documentation build ๐Ÿ’š
whirlpool Whirlpool crates.io Documentation build ๐Ÿ’š

NOTE: the BLAKE3 crate implements the digest (and crypto-mac) traits used by the rest of the hashes in this repository, but is maintained by the BLAKE3 team.

* RIPEMD-320 provides only the same security as RIPEMD-160

Crate names

Whenever possible crates are published under the the same name as the crate folder. Owners of md5 and sha1 crates declined (1, 2) to participate in this project. This is why crates marked by โ— are published under md-5 and sha-1 names respectively.

Security Level Legend

The following describes the security level ratings associated with each hash function (i.e. algorithms, not the specific implementation):

Heart Description
๐Ÿ’š No known successful attacks
๐Ÿ’› Theoretical break: security lower than claimed
๐Ÿ’” Attack demonstrated in practice: avoid if at all possible

See the Security page on Wikipedia for more information.

Minimum Supported Rust Version (MSRV)

All crates in this repository support Rust 1.21 or higher. In future minimally supported version of Rust can be changed, but it will be done with a minor version bump.

Usage

Let us demonstrate how to use crates in this repository using BLAKE2b as an example.

First add blake2 crate to your Cargo.toml:

[dependencies]
blake2 = "0.9"

Note that crates in this repository have an enabled by default std feature. So if you plan to use the crate in no_std enviroments, don't forget to disable it:

[dependencies]
blake2 = { version="0.9", default-features = false }

blake2 and other crates re-export digest crate and Digest trait for convenience, so you don't have to add digest crate as an explicit dependency.

Now you can write the following code:

use blake2::{Blake2b, Digest};

let mut hasher = Blake2b::new();
let data = b"Hello world!";
hasher.update(data);
// `update` can be called repeatedly and is generic over `AsRef<[u8]>`
hasher.update("String data");
// Note that calling `finalize()` consumes hasher
let hash = hasher.finalize();
println!("Result: {:x}", hash);

In this example hash has type GenericArray<u8, U64>, which is a generic alternative to [u8; 64].

Alternatively you can use chained approach, which is equivalent to the previous example:

use blake2::{Blake2b, Digest};

let hash = Blake2b::new()
    .chain(b"Hello world!")
    .chain("String data")
    .finalize();
println!("Result: {:x}", hash);

If the whole message is available you also can use convinience digest method:

use blake2::{Blake2b, Digest};

let hash = Blake2b::digest(b"my message");
println!("Result: {:x}", hash);

Hashing Readable objects

If you want to hash data from Read trait (e.g. from file) you can rely on implementation of Write trait (requires an enabled-by-default std feature):

use blake2::{Blake2b, Digest};
use std::{fs, io};

let mut file = fs::File::open(&path)?;
let mut hasher = Blake2b::new();
let n = io::copy(&mut file, &mut hasher)?;
let hash = hasher.finalize();
println!("Path: {}", path);
println!("Bytes processed: {}", n);
println!("Hash value: {:x}", hash);

Hash-based Message Authentication Code (HMAC)

If you want to calculate Hash-based Message Authentication Code (HMAC), you can use generic implementation from hmac crate, which is a part of the RustCrypto/MACs repository.

Generic code

You can write generic code over Digest (or other traits from digest crate) trait which will work over different hash functions:

use digest::Digest;
use blake2::Blake2b;
use sha2::Sha256;

// Toy example, do not use it in practice!
// Instead use crates from: https://github.com/RustCrypto/password-hashing
fn hash_password<D: Digest>(password: &str, salt: &str, output: &mut [u8]) {
    let mut hasher = D::new();
    hasher.update(password.as_bytes());
    hasher.update(b"$");
    hasher.update(salt.as_bytes());
    output.copy_from_slice(&hasher.finalize())
}

let mut buf1 = [0u8; 64];
hash_password::<Blake2b>("my_password", "abcd", &mut buf1);

let mut buf2 = [0u8; 32];
hash_password::<Sha256>("my_password", "abcd", &mut buf2);

If you want to use hash functions with trait objects, use digest::DynDigest trait.

License

All crates licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Comments
  • There should be a standard way to recusively hash structs

    There should be a standard way to recusively hash structs

    std::hash::Hasher can be derived for structs and is a standard hashing interface in rust. The standard interface only allows 64bit outputs but there's nothing stopping extra outpust tailored to specific hashes. So for ergonomic purposes wouldn't it make sense to have an adapter to allow using the Hasher API?

    opened by pedrocr 60
  • switch the BLAKE2 implementation to blake2b_simd/blake2s_simd

    switch the BLAKE2 implementation to blake2b_simd/blake2s_simd

    [This is a very large change which I haven't discussed with anyone yet, so I'm not sure it's the right choice for the project. But hopefully this is a good starting point for discussion.]

    This is mostly a large performance improvement. The BLAKE2b bench_10000 case is improved by about 30%. This implementation also detects SIMD support at runtime, so the feature flags related to SIMD support are removed.

    The only performance loss is in the bench_10 cases, where the caller repeatedly feeds input slices less than one block long. The BLAKE2s bench_10 case is almost 20% slower. I'm not sure exactly why, but this implementation optimizes for avoiding copies on long runs of input, so it might just be that it's doing more math up front. This performance issue disappears if the inputs are a full block or longer.

    The only API consequence of this change is that the undocumented with_parameter_block constructor is no longer supported. Callers who need other parameters might prefer to use the blake2b_simd/blake2s_simd APIs directly, which expose them in a safer way through a Params object.

    opened by oconnor663 29
  • Shake output should be variable length

    Shake output should be variable length

    Sha3's shake mode should provides variable length output determined at runtime, but it's currently a user defined type level numeric. I'd think the OutputSize type of the Digest trait should be replaced by a Output type to fix this, but I have no looked into doing it.

    enhancement 
    opened by burdges 18
  • Expose round functions under separate trait

    Expose round functions under separate trait

    It would be handy to have some access to internals of e.g. SHA256/512, Blake2 family and Sha3 family to be able to manually update a state by "absorbing" a proper rate in every case. All hash families named above anyway follow a logic that some internal state is updated by processing potentially >1 round, but each round only a fixed amount of bytes is processed.

    To clarify - such trait can even be made "unsafe" as the caller would be responsible to:

    • somehow create an "empty" state (that would be great to have as a part of the trait if "raw" internal state is not pub. By "raw" I mean e.g. 512 bits of internal state of Sha256 without any extra information such as what length was processed before this point, etc)
    • call "round function" as many times as necessary, ideally using [u8; RATE] as an input, but in principle for e.g. Sha3 family [u64; RATE_IN_WORDS] may be ok. For whatever reason caller uses such a functionality, he would have to take care of all the paddings!
    • take a "state" and either provide some as_ref() for it to be able to take inner information to produce a final hash value manually (caller is 100% responsible) or (more convenient, but more work and a lot of diversities here) have some "into_hash(state)" function that would produce a hash from the state (functions with extendable output are out of the scope of this feature request, so it's kind of expected that final state will be used only once)

    It may be possible to use some feature flags, and e.g. just expose a raw "compress" function for sha256 and do it all by hands (not sure about other families if their internals are exposed to the necessary degree under feature flags), but consistent way for cases where such workflow is possible would be great (and will allow to avoid forking and butchering a crate to just add more pub)

    opened by shamatar 15
  • RIPEMD-320 implementation

    RIPEMD-320 implementation

    This partly addresses issue #13.

    This RIPEMD-320 implementation is based on the existing RIPEMD-160 implementation. It would be possible and relatively easy to refactor code to avoid so much duplication, but making this a separate crate breaks less code and makes it easy to add.

    RIPEMD-160 and RIPEMD-320 also share a similar relationship as RIPEMD-128 and RIPEMD-256 do. A quick diff between RIPEMD-160 and RIPEMD-320 implementations should be useful anyone writing RIPEMD-128/256.

    I don't know if that's OK with regard to the conventions in place, but in the tests I drew some samples from the RIPEMD-160 webpage[1] that describes expected hashes for some strings.

    Also, I have uploaded a 0.8.0-rc1 version to crates.io (under the name ripemd320). If/when you can merge this into master and publish, please ping me so I can give you access and optionally yank the rc1.

    [1] https://homes.esat.kuleuven.be/~bosselae/ripemd160.html

    opened by magnet 14
  • Obtain hash output as a String

    Obtain hash output as a String

    Currently, this results in a value of GenericArray<u8, _>:

    let input = String::from("hello");
    
    let mut hasher = Sha512::new();
    hasher.update(input);
    let hash_result = hasher.finalize();
    

    However, what I need is not a byte array but a String as output. I tried converting it with std::str::from_utf8(&hash_result[..]) but that errors out with Err(Utf8Error { valid_up_to: 0, error_len: Some(1) }) as an error value. This seems weird to me since the hash should be a hexadecimal string, but that's what I observed.

    How can I get a valid UTF-8 string from hash_result?

    question 
    opened by jjpe 13
  • Add `Blake2b-256`, `Blake2b-128`, etc. as wrappers over `VarBlake2b`.

    Add `Blake2b-256`, `Blake2b-128`, etc. as wrappers over `VarBlake2b`.

    It looks like some crates want a D: Digest<OutputSize = U64> + Default as an argument to what hash to use, so that VarBlake2b is not very useful on it's own. Eg. https://github.com/dalek-cryptography/ed25519-dalek/issues/59

    I could write my own wrapper, but if I need it, other people will, too.

    opened by dpc 13
  • sha1: switch name from sha-1 to sha1

    sha1: switch name from sha-1 to sha1

    @mitsuhiko has kindly transferred ownership of sha1 to us, so now we can publish our implementation under it instead of using sha-1.

    For user convenience, we will skip v0.7-v0.9 and will release sha1 v0.10.0, so the version will be synchronized with sha-1. I plan to continue releasing v0.10.x patch versions for sha-1 in parallel with sha1 and deprecate it only after sha1 v0.11 will be released.

    opened by newpavlov 10
  • feat(sha2): implement intrinsic based version for sha256

    feat(sha2): implement intrinsic based version for sha256

    This is not optimal yet when processing multiple blocks, but it does give a considerable speedup over the non intrinsic version already

    Measurements were taken on an AMD Ryzen 7 3700X 8-Core.

    Baseline

    test bench1_10    ... bench:          36 ns/iter (+/- 0) = 277 MB/s
    test bench2_100   ... bench:         314 ns/iter (+/- 4) = 318 MB/s
    test bench3_1000  ... bench:       3,096 ns/iter (+/- 16) = 322 MB/s
    test bench4_10000 ... bench:      30,935 ns/iter (+/- 297) = 323 MB/s
    

    With asm-hashes

    test bench1_10    ... bench:          33 ns/iter (+/- 0) = 303 MB/s
    test bench2_100   ... bench:         291 ns/iter (+/- 1) = 343 MB/s
    test bench3_1000  ... bench:       2,863 ns/iter (+/- 14) = 349 MB/s
    test bench4_10000 ... bench:      28,597 ns/iter (+/- 191) = 349 MB/s
    

    With Intrinsics

    test bench1_10    ... bench:           8 ns/iter (+/- 0) = 1250 MB/s
    test bench2_100   ... bench:          54 ns/iter (+/- 0) = 1851 MB/s
    test bench3_1000  ... bench:         511 ns/iter (+/- 8) = 1956 MB/s
    test bench4_10000 ... bench:       5,079 ns/iter (+/- 29) = 1968 MB/s
    
    opened by dignifiedquire 10
  • Digest trait cannot be made into an object

    Digest trait cannot be made into an object

    Hey, I'm very new to Rust so I apologize if this turns out to be a language misunderstanding rather than a package issue...

    I'm trying to dynamically create instances of algorithm structs that implement the Digest trait, hold on to them using a Box<Digest>, and interact with them via the Digest interface.

    In other words, something like this:

    let hasher = match "one of the algorithms" {
        "sha256" => Box::new(Sha256::new()) as Box<Digest>,
        "sha512" => Box::new(Sha512::new()) as Box<Digest>
        // ... etc
    };
    

    I sort of get why that doesn't work (missing associated types), but even if I fill those in like:

    "sha256" => Box::new(Sha256::new()) as Box<Digest<<OutputSize=U32, BlockSize=U64>>>,
    

    I'm still left with an error: the trait 'digest::Digest' cannot be made into an object.

    After poking around it seemed like this might be because of the way Digest was implemented? Looking at the docs it doesn't seem to have any static methods, but maybe it does or there's something else I'm missing?

    Again, sorry to bother you with this!

    enhancement 
    opened by WestleyArgentum 10
  • Next iteration of Digest traits

    Next iteration of Digest traits

    Sacundim in his feedback on the reddit proposed to use instead of VariableOutput the following traits:

    • ExtendableOutput for functions like SHAKE from SHA-3, which allow to "read" indefinitely from the result
    • VariableOutput for functions like Groestl, which have some limits on the output size and may require output size to be known at state initalization

    Also @burdges proposed to move out BlockSize from the Input trait to a separate one.

    opened by newpavlov 10
  • docs for hasher states could use a reference to the `Digest` trait

    docs for hasher states could use a reference to the `Digest` trait

    For someone new to the ecosystem it might be hard to tell how to use a... For example, sha3::Keccak256 (https://docs.rs/sha3/latest/sha3/type.Keccak256.html), it's just a type alias with no real info about what it is (other than some nebulous "hasher state") or how to use it. I'd recommend linking to the Digest trait in the docs as a way of explaining "how to use it"

    Additionally (if I should move this to a separate issue, let me know and I will do so) I would recommend an example specifically showing how to sha3::Keccak256::digest(b"a message") in one go. Finally, the example(s) that use update should add more than one message. This would be so that show new user why you would use new and then update rather than digest ("because you can add more than one thing").

    I would be willing to create the examples / documentation if this would be agreeable

    opened by izik1 1
  • blake2 simd benches produce unexpected results

    blake2 simd benches produce unexpected results

    I ran blake2 tests with and without simd feature enabled and found that behavior is strange and doesn't make a lot of sense.

    Default (no simd):

    $ cargo +nightly bench
    ...
    running 8 tests
    test blake2b512_10    ... bench:           8 ns/iter (+/- 0) = 1250 MB/s
    test blake2b512_100   ... bench:          74 ns/iter (+/- 4) = 1351 MB/s
    test blake2b512_1000  ... bench:         708 ns/iter (+/- 85) = 1412 MB/s
    test blake2b512_10000 ... bench:       7,005 ns/iter (+/- 531) = 1427 MB/s
    test blake2s256_10    ... bench:          13 ns/iter (+/- 0) = 769 MB/s
    test blake2s256_100   ... bench:         121 ns/iter (+/- 7) = 826 MB/s
    test blake2s256_1000  ... bench:       1,155 ns/iter (+/- 62) = 865 MB/s
    test blake2s256_10000 ... bench:      11,791 ns/iter (+/- 1,005) = 848 MB/s
    
    test result: ok. 0 passed; 0 failed; 0 ignored; 8 measured; 0 filtered out; finished in 28.22s
    

    Simd:

    $ cargo +nightly bench --features simd
    ...
    running 8 tests
    test blake2b512_10    ... bench:          11 ns/iter (+/- 0) = 909 MB/s
    test blake2b512_100   ... bench:         102 ns/iter (+/- 0) = 980 MB/s
    test blake2b512_1000  ... bench:       1,010 ns/iter (+/- 11) = 990 MB/s
    test blake2b512_10000 ... bench:      10,076 ns/iter (+/- 68) = 992 MB/s
    test blake2s256_10    ... bench:          16 ns/iter (+/- 0) = 625 MB/s
    test blake2s256_100   ... bench:         152 ns/iter (+/- 1) = 657 MB/s
    test blake2s256_1000  ... bench:       1,483 ns/iter (+/- 12) = 674 MB/s
    test blake2s256_10000 ... bench:      14,750 ns/iter (+/- 344) = 677 MB/s
    
    test result: ok. 0 passed; 0 failed; 0 ignored; 8 measured; 0 filtered out; finished in 2.43s
    

    I expected simd version to produce better results and judging by the total execution time it is the case, but throughput reported by the benchmark says the opposite.

    I suspect something is wrong with benchmarking code.

    Using latest master (cc523733e5ba84b5a366825a7d1150bbbfea368b right now) and rustc 1.65.0-nightly (20ffea693 2022-08-11).

    opened by nazar-pc 1
  • Blake2 missing functionality while migrating from `blake2-rfc`

    Blake2 missing functionality while migrating from `blake2-rfc`

    Not sure if this is a feature request or a question...

    I was previously using the blake2-rfc crate and now I want to migrate to the blake2 crate. However previously I was using the Blake2b::with_key constructor (as per https://docs.rs/blake2-rfc/0.2.18/blake2_rfc/blake2b/struct.Blake2b.html#method.with_key) and I can't seem to find the proper equivalent in case of the blake2 crate.

    There seems to exist Blake2bVarCore::new_with_params (as per https://docs.rs/blake2/0.10.2/blake2/struct.Blake2bVarCore.html#method.new_with_params), however I can't seem to convert that into a Blake2bVar (which I need to get variable hash output).

    Based on the current blake2b implementation, it seems I should be able to just replace the core member of the Blake2bVar with the Blake2bVarCore instance, which indeed works if I "hack my way" by using pointers. However there is no "official" (as per the public API) way of doing this.

    A simple From implementation, or even an unsafe constructor that takes a Blake2bVarCore and yields a Blake2bVar would seem to suffice.

    opened by cipriancraciun 3
  • Refactor k12

    Refactor k12

    The k12 crate had its own keccak-p permutation implementation. With https://github.com/RustCrypto/sponges/pull/7 a generic keccak-p implementation would be available, which could be used within the k12 crate.

    Depends on

    • [ ] https://github.com/RustCrypto/sponges/pull/7
    • [ ] and a new release of the keccak crate ;)
    opened by aewag 7
Owner
Rust Crypto
Cryptographic algorithms written in pure Rust
Rust Crypto
Rust implementation of the PTHash perfect hash function for static compile-time generated hash tables

QuickPHF QuickPHF is a Rust implementation of the PTHash minimal perfect hash function algorithm. It consists of two crates: quickphf - runtime code f

Darko Trifunovski 11 Oct 20, 2023
Fastmurmur3 - Fast non-cryptographic hash, with the benchmarks to prove it.

Fastmurmur3 Murmur3 is a fast, non-cryptographic hash function. fastmurmur3 is, in my testing, the fastest implementation of Murmur3. Usage let bytes:

Kurt Wolf 13 Dec 2, 2022
Lockstitch is an incremental, stateful cryptographic primitive for symmetric-key cryptographic operations in complex protocols.

Lockstitch is an incremental, stateful cryptographic primitive for symmetric-key cryptographic operations (e.g. hashing, encryption, message authentication codes, and authenticated encryption) in complex protocols.

Coda Hale 3 Dec 27, 2022
Dexios-Core is a library used for managing cryptographic functions and headers that adhere to the Dexios format.

What is it? Dexios-Core is a library used for managing cryptographic functions and headers that adhere to the Dexios format. Security Dexios-Core uses

brxken 3 Jul 4, 2022
Expose various non-cryptographic hashing functions with Digest traits

noncrypto-digests Expose various non-cryptographic hashing functions with Digest traits. This allows users to use any hashing function with the same t

Yuri Astrakhan 3 Dec 9, 2023
A (mostly) pure-Rust implementation of various cryptographic algorithms.

Rust-Crypto A (mostly) pure-Rust implementation of various common cryptographic algorithms. Rust-Crypto seeks to create practical, auditable, pure-Rus

null 1.2k Dec 27, 2022
Pure Rust implementation of the RNCryptor cryptographic format by Rob Napier

rncryptor Rust Implementation of the RNCryptor spec This library implements the specification for the RNCryptor encrypted file format by Rob Napier. d

null 7 Jun 29, 2022
Pure-Rust traits and utilities for constant-time cryptographic implementations.

subtle Pure-Rust traits and utilities for constant-time cryptographic implementations. It consists of a Choice type, and a collection of traits using

dalek cryptography 196 Dec 13, 2022
Collection of block cipher algorithms written in pure Rust

RustCrypto: block ciphers Collection of block ciphers and block modes written in pure Rust. Warnings Currently only the aes crate provides constant-ti

Rust Crypto 506 Jan 3, 2023
Elliptic-curves - Collection of pure Rust elliptic curve implementations (e.g. P-256, P-384, secp256k1)

RustCrypto: Elliptic Curves General purpose Elliptic Curve Cryptography (ECC) support, including types and traits for representing various elliptic cu

Rust Crypto 386 Dec 27, 2022
Sodium Oxide: Fast cryptographic library for Rust (bindings to libsodium)

sodiumoxide |Crate|Documentation|Gitter| |:---:|:-----------:|:--------:|:-----:|:------:|:----:| |||| NaCl (pronounced "salt") is a new easy-to-use h

sodiumoxide 642 Dec 17, 2022
Secure storage for cryptographic secrets in Rust

secrets secrets is a library to help Rust programmers safely held cryptographic secrets in memory. It is mostly an ergonomic wrapper around the memory

Stephen Touset 165 Dec 22, 2022
A rust binding for nodejs to generate md5 hash value

Hasher A rust binding for creating node module to generate md5 hash value This project was bootstrapped by create-neon. Installing hasher Installing h

Md. Al-Amin 0 Nov 7, 2021
MD5/SHA256 HASH ATTACK IN RUST

hashraccoon Installation Install cargo curl https://sh.rustup.rs -sSf | sh Install the hashraccoon crate cargo install hashraccoon Download the rockyo

null 3 Nov 5, 2022
A Boring(SSL)-compatible API abstraction for Rust cryptographic implementations.

A Boring(SSL)-compatible API abstraction for Rust cryptographic implementations. What is Superboring? Superboring hides the complexity, diversity and

Frank Denis 7 Dec 29, 2023
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.

Themis provides strong, usable cryptography for busy people General purpose cryptographic library for storage and messaging for iOS (Swift, Obj-C), An

Cossack Labs 1.6k Dec 30, 2022
Highly modular & configurable hash & crypto library

Octavo Highly modular & configurable hash & crypto library written in pure Rust. Installation [dependencies] octavo = { git = "https://github.com/libO

Octavo Developers 139 Dec 29, 2022
Modern Cryptographic Firmware

Trussedยฎ Modern Cryptographic Firmware Status Very much WIP. Actively developed. Unstable APIs.

Trussedยฎ 300 Dec 16, 2022
The underlying cryptographic primitives for Manta Ecosystem

manta crypto The underlying cryptography that manta ecosystem relies on. It comes with the following traits: checksum: definitions for message digest.

Manta Network 10 Nov 10, 2021