Giter VIP home page Giter VIP logo

hashes's Introduction

RustCrypto: Hashes

Project Chat dependency status Apache2/MIT licensed

Collection of cryptographic hash functions written in pure Rust.

All algorithms reside in separate crates and are 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.

Algorithm Crate Crates.io Documentation MSRV Security
Ascon hash ascon‑hash crates.io Documentation MSRV 1.71 πŸ’š
BelT hash belt‑hash crates.io Documentation MSRV 1.71 πŸ’š
BLAKE2 blake2 crates.io Documentation MSRV 1.71 πŸ’š
FSB fsb crates.io Documentation MSRV 1.71 πŸ’š
GOST R 34.11-94 gost94 crates.io Documentation MSRV 1.71 πŸ’›
GrΓΈstl (Groestl) groestl crates.io Documentation MSRV 1.71 πŸ’š
JH jh crates.io Documentation MSRV 1.71 πŸ’š
KangarooTwelve k12 crates.io Documentation MSRV 1.71 πŸ’š
MD2 md2 crates.io Documentation MSRV 1.71 πŸ’”
MD4 md4 crates.io Documentation MSRV 1.71 πŸ’”
MD5 md5 ❗ crates.io Documentation MSRV 1.72 πŸ’”
RIPEMD ripemd crates.io Documentation MSRV 1.71 πŸ’š
SHA-1 sha1 crates.io Documentation MSRV 1.72 πŸ’”
SHA-1 Checked sha1-checked crates.io Documentation MSRV 1.72 πŸ’›
SHA-2 sha2 crates.io Documentation MSRV 1.72 πŸ’š
SHA-3 (Keccak) sha3 crates.io Documentation MSRV 1.71 πŸ’š
SHABAL shabal crates.io Documentation MSRV 1.71 πŸ’š
Skein skein crates.io Documentation MSRV 1.71 πŸ’š
SM3 (OSCCA GM/T 0004-2012) sm3 crates.io Documentation MSRV 1.71 πŸ’š
Streebog (GOST R 34.11-2012) streebog crates.io Documentation MSRV 1.71 πŸ’›
Tiger tiger crates.io Documentation MSRV 1.74 πŸ’š
Whirlpool whirlpool crates.io Documentation MSRV 1.71 πŸ’š

NOTE: the blake3 crate implements the digest traits used by the rest of the hashes in this repository, but is maintained by the BLAKE3 team.

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.

Crate Names

Whenever possible crates are published under the same name as the crate folder. Owners of md5 declined to participate in this project. This crate does not implement the digest traits, so it is not interoperable with the RustCrypto ecosystem. This is why we publish our MD5 implementation as md-5 and mark it with the ❗ mark. Note that the library itself is named as md5, i.e. inside use statements you should use md5, not md_5.

The SHA-1 implementation was previously published as sha-1, but migrated to sha1 since v0.10.0. sha-1 will continue to receive v0.10.x patch updates, but will be deprecated after sha1 v0.11 release.

Minimum Supported Rust Version (MSRV) Policy

MSRV bumps are considered breaking changes and will be performed only with minor version bump.

Examples

Let us demonstrate how to use crates in this repository using SHA-2 as an example.

First add sha2 crate to your Cargo.toml:

[dependencies]
sha2 = "0.10"

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

[dependencies]
sha2 = { version = "0.10", default-features = false }

sha2 and the other hash implementation crates re-export the digest crate and the Digest trait for convenience, so you don't have to include it in your Cargo.toml it as an explicit dependency.

Now you can write the following code:

use sha2::{Sha256, Digest};

let mut hasher = Sha256::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!("Binary hash: {:?}", hash);

In this example hash has type GenericArray<u8, U32>, which is a generic alternative to [u8; 32] defined in the generic-array crate. If you need to serialize hash value into string, you can use crates like base16ct and base64ct:

use base64ct::{Base64, Encoding};

let base64_hash = Base64::encode_string(&hash);
println!("Base64-encoded hash: {}", base64_hash);

let hex_hash = base16ct::lower::encode_string(&hash);
println!("Hex-encoded hash: {}", hex_hash);

Instead of calling update, you also can use a chained approach:

