RustCrypto hashes
Collection of cryptographic hash functions written in pure Rust.
All algorithms split into 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 programming.
Supported algorithms
Note: For new applications, or where compatibility with other existing standards is not a primary concern, we strongly recommend either BLAKE2, SHA-2 or SHA-3.
Name | Alt name | Crates.io | Documentation | Security Level |
---|---|---|---|---|
BLAKE2 | π | |||
GOST94 | GOST R 34.11-94 | π | ||
GrΓΈstl | Groestl | π | ||
MD2 | π | |||
MD4 | π | |||
MD5 β | π | |||
RIPEMD-160 | π | |||
SHA-1 β | π | |||
SHA-2 | π | |||
SHA-3 | Keccak | π | ||
Streebog | GOST R 34.11-2012 | π | ||
Whirlpool | π |
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 |
Minimum Rust version
All crates in this repository support Rust 1.13 or higher. Although to simplify CI configuration the oldest continuously tested version is 1.18. In future minimally supported version of Rust can be changed, but it will be done with the minor version bump.
Crate names
Whenever possible crates are published under the the same name as the crate
folder. Owners of md5
and sha1
crates refused
(1,
2) to participate in this
project. This is why crates marked by β are published under
md-5
and sha-1
names respectively.
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.6"
blake2
and other crates re-export
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.input(data);
// `input` can be called repeatedly
hasher.input("String data".as_bytes());
// Note that calling `result()` consumes hasher
let hash = hasher.result();
println!("Result: {:x}", hash);
hash
has type GenericArray<u8, U64>
, which is a generic alternative to [u8; 64]
.
Also you can use the following approach if the whole message is available:
let hash = Blake2b::digest(b"my message");
println!("Result: {:x}", hash);
Read
able objects
Hashing If you want to hash data from Read
trait (e.g. from file) you can enable std
feature in digest crate:
[dependencies]
blake2 = "0.6"
digest = { version = "0.6", features = ["std"]}
And use digest_reader
method which will compute hash by reading data using
1 KB blocks:
use blake2::{Blake2b, Digest};
use std::fs;
let mut file = fs::File::open(&path)?;
let hash = Blake2b::digest_reader(&mut file)?;
println!("{:x}\t{}", hash, path);
Hash-based Message Authentication Code (HMAC)
One of the common tasks for cryptographic hash functions is generation of
Message Authentication Codes
(MAC). In RustCrypto all MAC functions represented using Mac
trait from
crypto-mac
crate. Some hash functions
provide Mac
implementations (e.g. BLAKE2), but for others you can use generically
implemented HMAC
from hmac
crate.
To demonstrate how to use HMAC, lets use SHA256 as an example. First add the following dependencies to your crate:
[dependencies]
hmac = "0.3"
sha2 = "0.6"
To get the authentication code:
extern crate sha2;
extern crate hmac;
use hmac::{Hmac, Mac};
use sha2::Sha256;
// Create `Mac` trait implementation, in this case HMAC-SHA256
let mac = Hmac::<Sha256>::new(b"my secret and secure key");
mac.input(b"input message");
// `result` has type `MacResult` which is a thin wrapper around array of
// bytes for providing constant time equality check
let result = mac.result();
// To get &[u8] use `code` method, but be carefull, since incorrect use
// of the code value may permit timing attacks which defeat the security
// provided by the `MacResult`.
let code_bytes = result.code();
To verify the message:
let mac = Hmac::<Sha256>::new(b"my secret and secure key");
mac.input(b"input message");
let is_code_correct = mac.verify(code_bytes);
Generic code
You can write generic code over Digest
trait which will work over different
hash functions:
use digest::Digest;
// Toy example, do not use it in practice!
fn hash_password<D: Digest + Default>(password: &str, salt: &str, output: &mut [u8]) {
let mut hasher = D::default();
hasher.input(password.as_bytes());
hasher.input(b"$");
hasher.input(salt.as_bytes());
output.copy_from_slice(hasher.result().as_slice())
}
use blake2::Blake2b;
use sha2::Sha256;
hash_password::<Blake2b>("my_password", "abcd", &mut buf);
hash_password::<Sha256>("my_password", "abcd", &mut buf);
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.