+ - 0:00:00
Notes for current slide
Notes for next slide

Bao

a general-purpose cryptographic tree hash

and perhaps the fastest hash function in the world

1 / 26

Caveats

"Fastest" is tricky.

Speed depends on your hardware and the size of your input. There is no "fastest hash in the world" on all platforms or for all inputs.

Bao isn't stable yet.

Version 1.0 is a couple months away, and hashes will change before then.

Cryptography is hard.

I'm not a cryptographer, but real cryptographers are helping. Big thanks to Zooko Wilcox-O'Hearn and Samuel Neves.

2 / 26

What is a hash function?

3 / 26

Hash functions

Turn a big file into a small* number.

$ md5sum my_big_movie.mp4
78035db461c9ebff34c6da825eb314e2 my_big_movie.mp4
$ sha1sum my_big_movie.mp4
592e98dc68ddd0fca198064a192aaf808cfea6d6 my_big_movie.mp4
$ sha256sum my_big_movie.mp4
93984073d78d2e18be8519601c051ade3796b987faa67286c3a1d5e323286892 my_big_movie.mp4

Different files have completely different hashes.

$ md5sum another_movie.mp4
a099223e1246644e685f8ea3365abc2c another_movie.mp4
$ sha1sum another_movie.mp4
4de5f92070b35e8c90937c38ba1d33dcadd084a8 another_movie.mp4
$ sha256sum another_movie.mp4
50c393f158c3de2db92fa9661bfb00eda5b67c3a777c88524ed3417509631625 another_movie.mp4

* Well, small by a computer's standards. But 64 digits is a pretty big number.

4 / 26

Hash functions

On the internet

5 / 26

Hash functions

On the internet

On the inside

SHA256 image

c stands for the "compression function". Note how the result of each compression is an input to the next one.

* Image source: https://medium.com/@pkmar437/blockchain-for-layman-part-2-a8984fda0acc

6 / 26

Speed demon demo!

7 / 26

What is a tree hash?

8 / 26

Tree hashes

tree hash

  • downsides
    • some overhead (but not much!)
  • upsides
    • parallelism (breaking speed records!)
    • streaming

* Image source: https://en.wikipedia.org/wiki/Merkle_tree

9 / 26

Tree hashes

Streaming

If we store the data blocks and all of the intermediate hashes together in an encoded file, we can stream the data back out and verify it all as we go:

# Take a look at the hash of a movie file.
$ bao hash my_movie.mp4
51362b96d8d7f4d4ef4ff02251ccc1b03ef2989f0efbe9a7b05199f198d51727
# Encode the movie file into the Bao encoded format.
$ bao encode my_movie.mp4 my_movie.mp4.bao
$ ls -lh my_movie.mp4 my_movie.mp4.bao
-rw-r--r-- 1 jacko jacko 797K Nov 27 15:28 my_movie.mp4
-rw-r--r-- 1 jacko jacko 809K Nov 27 15:28 my_movie.mp4.bao
# Stream the movie back out of the encoding,
# while verifying its hash.
$ hash=`bao hash my_movie.mp4`
$ bao decode $hash my_movie.mp4.bao | vlc -
10 / 26

Tree hashes

Streaming

Fancy streaming

$ bao --help
Usage: bao hash [<input>] [<inputs>... | --encoded
| --outboard=<file>]
bao encode <input> (<output> | --outboard=<file>)
bao decode <hash> [<input>] [<output>]
[--outboard=<file>] [--start=<offset>]
[--count=<count>]
bao slice <start> <count> [<input>] [<output>]
[--outboard=<file>]
bao decode-slice <hash> <start> <count> [<input>]
[<output>]
bao (--help | --version)

--start lets you seek into the middle of an encoding. "Slicing" lets you extract parts from the middle, so that they can be verified independently, without changing the hash.

11 / 26

Barney the Demosaur

12 / 26

Parallelism in Rust

13 / 26

Rust

Rust

A systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety.

Featuring

  • zero-cost abstractions
  • move semantics
  • guaranteed memory safety
  • threads without data races
  • trait-based generics
  • pattern matching
  • type inference
  • minimal runtime
  • efficient C bindings
14 / 26

Rust

Rayon

https://github.com/rayon-rs/rayon

Data parallelism made easy.

fn hash_recurse_rayon(
input: &[u8],
finalization: Finalization,
) -> Hash {
// The chunk case. Just hash the chunk.
if input.len() <= CHUNK_SIZE {
return hash_chunk(input, finalization);
}
// The parent case. Divide the input into two parts
// and recurse through the left and right subtrees
// in parallel.
let (left, right) = input.split_at(
left_len(input.len() as u64) as usize);
let (left_hash, right_hash) = rayon::join(
|| hash_recurse_rayon(left, NotRoot),
|| hash_recurse_rayon(right, NotRoot),
);
parent_hash(&left_hash, &right_hash, finalization)
}
15 / 26

Rust

Rayon

SIMD

simd

Functions using these intrinsics need annotations like this:

#[target_feature(enable = "avx2")]
pub unsafe fn compress(
h: &mut StateWords,
msg: &Block,
count: u128,
lastblock: u64,
lastnode: u64,
) {
...
}
16 / 26

Rust

Rayon

SIMD

simd

And before you call them you need to do checks like this:

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
if is_x86_feature_detected!("avx2") {
return avx2::compress;
}
}
return portable::compress;
17 / 26

Rust

Rayon

SIMD

BLAKE2

blake2

Each of the rows can be stored in a single vector.

But it's actually faster to hash 4 (BLAKE2b) or 8 (BLAKE2s) inputs in parallel, using 16 vectors.

When AVX-512 comes out, the parallelism will double.

* Image source: https://131002.net/blake/blake.pdf

18 / 26

Cryptographic security

19 / 26

Preimage resistance

The only way to figure out what input generated a given hash, is to try all the possibilities. You can't work backwards.

20 / 26

Preimage resistance

Collision resistance

The only way to figure out what input generated a given hash, is to try all the possibilities. You can't work backwards.

No two different inputs ever generate the same hash.

21 / 26

Preimage resistance

Collision resistance

Length extensions

The only way to figure out what input generated a given hash, is to try all the possibilities. You can't work backwards.

No two different inputs ever generate the same hash.

There's no way to use the hash of one input to help you find the hash of a related input.

22 / 26

Preimage resistance

Collision resistance

Length extensions

Attacks

A collision attack:* SHA256 image

An extension attack:* SHA256 image

23 / 26

Preimage resistance

Collision resistance

Length extensions

Attacks

Security proof

Sufficient conditions for sound tree and sequential hashing modes by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche (the Keccak/SHA3 team)

https://eprint.iacr.org/2009/210.pdf

Three conditions for security:

  • Tree decodability: You can tell leaves and parents apart.
  • Message completeness: You can reconstruct the original input from the tree.
  • Final-node separability: You can tell the root apart from the rest.

* Images on the previous slide are from the paper above.

24 / 26

Monster hardware demo!

25 / 26

Future directions

BLAKE2b vs BLAKE2s

Alternative tree structures

Thanks for listening!

Questions?

https://github.com/oconnor663/bao

26 / 26

Caveats

"Fastest" is tricky.

Speed depends on your hardware and the size of your input. There is no "fastest hash in the world" on all platforms or for all inputs.

Bao isn't stable yet.

Version 1.0 is a couple months away, and hashes will change before then.

Cryptography is hard.

I'm not a cryptographer, but real cryptographers are helping. Big thanks to Zooko Wilcox-O'Hearn and Samuel Neves.

2 / 26
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow