~/bend-docscommunity

spec/crypto/blake/blake3.bend checks

raw source on the hub · import bend-collections-laws-crypto@1.0.0.0/spec/crypto/blake/blake3.bend as Blake3

3 imports
import Base
import ../../../src/crypto/blake/blake3/types.bend as T
import ../../lib/common.bend as SC

Definitions

def iv source · line 24 · raw

List<&2, U32>

def msg_permutation source · line 27 · raw

List<&2, Nat>

def chunk_start source · line 30 · raw

U32

def chunk_end source · line 33 · raw

U32

def parent_flag source · line 36 · raw

U32

def root_flag source · line 39 · raw

U32

def at source · line 44 · raw

@xs:List<&2, U32> -> @i:Nat -> U32

def put source · line 50 · raw

@xs:List<&2, U32> -> @i:Nat -> @+v:U32 -> List<&2, U32>

def cv_words source · line 56 · raw

@c:0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.CV -> List<&2, U32>

def cv_of source · line 63 · raw

@+ws:List<&2, U32> -> 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.CV

(Each list consumer below starts by matching its list, so that it stays an unevaluated call on a symbolic list; the Nil cases agree with the general formula, since at(Nil, i) = 0 and put(Nil, i, x) = Nil.)

def block_of source · line 70 · raw

@+ws:List<&2, U32> -> 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Block

def rotr source · line 80 · raw

@+x:U32 -> @+n:Nat -> U32

Right rotation by n bits, 0 < n < 32.

def g source · line 84 · raw

@+v:List<&2, U32> -> @+a:Nat -> @+b:Nat -> @+c:Nat -> @+d:Nat -> @+mx:U32 -> @+my:U32 -> List<&2, U32>

The quarter-round G on state positions a, b, c, d with message words mx, my.

def columns source · line 96 · raw

@+v:List<&2, U32> -> @+m:List<&2, U32> -> List<&2, U32>

A round mixes the columns, then the diagonals, of the 4x4 state.

def diagonals source · line 102 · raw

@+v:List<&2, U32> -> @+m:List<&2, U32> -> List<&2, U32>

def round source · line 108 · raw

@v:List<&2, U32> -> @+m:List<&2, U32> -> List<&2, U32>

def permute_go source · line 115 · raw

@ps:List<&2, Nat> -> @+m:List<&2, U32> -> List<&2, U32>

The message words are permuted between rounds: word i of the next round is word msg_permutation[i] of this one.

def permute source · line 120 · raw

@+m:List<&2, U32> -> List<&2, U32>

def rounds source · line 123 · raw

@n:Nat -> @+v:List<&2, U32> -> @+m:List<&2, U32> -> List<&2, U32>

def init source · line 131 · raw

@c:0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.CV -> @+t:U32 -> @+len:U32 -> @+flags:U32 -> List<&2, U32>

The initial state of compress(h, m, t, len, flags): h[0..7], IV[0..3], the counter t (low word, then the high word, always 0 here: an input has fewer than 2^32 chunks), the block length and the flags.

def output source · line 136 · raw

@+v:List<&2, U32> -> 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.CV

The new chaining value: word i xor word i+8 of the final state (the 64-byte extended output is not needed for a 32-byte digest).

def compress source · line 140 · raw

@c:0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.CV -> @b:0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Block -> @+t:U32 -> @+len:U32 -> @+flags:U32 -> 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.CV

Seven rounds over the block's words.

def gather source · line 148 · raw

@n:Nat -> @+base:U32 -> @+next:U32 -> @acc:List<&2, U32> -> @pair:Pair(Array<U32>, U32) -> Pair(Array<U32>, List<&2, U32>)

The sixteen words of the block at word index, in order.

def as_block source · line 153 · raw

@pair:Pair(Array<U32>, List<&2, U32>) -> Pair(Array<U32>, 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Block)

def read_block source · line 157 · raw

@a:Array<U32> -> @+index:U32 -> Pair(Array<U32>, 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Block)

def low_bytes source · line 162 · raw

@w:U32 -> @k:Nat -> U32

A block holding len bytes (len <= 64) is zero past them: the word at byte offset pos keeps its min(4, len - pos) low bytes.

def keep source · line 170 · raw

@w:U32 -> @+pos:Nat -> @+len:Nat -> U32

def zero_tail source · line 173 · raw

@b:0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Block -> @+len:Nat -> 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Block

def chunk_blocks source · line 185 · raw

@n:Nat -> @+t:U32 -> @+index:U32 -> @+flags:U32 -> @+len:Nat -> @cv:0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.CV -> @pair:Pair(Array<U32>, 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Block) -> Pair(Array<U32>, 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out)

The blocks of a chunk are compressed in order starting from the key (IV in hash mode), all with the chunk counter t; the first block carries CHUNK_START and the last CHUNK_END. The last block is not compressed here: it is the chunk's output node (2.5, 2.6 decide its flags and use). n blocks follow the current block (in pair); the last block has len bytes.

def chunk source · line 193 · raw

@a:Array<U32> -> @+t:U32 -> @+index:U32 -> @+len:Nat -> Pair(Array<U32>, 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out)

A chunk of len bytes (1..1024; 0 only for the empty message) at word index has max(1, ceil(len/64)) blocks: n = (len - 1) div 64 full blocks, then a last block of len - 64n bytes.

def chunk_at source · line 198 · raw

@more:Nat -> @+t:U32 -> @+index:U32 -> @+len:Nat -> @a:Array<U32> -> Pair(Array<U32>, 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out)

Every chunk but the last holds 1024 bytes; chunk t starts at word 256t.

def chunks source · line 205 · raw

@+n:Nat -> @+t:U32 -> @+index:U32 -> @+len:Nat -> @pair:Pair(Array<U32>, 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out) -> List<&2, 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out>

The outputs of the chunks, in order; pair holds the current chunk, n chunks follow it, the last one of len bytes.

def message_chunks source · line 212 · raw

@a:Array<U32> -> @+length:Nat -> List<&2, 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out>

A message of length bytes has max(1, ceil(length/1024)) chunks: n = (length - 1) div 1024 full ones, then the last of length - 1024n bytes.

def cv source · line 220 · raw

@o:0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out -> 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.CV

A node's chaining value: its compression with its own flags.

def parent source · line 226 · raw

@l:0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.CV -> @r:0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.CV -> 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out

A parent node: key IV, block = left child CV ++ right child CV, counter 0, length 64, flag PARENT.

def is_nil source · line 229 · raw

@xs:List<&2, 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out> -> Bool

def first source · line 234 · raw

@xs:List<&2, 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out> -> 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out

def join source · line 239 · raw

@l:0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out -> @r:0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out -> @alone:Bool -> 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out

def tree source · line 250 · raw

@+h:Nat -> @+xs:List<&2, 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out> -> 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out

The tree over the chunk outputs xs, 1 <= |xs| <= 2^h. The chunks are its leaves in order; a left subtree is always complete with a power of two of chunks, the largest one that leaves at least one chunk to its right: with h = g+1 and |xs| > 2^g the left subtree takes the first 2^g chunks and the right one the rest, while |xs| <= 2^g (nothing left for the right) means the tree already fits in height g.

def root source · line 264 · raw

@o:0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.Out -> 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.CV

The root node is compressed with ROOT added to its flags; the 32-byte digest is the resulting chaining value, words in little-endian order. A single chunk is itself the root.

def hash source · line 268 · raw

@a:Array<U32> -> @+length:Nat -> 0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.CV

def digest source · line 272 · raw

@c:0xa7e654f9780078ca65bf9e187da99d3e/src/crypto/blake/blake3/types.CV -> Array<U32>

def checked source · line 277 · raw

@valid:Bool -> @a:Array<U32> -> @+length:Nat -> Maybe<&1, Array<U32>>

def sized source · line 283 · raw

@+length:Nat -> @pair:Pair(Array<U32>, U32) -> Maybe<&1, Array<U32>>

None when byte_length exceeds the 4 * capacity bytes the array can hold.

def blake3 source · line 287 · raw

@words:Array<U32> -> @byte_length:Nat -> Maybe<&1, Array<U32>>