All Projects → nickbabcock → highway-rs

nickbabcock / highway-rs

Licence: MIT License
Native Rust port of Google's HighwayHash, which makes use of SIMD instructions for a fast and strong hash function

Programming Languages

rust
11053 projects
r
7636 projects

Projects that are alternatives of or similar to highway-rs

John
John the Ripper jumbo - advanced offline password cracker, which supports hundreds of hash and cipher types, and runs on many operating systems, CPUs, GPUs, and even some FPGAs
Stars: ✭ 5,656 (+9822.81%)
Mutual labels:  hash, simd
CudaSHA256
Simple tool to calculate sha256 on GPU using Cuda
Stars: ✭ 38 (-33.33%)
Mutual labels:  hash
fast-base64
Fastest base64 on the web, with Wasm + SIMD
Stars: ✭ 23 (-59.65%)
Mutual labels:  simd
xxhash-rust
Rust implementation of xxhash
Stars: ✭ 56 (-1.75%)
Mutual labels:  hash
block-aligner
SIMD-accelerated library for computing global and X-drop affine gap penalty sequence-to-sequence or sequence-to-profile alignments using an adaptive block-based algorithm.
Stars: ✭ 58 (+1.75%)
Mutual labels:  simd
varint-simd
Decoding and encoding gigabytes of LEB128 variable-length integers per second in Rust with SIMD
Stars: ✭ 31 (-45.61%)
Mutual labels:  simd
ADbHash
Really fast C++ hash table
Stars: ✭ 12 (-78.95%)
Mutual labels:  simd
invokable
Objects are functions! Treat any Object or Class as a Proc (like Enumerable but for Procs).
Stars: ✭ 40 (-29.82%)
Mutual labels:  hash
signet
Easily compare SHA/BLAKE2 sums.
Stars: ✭ 13 (-77.19%)
Mutual labels:  hash
xxhash
A super-fast hash algorithm in a single C++ header
Stars: ✭ 48 (-15.79%)
Mutual labels:  hash
server
Hashtopolis - A Hashcat wrapper for distributed hashcracking
Stars: ✭ 954 (+1573.68%)
Mutual labels:  hash
agent-python
Official python agent for using the distributed hashcracker Hashtopolis
Stars: ✭ 39 (-31.58%)
Mutual labels:  hash
EncrypC
🔑 File Encryption Application using Python.
Stars: ✭ 14 (-75.44%)
Mutual labels:  hash
positional-popcount
Fast C functions for the computing the positional popcount (pospopcnt).
Stars: ✭ 47 (-17.54%)
Mutual labels:  simd
sha-2
SHA-2 algorithm implementations
Stars: ✭ 122 (+114.04%)
Mutual labels:  hash
merkle
Golang Merkle Tree Implementation. With hash.Hash interface for streaming support
Stars: ✭ 50 (-12.28%)
Mutual labels:  hash
fastbloom
A simple but fast bloomfilter written in Python
Stars: ✭ 21 (-63.16%)
Mutual labels:  hash
shortcut-comparison
Performance comparison of parallel Rust and C++
Stars: ✭ 74 (+29.82%)
Mutual labels:  simd
awesome-simd
A curated list of awesome SIMD frameworks, libraries and software
Stars: ✭ 39 (-31.58%)
Mutual labels:  simd
MalwareHashDB
Malware hashes for open source projects.
Stars: ✭ 31 (-45.61%)
Mutual labels:  hash

ci Rust Version

Highway-rs

This crate is a native Rust port of Google's HighwayHash, which is a fast, keyed, portable (output is hardware independent) and strong hash function.

Features

  • pure / stable rust
  • zero dependencies
  • generate 64, 128, and 256bit hashes
  • > 10 GB/s with SIMD (SSE 4.1 & AVX 2) aware instructions on x86 architectures
  • > 3 GB/s on Wasm with the Wasm SIMD extension
  • > 1 GB/s portable implementation with zero unsafe code
  • incremental / streaming hashes
  • zero heap allocations
  • no_std compatible
  • fuzzed against reference implementation to ensure stability and compatibility

Caution

HighwayHash (the algorithm) has not undergone extensive cryptanalysis like SipHash (the default hashing algorithm in Rust), but according to the authors, HighwayHash output bits are uniformly distributed and should withstand differential and rotational attacks. Hence HighwayHash is referred to as a strong hash function, not a cryptographic hash function. I encourage anyone interested to peruse the paper to understand the risks.

Examples

The quickest way to get started:

use highway::{HighwayHasher, HighwayHash};
let res: u64 = HighwayHasher::default().hash64(&[]);
let res2: [u64; 2] = HighwayHasher::default().hash128(&[]);
let res3: [u64; 4] = HighwayHasher::default().hash256(&[]);

A more complete tour of the API follows:

use highway::{HighwayHasher, HighwayHash, Key};

// HighwayHash requires a key that should be hidden from attackers
// to ensure outputs are unpredictable, so attackers can't mount
// DoS attacks.
let key = Key([1, 2, 3, 4]);

// A HighwayHasher is the recommended approach to hashing,
// as it will select the fastest algorithm available
let mut hasher = HighwayHasher::new(key);

// Append some data
hasher.append(&[255]);

// After all data has been appended, you ask for
// 64, 128, or 256bit output. The hasher is consumed
// after finalization.
let res: u64 = hasher.finalize64();

assert_eq!(0x07858f24d_2d79b2b2, res);

Creating a 128bit and 256bit hash is just as simple.

use highway::{HighwayHasher, HighwayHash, Key};

// Generate 128bit hash
let key = Key([1, 2, 3, 4]);
let mut hasher128 = HighwayHasher::new(key);
hasher128.append(&[255]);
let res128: [u64; 2] = hasher128.finalize128();
assert_eq!([0xbb007d2462e77f3c, 0x224508f916b3991f], res128);

// Generate 256bit hash
let key = Key([1, 2, 3, 4]);
let mut hasher256 = HighwayHasher::new(key);
hasher256.append(&[255]);
let res256: [u64; 4] = hasher256.finalize256();
let expected: [u64; 4] = [
    0x7161cadbf7cd70e1,
    0xaac4905de62b2f5e,
    0x7b02b936933faa7,
    0xc8efcfc45b239f8d,
];
assert_eq!(expected, res256);

Use highway hash in standard rust collections

use std::collections::HashMap;
use highway::{HighwayBuildHasher, Key};
let mut map =
  HashMap::with_hasher(HighwayBuildHasher::new(Key([
    0xcbf29ce484222325,
    0xc3a5c85c97cb3127,
    0xb492b66fbe98f273,
    0x9ae16a3b2f90404f,
  ])));

map.insert(1, 2);
assert_eq!(map.get(&1), Some(&2));

Or if utilizing a key is not important, one can use the default

use std::collections::HashMap;
use std::hash::BuildHasherDefault;
use highway::HighwayHasher;
let mut map =
  HashMap::with_hasher(BuildHasherDefault::<HighwayHasher>::default());

map.insert(1, 2);
assert_eq!(map.get(&1), Some(&2));

Hashing a file, or anything implementing Read

use std::fs::File;
use std::hash::Hasher;
use highway::{PortableHash, HighwayHash};

let mut file = File::open("./README.md").unwrap();
let mut hasher = PortableHash::default();
std::io::copy(&mut file, &mut hasher).unwrap();
let hash64 = hasher.finish(); // core Hasher API
let hash256 = hasher.finalize256(); // HighwayHash API

Wasm SIMD

When deploying HighwayHash to a Wasm environment, one can opt into using the Wasm SIMD instructions by adding a Rust flag:

RUSTFLAGS="-C target-feature=+simd128" wasm-pack build

Then HighwayHasher will automatically defer to the Wasm SIMD implementation via WasmHash.