use sha2::{Sha256, Digest};

let hash = Sha256::new()
    .chain_update(b"Hello world!")
    .chain_update("String data")
    .finalize();

If a complete message is available, then you can use the convenience Digest::digest method:

use sha2::{Sha256, Digest};

let hash = Sha256::digest(b"my message");

Hashing Readable Objects

If you want to hash data from a type which implements the Read trait, you can rely on implementation of the Write trait (requires enabled-by-default std feature):

use sha2::{Sha256, Digest};
use std::{fs, io};

let mut file = fs::File::open(&path)?;
let mut hasher = Sha256::new();
let n = io::copy(&mut file, &mut hasher)?;
let hash = hasher.finalize();

Hash-based Message Authentication Code (HMAC)

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

Generic Code

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

use sha2::{Sha256, Sha512, Digest};

// 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; 32];
hash_password::<Sha256>("my_password", "abcd", &mut buf1);

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

If you want to use hash functions with trait objects, you can use the DynDigest trait:

use digest::DynDigest;

// Dynamic hash function
fn use_hasher(hasher: &mut dyn DynDigest, data: &[u8]) -> Box<[u8]> {
    hasher.update(data);
    hasher.finalize_reset()
}

// You can use something like this when parsing user input, CLI arguments, etc.
// DynDigest needs to be boxed here, since function return should be sized.
fn select_hasher(s: &str) -> Box<dyn DynDigest> {
    match s {
        "md5" => Box::new(md5::Md5::default()),
        "sha1" => Box::new(sha1::Sha1::default()),
        "sha224" => Box::new(sha2::Sha224::default()),
        "sha256" => Box::new(sha2::Sha256::default()),
        "sha384" => Box::new(sha2::Sha384::default()),
        "sha512" => Box::new(sha2::Sha512::default()),
        _ => unimplemented!("unsupported digest: {}", s),
    }
}

let mut hasher1 = select_hasher("md5");
let mut hasher2 = select_hasher("sha512");

// the `&mut *hasher` is to DerefMut the value out of the Box
// this is equivalent to `DerefMut::deref_mut(&mut hasher)`

// can be reused due to `finalize_reset()`
let hash1_1 = use_hasher(&mut *hasher1, b"foo");
let hash1_2 = use_hasher(&mut *hasher1, b"bar");
let hash2_1 = use_hasher(&mut *hasher2, b"foo");

License

All crates in this repository are 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.

hashes's People

Contributors

aewag avatar causingbrick avatar centril avatar dconnolly avatar dependabot[bot] avatar dignifiedquire avatar dotdash avatar felipeamp avatar gavadinov avatar gtank avatar heiher avatar iquerejeta avatar ivashchenkoserhii avatar jvdsn avatar linkmauve avatar lumag avatar makavity avatar mrnossiom avatar myers avatar newpavlov avatar robjtede avatar rodoufu avatar rsaarelm avatar rukai avatar sebastinas avatar sourcefrog avatar str4d avatar striezel avatar tarcieri avatar vorot93 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hashes's Issues

Sha2 became slower

Hi,

I use sha256 in vagga a lot. And I just noticed that current implementation of sha256 is much slower (2x-3x) than old sha2 = 0.1.2.

I do not post benchmarks here because I can't find repository for old code. Do you have a link?

Is there any chance to fix it?

Traits for digests of particular output length

Currently the Digest trait allows writing code that's generic with respect to the choice of hash function. But for an application that requires a certain output size, there's no way to encode that requirement into the type system (e.g., "This function requires a hash function with 512 bits of output").

Perhaps one way to solve this would be to introduce empty Digest256, Digest512, etc traits, which all inherit the Digest trait. Implementing, say, Digest512 is then a declaration that that hash function has 512 bits of output, so that users can write functions which are generic over hash functions with a fixed output size.

Is this a good idea, or there a better way to do this?

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!

Groestl perfomance

Current implementation of Groestl is quite slow (<1 MB/s) and can be significantly improved.

Various performance improvement techniques can be found in the "GrΓΈstl Implementation Guide". List of the fastest implementations can be found here.

MD5 performance optimization

In line 53 in lib.rs, the function hash() initialized the output array as [0; 16].

I believe this can be optimized to unsafe { ::std::mem::uninitialized() }, as all the bytes in the output array are overwritten.

When computing many hashes per second in an environment where hash result matters (eg authenticating TCP segments with the MD5 signature option), this is just another little win.

What's the best `Digest` trait?

Both the rust-crypto and digest crates have a Digest trait. They're both listed as being authored by "The Rust-Crypto Project Developers".

If I'm defining a new hash algorithm, which trait should I implement?

Compilation error when used as a dependency

When trying to install tectonic which depends on this:

error: `Self` and associated types in struct expressions and patterns are unstable (see issue #37544)
  --> ~/.cargo/registry/src/github.com-1ecc6299db9ec823/md-5-0.4.3/src/lib.rs:40:9
   |
40 |         Self {
   |         ^^^^

Though, strangely, the Travis CI build is passing.

Extend `Digest` trait to support inputting data from a `Read`-able object

The current Digest trait looks like this:

pub trait Digest: Input + FixedOutput {
    type OutputSize: ArrayLength<u8>;
    type BlockSize: ArrayLength<u8>;
    fn input(&mut self, input: &[u8]);
    fn result(self) -> GenericArray<u8, Self::OutputSize>;
}

A common pattern, at least for me, is to take a hash for an entire file. This can be done something like:

let file = File::open(...).unwrap();
let mut hasher = Sha256::default();

// Read blocks of the file into memory and pass them into the hasher.
let mut buffer: [u8; 512] = Default::default();
loop {
    let bytes_read = file.read(&mut buffer)?;
    hasher.input(&buffer[..bytes_read]);
    if bytes_read != buffer.len() {
        break;
    }
}

let hash = hasher.result();

I think this pattern may be common enough to justify extending the Digest trait with a read_from method, and providing a default implementation that is used across all implementors:

pub trait Digest: Input + FixedOutput {
    fn read_from(&mut self, from: &mut std::io::Read) -> Result<(), std::io::Error> {
        // Read blocks into memory until EOF (or io error), and pass into the `input` function.
    }
}

This would replace the middle 8 lines I wrote in the above example with what in my opinion is a more ergonomic function call, and it generalizes to any type that implements std::io::Read (e.g. sockets or Tcp streams).

Does this seem like a good idea? I'd be happy to implement it if those more invested in RustCrypto than myself approve.

Proposal: Add a DigestBuilder

Instead of this:

let foo = {
    let mut sh = Sha1::default();
    sh.input(&bar);
    sh.input(&baz);
    sh.input(&buz);
    sh.result()
};

It would allow for this:

let foo = Sha1::builder()
    .input(&bar)
    .input(&baz)
    .input(&buz)
    .result()

This could be added entirely in the digest crate.

Use big endian for streebog and gost94

GOSTs are specified in terms of N-bit integers and do not define byte order which should be used. Initially I've chose to use little endian order, but probably big endian would have been a better choice. This will allow to simplify code a bit, and will probably be more compatible with other implementations.

TODO: Look into other implementations.

0.6.1 release breaks code depending on 0.6.0

This is a violation of semver, the error being:

error[E0599]: no method named `variable_result` found for type `blake2::Blake2b` in the current scope                  
   --> src/caps.rs:180:35                                  
    |                                                                                                                  
180 |                 let hash = hasher.variable_result(&mut buf).unwrap();                                            
    |                                   ^^^^^^^^^^^^^^^    
    |                                                                                                                  
    = note: the method `variable_result` exists but the following trait bounds were not satisfied:                     
            `blake2::Blake2b : digest::ExtendableOutput`   
            `&blake2::Blake2b : digest::ExtendableOutput`                                                              
            `&mut blake2::Blake2b : digest::ExtendableOutput`

Add Grostl

Claimed by @gsgsingh93

Moved from #1:

I'm having some trouble with the types for Grostl. The issue is that the BlockSize depends on the OutputSize, and so I can't figure out to define the impl for Digest. If the Output size is 256 bits or less, then 512 is used as the block size. If the output size is greater than 256 bytes, then 1024 is used as the block size. Here's what I have right now, with the incorrectly hardcoded BlockSize as U512

extern crate digest;
extern crate generic_array;

use std::marker::PhantomData;

use digest::Digest;
use generic_array::{ArrayLength, GenericArray};
use generic_array::typenum::U512;

// TODO: This could also be U1024
type BlockSize = U512;

pub struct Grostl<OutputSize: ArrayLength<u8>> {
    phantom: PhantomData<OutputSize>,
}

impl<OutputSize: ArrayLength<u8>> Grostl<OutputSize> {
    fn new() -> Grostl<OutputSize> {
        Grostl { phantom: PhantomData }
    }
}

impl<OutputSize: ArrayLength<u8>> Default for Grostl<OutputSize> {
    fn default() -> Self { Self::new() }
}

impl<OutputSize: ArrayLength<u8>> Digest for Grostl<OutputSize> {
    type OutputSize = OutputSize;
    type BlockSize = BlockSize;

    fn input(&mut self, input: &[u8]) {
    }

    fn result(mut self) -> GenericArray<u8, Self::OutputSize> {
        GenericArray::default()
    }
}

Note that OutputSize is parameterized here because Grostl can output hashes between 1 and 64 bytes.

EDIT: I guess if there's no fancy solution with the generics that could get this to work, I could always just override block_bytes and block_bits in the trait, and just set a dummy BlockSize and not use it.

Hasher trait not implemented for digests

The std::hash::Hasher trait is not implemented for these digests. The trait is identical to the digest::Input and digest::FixedOutput traits. Implementing it would be useful for me, because I'd like to have my std::hash::Hash implementation be usable with a digest::Digest.

GOST94 optimization

It's possible to significantly improve performance of GOST94 with a relatively little work.

perf report results:

--98.25%-- gost94::gost94::Gost94State::f::h77646fa46d6b3d1b
     |
     |--45.54%-- gost94::gost94::Gost94State::shuffle::hdd9f6ead0dcb2230
     |     |
     |     |--42.68%-- gost94::gost94::psi::h3fd72e14f2fd3fca
     |
     |--35.82%-- gost94::gost94::encrypt::h32d61af8e91b44b7
     |     |
     |     |--29.97%-- gost94::gost94::g::ha2fe1802e6e6b67f
     |          |
     |          |--26.89%-- gost94::gost94::sbox::hd99689d5581a89bb
     |
     |--8.02%-- gost94::gost94::a::h8a2cac7c5b28e727
     |
     |--3.59%-- gost94::gost94::p::h158268fffc4616a5
     |
     |--1.97%-- gost94::gost94::g::ha2fe1802e6e6b67f

sbox can be optimized using 8-bit S-boxes instead of 4-bit ones. Additionally you can read this paper (Russian) about possible optimizations of block cipher used in GOST94.

psi could be optimized by replacing unnecessary copy operations with cursor based approach.

Link error in SHA2 with asm on macOS

When I compile sha2 version 0.7.1 with the asm feature enabled, I get the following link error:

  = note: Undefined symbols for architecture x86_64:
            "_sha512_compress", referenced from:
                sha2_asm::compress512::h2714fa0e6f190002 in libsha2-128ed50e2e0d1cae.rlib(sha2-128ed50e2e0d1cae.sha214.rcgu.o)
          ld: symbol(s) not found for architecture x86_64
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

This is on macOS 10.13.4 with Rust 1.26.

To reproduce, run cargo new --bin test_sha2 and then edit the following files:

Cargo.toml:

[package]
name = "test_sha2"
version = "0.1.0"

[dependencies]
sha2 = { version = "0.7", features = ["asm"] }

src/main.rs:

extern crate sha2;

use sha2::{Sha512Trunc256, Digest};

fn main() {
    let mut hasher = Sha512Trunc256::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);
}

Sha-1 asm feature is broken

Compiling sha-1 with asm feature enabled results in

error[E0308]: mismatched types
  --> /Users/dignifiedquire/.cargo/registry/src/github.com-1ecc6299db9ec823/sha-1-0.8.0/src/lib.rs:80:54
   |
80 |         self.buffer.input(input, |d| compress(state, d));
   |                                                      ^ expected array of 64 elements, found struct `block_buffer::generic_array::GenericArray`
   |
   = note: expected type `&[u8; 64]`
              found type `&block_buffer::generic_array::GenericArray<u8, block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UTerm, block_buffer::generic_array::typenum::B1>, block_buffer::generic_array::typenum::B0>, block_buffer::generic_array::typenum::B0>, block_buffer::generic_array::typenum::B0>, block_buffer::generic_array::typenum::B0>, block_buffer::generic_array::typenum::B0>, block_buffer::generic_array::typenum::B0>>`

error[E0308]: mismatched types
  --> /Users/dignifiedquire/.cargo/registry/src/github.com-1ecc6299db9ec823/sha-1-0.8.0/src/lib.rs:91:71
   |
91 |             self.buffer.len64_padding::<BE, _>(l, |d| compress(state, d));
   |                                                                       ^ expected array of 64 elements, found struct `block_buffer::generic_array::GenericArray`
   |
   = note: expected type `&[u8; 64]`
              found type `&block_buffer::generic_array::GenericArray<u8, block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UInt<block_buffer::generic_array::typenum::UTerm, block_buffer::generic_array::typenum::B1>, block_buffer::generic_array::typenum::B0>, block_buffer::generic_array::typenum::B0>, block_buffer::generic_array::typenum::B0>, block_buffer::generic_array::typenum::B0>, block_buffer::generic_array::typenum::B0>, block_buffer::generic_array::typenum::B0>>`

error: aborting due to 2 previous errors

It works fine without it.

Key stretching to 64B.

Hi,

I need to use blake2 for key stretching to a 64B value. Is VariableOutput the way to go or am I misunderstanding its purpose? Is effectively making me use BLAKE-512?

Thank you for your help!

Package for sha2 contains binary tests

Tested with 0.7.1 (I cannot test with 0.8.0 atm).

  • sha2/tests/data/sha224/test1.output.bin
  • sha2/tests/data/sha224/test2.output.bin
  • sha2/tests/data/sha224/test3.output.bin
  • sha2/tests/data/sha256/one_million_a.output.bin
  • sha2/tests/data/sha256/test1.output.bin
  • sha2/tests/data/sha256/test2.output.bin
  • sha2/tests/data/sha256/test3.output.bin
  • sha2/tests/data/sha384/test1.output.bin
  • sha2/tests/data/sha384/test2.output.bin
  • sha2/tests/data/sha384/test3.output.bin
  • sha2/tests/data/sha512/test1.output.bin
  • sha2/tests/data/sha512/test2.output.bin
  • sha2/tests/data/sha512/test3.output.bin
  • sha2/tests/data/sha512_224/test1.output.bin
  • sha2/tests/data/sha512_224/test3.output.bin
  • sha2/tests/data/sha512_256/test1.output.bin

I assume that this is an error. At least, it gets flagged as "odd" by the Firefox submission mechanism.

Technically Keccak β‰  SHA-3

SHA-3 is just based on Keccak because it uses a slightly different padding function.

Maybe this should be corrected in the README but of course it's entirely your decision because the difference isn't that big.

why do the hashes derive copy

So this is something I'm hoping can be documented somewhere. I'm curious why the hashes derive copy because it seems like not the behavior you'd want. If you accidentally forget to pass your data by reference you will get an automatic copy which is not something you'd likely want in this case. Typically I've found if the impl has mut on self then you don't want copy.

e.g.

enum Foo {
   Sha(sha2::Sha256),
   Md5(md5::Md5),
}

struct Bar {
  hash: Foo,
}

impl Bar { 
  fn some_data(&mut self, data: &[u8]) {
    match self.hash {
      Foo::Sha(mut hash) => hash.input(data),
      Foo::Md5(mut hash) => hash.input(data),
   }
  }
}

What's the expected behavior here?

Please add more inline examples in the documentation.

I'm trying to figure out how to get a digest of a given size, and there is so many abstraction and crates involved, and the source is based on macros, obfuscating what is going on, that it's beyond me at this late hour.

I realize it's a lot of work, and don't want to just complain. I'm just trying to point out the issue. All these efforts are greatly appreciated!

Port blake2 on coresimd

With stabilization of SIMD intrinsics in Rust 1.27 we can remove simd feature from the blake2 crate.

CI improvements

  • Add crate specific feature tests (including asm)
  • Add big-endian tests (using either qemu or https://github.com/japaric/trust.) [#40]
  • Test minimal Rust versions for crates (currently all crates support 1.13 or higher)
  • Add tests to check if crates are truly no_std (see #36)

Add asm feature tests to CI

asm feature was added to md5, sha1, sha2 and whirlpool crates, but current CI configuration does not test it.

Performance of blake2

Hi,

It looks like performance of blake2 compared to sha512 is very similar (while still faster):

     Running target/release/deps/blake2b-2fc6bb02e2d63899

running 6 tests
test bench_16  ... bench:          45 ns/iter (+/- 6) = 355 MB/s
test bench_1k  ... bench:       2,636 ns/iter (+/- 3) = 388 MB/s
test bench_256 ... bench:         685 ns/iter (+/- 31) = 373 MB/s
test bench_64  ... bench:         170 ns/iter (+/- 9) = 376 MB/s
test bench_64k ... bench:     174,027 ns/iter (+/- 3,512) = 376 MB/s
test bench_8k  ... bench:      21,669 ns/iter (+/- 951) = 378 MB/s

running 6 tests
test bench_16  ... bench:          60 ns/iter (+/- 1) = 266 MB/s
test bench_1k  ... bench:       3,092 ns/iter (+/- 101) = 331 MB/s
test bench_256 ... bench:         779 ns/iter (+/- 15) = 328 MB/s
test bench_64  ... bench:         204 ns/iter (+/- 9) = 313 MB/s
test bench_64k ... bench:     197,618 ns/iter (+/- 8,180) = 331 MB/s
test bench_8k  ... bench:      24,689 ns/iter (+/- 896) = 331 MB/s

But https://blake2.net/ shows that performance should be about 3x faster.

Any ideas? It looks like blake2 does not use SIMD? Is it not needed? Is there a chance that blake2 crate here will be optimized better in future? Or it's just because recent processors already execute sha512 much faster?

Add security summaries

It would be nice to have a short security summary in each crate documentation which would include known insecurities, applicability, etc.

Determine minimal Rust version requirements for crates

Currently most of the crates require 1.16 due to the use of Self in structs, with small changes they can be made compatible with at least 1.13. It would be good to explicitly show those requirements in the algorithms table.

Either way it's worth to add relevant tests to Travis CI, so this table would stay updated.

Sha256 (and seemingly most others) do not implement Debug

This makes it really painful to include one of these types into my own struct as now I have to implement Debug by hand. If the internals are being hidden for some reason, could the library provide an implementation that prints something like Sha256 { ... }?

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.

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?

Using XofReader

Hi,
Am I using the XofReader (Sha3XofReader) incorrectly? I was assuming that each call to XofReader::read(...) would extend the previous values.

For example, the following:

extern crate digest;
extern crate sha3;

use digest::{Input, ExtendableOutput ,XofReader};
use sha3::Shake256;

fn main() {
    let mut hasher = Shake256::default();
    hasher.process(b"some nice randomness here");
    let mut xof = hasher.xof_result();

    let mut buf = [0; 4];

    for _ in 0..5 {
        xof.read(&mut buf);
        println!("{:?}", buf);
    }
}

Repeatedly returns the same values.

[27, 145, 10, 182]
[27, 145, 10, 182]
[27, 145, 10, 182]
[27, 145, 10, 182]
[27, 145, 10, 182]

(Sorry if this is better placed in https://github.com/RustCrypto/traits, I figured it's probably an implementation bug, unless I've done something stupid.)

Continuing a hashing computation on another machine

Thanks for the fantastic library! It's allowing me to give Rust a try for a small project.

I'm very new to Rust, so this may be a usage question rather than a feature request: I'm trying to start calculating a hash on one machine, and then continue the calculation on another. (Imagine the machines each have private input that must be added to the hash, for example.)

What's the best way to "serialize" and "deserialize" a Sha256? Does this library offer a safe way, or can anyone recommend an unsafe one?

(My compile target is guaranteed to be the same for all machines: wasm32-unknown-unknown. I'm trying to use wasm-bindgen to provide functionality from this library to some JavaScript.)

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.