Once opted in, the execution environment must support Wasm SIMD instructions, which Chrome, Firefox, and Node LTS have stabilized since mid-2021. The opt in is required as there is not a way for Wasm to detect SIMD capabilities at runtime. The mere presence of Wasm SIMD instructions will cause incompatible environments to fail to compile, so it is recommended to provide two Wasm payloads to downstream users: one with SIMD enabled and one without.

Use Cases

HighwayHash can be used against untrusted user input where weak hashes can't be used due to exploitation, verified cryptographic hashes are too slow, and a strong hash function meets requirements. Some specific scenarios given by the authors of HighwayHash:

  • Use 64bit hashes to for authenticating short lived messages
  • Use 256bit hashes for checksums. Think file storage (S3) or any longer lived data where there is a need for strong guarantees against collisions.

HighwayHash may not be a good fit if the payloads trend small (< 100 bytes) and speed is up of the utmost importance, as HighwayHash hits its stride at larger payloads.

no_std crates

This crate has a feature, std, that is enabled by default. To use this crate in a no_std context, add the following to your Cargo.toml:

[dependencies]
highway = { version = "x", default-features = false }

Be aware that the no_std version is unable to detect CPU features and so will always default to the portable implementation. If building for a known SSE 4.1 or AVX 2 machine (and the majority of machines in the last decade will support SSE 4.1), then explicitly enable the target feature:

RUSTFLAGS="-C target-feature=+sse4.1" cargo test
RUSTFLAGS="-C target-feature=+avx2" cargo test

Benchmarks

Benchmarks are ran with the following command:

(cd compare && cargo clean && RUSTFLAGS="-C target-cpu=native" cargo bench)
find ./compare/target -wholename "*/new/raw.csv" -print0 | xargs -0 xsv cat rows > assets/highway.csv

And can be analyzed with the R script found in the assets directory

Keep in mind, benchmarks will vary by machine. Newer machines typically handle AVX payloads better than older.

We'll first take a look at the throughput when calculating the 64bit hash of a varying payload with various implementations

64bit-highwayhash.png

Takeaways:

  • The lower left corner of the graph illustrates HighwayHash's weakness: small payloads, as with a bit of squinting, one can see that HighwayHash ranks amongst the bottom.
  • At larger payloads, HighwayHash can be competitive in performance as the CPU has room to stretch its proverbial SIMD legs on the input.
  • AHash and t1ha perform fantastically and should be in one's toolkit for in memory data structures.

Now taking a look at calculating a 256bit hash value, we see a similar story.

256bit-highwayhash.png

Takeaways:

  • HighwayHash is by far the fastest compared to the other functions, but if one needs a cryptographic hash, then BLAKE3 should be chosen

Even with the best eyesight, the differences are indistinguishable at smaller payloads, so let's look at the hash rate:

256bit-highwayhash-rate.png

Takeaways:

  • At smaller payloads HighwayHash maintains its performance lead

HighwayHash uses more rounds of permutation when finalizing the 256bit output compared to the 64bit and this is reflected in the following graphic:

64bit-vs-256bit-highwayhash.png

Takeaways:

  • At max, the 64bit hash can be computed 33% faster than the 256bit output
  • After 64KiB there is no performance difference between 64bit and 256bit outputs

For those more into numbers and are curious about specifics or want more details about the hash functions at small payloads size, here is a table that breaks down throughput (in GB/s) at all payload sizes

highwayhash-table.png

Builder Benchmarks

Have fun running the builder benchmarks to see how performance differs with flags:

Default compilation

cargo bench -- highway-builder

Explicitly disable avx2

RUSTFLAGS="-C target-feature=-avx2" cargo bench -- highway-builder

Explicitly disable avx2 when targeting native cpu

RUSTFLAGS="-C target-cpu=native -C target-feature=+sse4.1,-avx2" \
  cargo bench -- highway-builder
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].