BLAKE (hash function)
Cryptographic hash function
- 15 min read
- 6 chapters
Related on Lably
Through Word (computer architecture), Multi-core processor and Pseudocode
The BLAKE2 hash function, based on BLAKE, was announced in 2012. The BLAKE3 hash function, based on BLAKE2, was announced in 2020.
History
BLAKE was submitted to the NIST hash function competition by Jean-Philippe Aumasson, Luca Henzen, Willi Meier, and Raphael C.-W. Phan. In 2008, there were 51 entries. BLAKE made it to the final round consisting of five candidates but lost to Keccak in 2012, which was selected for the SHA-3 algorithm.
Sign in to keep reading
5 more chapters are free with a Lably account.
Algorithm
Like SHA-2, BLAKE comes in two variants: one that uses 32-bit words, used for computing hashes up to 256 bits long, and one that uses 64-bit words, used for computing hashes up to 512 bits long. The core block transformation combines 16 words of input with 16 working variables, but only 8 words (256 or 512 bits) are preserved between blocks.
It uses a table of 16 constant words (the leading 512 or 1024 bits of the fractional part of π as nothing up my sleeve numbers), and a table of 10 16-element permutations:
σ[0] = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 σ[1] = 14 10 4 8 9 15 13 6 1 12 0 2 11 7 5 3 σ[2] = 11 8 12 0 5 2 15 13 10 14 3 6 7 1 9 4 σ[3] = 7 9 3 1 13 12 11 14 2 6 5 10 4 0 15 8 σ[4] = 9 0 5 7 2 4 10 15 14 1 11 12 6 8 3 13 σ[5] = 2 12 6 10 0 11 8 3 4 13 7 5 15 14 1 9 σ[6] = 12 5 1 15 14 13 4 10 0 7 6 3 9 2 8 11 σ[7] = 13 11 7 14 12 1 3 9 5 0 15 4 8 6 2 10 σ[8] = 6 15 14 9 11 3 0 8 12 2 13 7 1 4 10 5 σ[9] = 10 2 8 4 7 6 1 5 15 11 9 14 3 12 13 0
The core operation, equivalent to ChaCha's quarter round, operates on a 4-word column or diagonal a b c d, which is combined with 2 words of message m[] and two constant words n[]. It is performed 8 times per full round:
j ← σ[r%10][2×i] <span style="color:green" id="mwKw">// Index computations</span> k ← σ[r%10][2×i+1] a ← a + b + (m[j] ⊕ n[k]) <span style="color:green" id="mwLA">// Step 1 (with input)</span> d ← (d ⊕ a) >>> 16 c ← c + d <span style="color:green" id="mwLQ">// Step 2 (no input)</span> b ← (b ⊕ c) >>> 12 a ← a + b + (m[k] ⊕ n[j]) <span style="color:green" id="mwLg">// Step 3 (with input)</span> d ← (d ⊕ a) >>> 8 c ← c + d <span style="color:green" id="mwLw">// Step 4 (no input)</span> b ← (b ⊕ c) >>> 7
In the above, r is the round number (0–13), and i varies from 0 to 7.
The differences from the ChaCha quarter-round function are:
- The addition of the message words has been added.
- The rotation directions have been reversed.
"BLAKE reuses the permutation of the ChaCha stream cipher with rotations done in the opposite directions. Some have suspected an advanced optimization, but in fact it originates from a typo in the original BLAKE specifications", Jean-Philippe Aumasson explains in his "Crypto Dictionary".
The 64-bit version (which does not exist in ChaCha) is identical, but the rotation amounts are 32, 25, 16 and 11, respectively, and the number of rounds is increased to 16.
Tweaks
Throughout the NIST hash function competition, entrants are permitted to "tweak" their algorithms to address issues that are discovered. Changes that have been made to BLAKE are: the number of rounds was increased from 10/14 to 14/16. This is to be more conservative about security while still being fast.
Example digests
Hash values of an empty string:
<style data-mw-deduplicate="TemplateStyles:r1239334494" typeof="mw:Extension/templatestyles mw:Transclusion" about="#mwt12" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"},"parts":[{"template":{"target":{"wt":"color","href":"./Template:Color"},"params":{"1":{"wt":"green"},"2":{"wt":"BLAKE-224(\"\")"}},"i":0}}]}' id="mwQg">@media screen{html.skin-theme-clientpref-night .mw-parser-output div:not(.notheme)>.tmp-color,html.skin-theme-clientpref-night .mw-parser-output p>.tmp-color,html.skin-theme-clientpref-night .mw-parser-output table:not(.notheme) .tmp-color{color:inherit!important}}@media screen and (prefers-color-scheme:dark){html.skin-theme-clientpref-os .mw-parser-output div:not(.notheme)>.tmp-color,html.skin-theme-clientpref-os .mw-parser-output p>.tmp-color,html.skin-theme-clientpref-os .mw-parser-output table:not(.notheme) .tmp-color{color:inherit!important}}</style><span class="tmp-color" style="color:green" about="#mwt12" id="mwQw">BLAKE-224("")</span> = 7dc5313b1c04512a174bd6503b89607aecbee0903d40a8a569c94eed <link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1239334494" about="#mwt14" typeof="mw:Extension/templatestyles mw:Transclusion" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"},"parts":[{"template":{"target":{"wt":"color","href":"./Template:Color"},"params":{"1":{"wt":"green"},"2":{"wt":"BLAKE-256(\"\")"}},"i":0}}]}' id="mwRA"/><span class="tmp-color" style="color:green" about="#mwt14" id="mwRQ">BLAKE-256("")</span> = 716f6e863f744b9ac22c97ec7b76ea5f5908bc5b2f67c61510bfc4751384ea7a <link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1239334494" about="#mwt16" typeof="mw:Extension/templatestyles mw:Transclusion" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"},"parts":[{"template":{"target":{"wt":"color","href":"./Template:Color"},"params":{"1":{"wt":"green"},"2":{"wt":"BLAKE-384(\"\")"}},"i":0}}]}' id="mwRg"/><span class="tmp-color" style="color:green" about="#mwt16" id="mwRw">BLAKE-384("")</span> = c6cbd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706 <link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1239334494" about="#mwt18" typeof="mw:Extension/templatestyles mw:Transclusion" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"},"parts":[{"template":{"target":{"wt":"color","href":"./Template:Color"},"params":{"1":{"wt":"green"},"2":{"wt":"BLAKE-512(\"\")"}},"i":0}}]}' id="mwSA"/><span class="tmp-color" style="color:green" about="#mwt18" id="mwSQ">BLAKE-512("")</span> = a8cfbbd73726062df0c6864dda65defe58ef0cc52a5625090fa17601e1eecd1b628e94f396ae402a00acc9eab77b4d4c2e852aaaa25a636d80af3fc7913ef5b8Changing a single bit causes each bit in the output to change with 50% probability, demonstrating an avalanche effect:
<link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1239334494" about="#mwt20" typeof="mw:Extension/templatestyles mw:Transclusion" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"},"parts":[{"template":{"target":{"wt":"color","href":"./Template:Color"},"params":{"1":{"wt":"green"},"2":{"wt":"BLAKE-512(\"The quick brown fox jumps over the lazy dog\")"}},"i":0}}]}' id="mwTQ"/><span class="tmp-color" style="color:green" about="#mwt20" id="mwTg">BLAKE-512("The quick brown fox jumps over the lazy dog")</span> = 1f7e26f63b6ad25a0896fd978fd050a1766391d2fd0471a77afb975e5034b7ad2d9ccf8dfb47abbbe656e1b82fbc634ba42ce186e8dc5e1ce09a885d41f43451 <link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1239334494" about="#mwt22" typeof="mw:Extension/templatestyles mw:Transclusion" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"},"parts":[{"template":{"target":{"wt":"color","href":"./Template:Color"},"params":{"1":{"wt":"green"},"2":{"wt":"BLAKE-512(\"The quick brown fox jumps over the lazy do{{color|red|f}}\")"}},"i":0}}]}' id="mwTw"/><span class="tmp-color" style="color:green" about="#mwt22" id="mwUA">BLAKE-512("The quick brown fox jumps over the lazy do<link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1239334494" about="#mwt24" typeof="mw:Extension/templatestyles" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"}}'/><span class="tmp-color" style="color:red">f</span>")</span> = a701c2a1f9baabd8b1db6b75aee096900276f0b86dc15d247ecc03937b370324a16a4ffc0c3a85cd63229cfa15c15f4ba6d46ae2e849ed6335e9ff43b764198a(In this example 266 matching bits out of 512 is about 52% due to the random nature of the avalanche.)
BLAKE2
BLAKE2 is a cryptographic hash function based on BLAKE, created by Jean-Philippe Aumasson, Samuel Neves, Zooko Wilcox-O'Hearn, and Christian Winnerlein. The design goal was to replace the widely used, but broken, MD5 and SHA-1 algorithms in applications requiring high performance in software. BLAKE2 was announced on December 21, 2012. A reference implementation is available under CC0, the OpenSSL License, and the Apache License 2.0.
BLAKE2b is faster than MD5, SHA-1, SHA-2, and SHA-3, on 64-bit x86-64 and ARM architectures. Its creators state that BLAKE2 provides better security than SHA-2 and similar to that of SHA-3: immunity to length extension, indifferentiability from a random oracle, etc.
BLAKE2 removes addition of constants to message words from BLAKE round function, changes two rotation constants, simplifies padding, adds parameter block that is XOR'ed with initialization vectors, and reduces the number of rounds from 16 to 12 for BLAKE2b (successor of BLAKE-512), and from 14 to 10 for BLAKE2s (successor of BLAKE-256).
BLAKE2 supports keying, salting, personalization, and hash tree modes, and can output digests from 1 up to 64 bytes for BLAKE2b, or up to 32 bytes for BLAKE2s. There are also parallel versions designed for increased performance on multi-core processors; BLAKE2bp (4-way parallel) and BLAKE2sp (8-way parallel).
BLAKE2X is a family of extendable-output functions (XOFs). Whereas BLAKE2 is limited to 64-byte digests, BLAKE2X allows for digests of up to 256 GiB. BLAKE2X is itself not an instance of a hash function, and must be based on an actual BLAKE2 instance. An example of a BLAKE2X instance could be BLAKE2Xb16MiB, which would be a BLAKE2X version based on BLAKE2b producing 16,777,216-byte digests (or exactly 16 MiB, hence the name of such an instance).
BLAKE2b and BLAKE2s are specified in RFC 7693. Optional features using the parameter block (salting, personalized hashes, tree hashing, et cetera), are not specified, and thus neither is support for BLAKE2bp, BLAKE2sp, or BLAKE2X.
Initialization vector
BLAKE2b uses an initialization vector that is the same as the IV used by SHA-512. These values are transparently obtained by taking the first 64 bits of the fractional parts of the positive square roots of the first eight prime numbers.
IV<sub id="mwkQ">0</sub> = 0x6a09e667f3bcc908 <span style="color: green" id="mwkg">// Frac(sqrt(2))</span> IV<sub id="mwkw">1</sub> = 0xbb67ae8584caa73b <span style="color: green" id="mwlA">// Frac(sqrt(3))</span> IV<sub id="mwlQ">2</sub> = 0x3c6ef372fe94f82b <span style="color: green" id="mwlg">// Frac(sqrt(5))</span> IV<sub id="mwlw">3</sub> = 0xa54ff53a5f1d36f1 <span style="color: green" id="mwmA">// Frac(sqrt(7))</span> IV<sub id="mwmQ">4</sub> = 0x510e527fade682d1 <span style="color: green" id="mwmg">// Frac(sqrt(11))</span> IV<sub id="mwmw">5</sub> = 0x9b05688c2b3e6c1f <span style="color: green" id="mwnA">// Frac(sqrt(13))</span> IV<sub id="mwnQ">6</sub> = 0x1f83d9abfb41bd6b <span style="color: green" id="mwng">// Frac(sqrt(17))</span> IV<sub id="mwnw">7</sub> = 0x5be0cd19137e2179 <span style="color: green" id="mwoA">// Frac(sqrt(19))</span>
BLAKE2b algorithm
Pseudocode for the BLAKE2b algorithm. The BLAKE2b algorithm uses 8-byte (UInt64) words, and 128-byte chunks.
<span style="color: #004DBB;" id="mwpQ"><b id="mwpg">Algorithm</b></span> BLAKE2b <span style="color: #004DBB;" id="mwpw"><b id="mwqA">Input:</b></span> M <span style="color: green;" id="mwqQ"><i id="mwqg">Message to be hashed</i></span> cbMessageLen: Number, (0..2<sup id="mwqw">128</sup>) <span style="color: green;" id="mwrA"><i id="mwrQ">Length of the message in bytes</i></span> Key <span style="color: green;" id="mwrg"><i id="mwrw">Optional 0..64 byte key</i></span> cbKeyLen: Number, (0..64) <span style="color: green;" id="mwsA"><i id="mwsQ">Length of optional key in bytes</i></span> cbHashLen: Number, (1..64) <span style="color: green;" id="mwsg"><i id="mwsw">Desired hash length in bytes</i></span> <span style="color: #004DBB;" id="mwtA"><b id="mwtQ">Output:</b></span> Hash <span style="color: green;" id="mwtg"><i id="mwtw">Hash of cbHashLen bytes</i></span> <span style="color: green;" id="mwuA"><i id="mwuQ">Initialize State vector <b id="mwug">h</b> with <b id="mwuw">IV</b></i></span> h<sub id="mwvA">0..7</sub> ← IV<sub id="mwvQ">0..7</sub> <span style="color: green;" id="mwvg"><i id="mwvw">Mix key size (cbKeyLen) and desired hash length (cbHashLen) into h<sub id="mwwA">0</sub></i></span> h<sub id="mwwQ">0</sub> ← h<sub id="mwwg">0</sub> xor 0x0101kknn <span style="color: green;" id="mwww"><i id="mwxA">where <b id="mwxQ">kk</b> is Key Length (in bytes)</i></span> <span style="color: green;" id="mwxg"><b id="mwxw">nn</b> <i id="mwyA">is Desired Hash Length (in bytes)</i></span> <span style="color: green;" id="mwyQ"><i id="mwyg">Each time we Compress we record how many bytes have been compressed</i></span> cBytesCompressed ← 0 cBytesRemaining ← cbMessageLen <span style="color: green;" id="mwyw"><i id="mwzA">If there was a key supplied (i.e. cbKeyLen > 0)</i> <i id="mwzQ">then pad with trailing zeros to make it 128-bytes (i.e. 16 words) </i> <i id="mwzg">and prepend it to the message <b id="mwzw">M</b></i></span> <span style="color: #004DBB;" id="mw0A"><b id="mw0Q">if</b></span> (cbKeyLen > 0) <span style="color: #004DBB;" id="mw0g"><b id="mw0w">then</b></span> M ← Pad(Key, 128) || M cBytesRemaining ← cBytesRemaining + 128 <span style="color: #004DBB;" id="mw1A"><b id="mw1Q">end if</b></span> <span style="color: green;" id="mw1g"><i id="mw1w">Compress whole 128-byte chunks of the message, except the last chunk</i></span> <span style="color: #004DBB;" id="mw2A"><b id="mw2Q">while</b></span> (cBytesRemaining > 128) <span style="color: #004DBB;" id="mw2g"><b id="mw2w">do</b></span> chunk ← get next 128 bytes of message <b id="mw3A">M</b> cBytesCompressed ← cBytesCompressed + 128 <span style="color: green;" id="mw3Q"><i id="mw3g">increase count of bytes that have been compressed</i></span> cBytesRemaining ← cBytesRemaining - 128 <span style="color: green;" id="mw3w"><i id="mw4A">decrease count of bytes in <b id="mw4Q">M</b> remaining to be processed</i></span> h ← Compress(h, chunk, cBytesCompressed, false) <span style="color: green;" id="mw4g"><i id="mw4w">false ⇒ this is not the last chunk</i></span> <span style="color: #004DBB;" id="mw5A"><b id="mw5Q">end while</b></span> <span style="color: green;" id="mw5g"><i id="mw5w">Compress the final bytes from <b id="mw6A">M</b></i></span> chunk ← get next 128 bytes of message <b id="mw6Q">M</b> <span style="color: green;" id="mw6g"><i id="mw6w">We will get cBytesRemaining bytes (i.e. 0..128 bytes)</i></span> cBytesCompressed ← cBytesCompressed+cBytesRemaining <span style="color: green;" id="mw7A"><i id="mw7Q">The actual number of bytes leftover in <b id="mw7g">M</b></i></span> chunk ← Pad(chunk, 128) <span style="color: green;" id="mw7w"><i id="mw8A">If <b id="mw8Q">M</b> was empty, then we will still compress a final chunk of zeros</i></span> h ← Compress(h, chunk, cBytesCompressed, true) <span style="color: green;" id="mw8g"><i id="mw8w">true ⇒ this is the last chunk</i></span> <span style="color: #004DBB;" id="mw9A"><b id="mw9Q">Result</b></span> ← first cbHashLen bytes of little endian state vector h <span style="color: #004DBB;" id="mw9g"><b id="mw9w">End Algorithm</b></span> BLAKE2b
Compress
The Compress function takes a full 128-byte chunk of the input message and mixes it into the ongoing state array:
<span style="color: #004DBB;" id="mw_A"><b id="mw_Q">Function</b></span> Compress <span style="color: #004DBB;" id="mw_g"><b id="mw_w">Input:</b></span> h <span style="color: green;" id="mwAQA"><i id="mwAQE">Persistent state vector</i></span> chunk <span style="color: green;" id="mwAQI"><i id="mwAQM">128-byte (16 double word) chunk of message to compress</i></span> t: Number, 0..2<sup id="mwAQQ">128</sup> <span style="color: green;" id="mwAQU"><i id="mwAQY">Count of bytes that have been fed into the Compression</i></span> IsLastBlock: Boolean <span style="color: green;" id="mwAQc"><i id="mwAQg">Indicates if this is the final round of compression</i></span> <span style="color: #004DBB;" id="mwAQk"><b id="mwAQo">Output:</b></span> h <span style="color: green;" id="mwAQs"><i id="mwAQw">Updated persistent state vector</i></span> <span style="color: green;" id="mwAQ0"><i id="mwAQ4">Setup local work vector V</i></span> V<sub id="mwAQ8">0..7</sub> ← h<sub id="mwARA">0..7</sub> <span style="color: green;" id="mwARE"><i id="mwARI">First eight items are copied from persistent state vector <b id="mwARM">h</b></i></span> V<sub id="mwARQ">8..15</sub> ← IV<sub id="mwARU">0..7</sub> <span style="color: green;" id="mwARY"><i id="mwARc">Remaining eight items are initialized from the <b id="mwARg">IV</b></i></span> <span style="color: green;" id="mwARk"><i id="mwARo">Mix the 128-bit counter <b id="mwARs">t</b> into V</i><sub id="mwARw">12</sub>:V<sub id="mwAR0">13</sub></span> V<sub id="mwAR4">12</sub> ← V<sub id="mwAR8">12</sub> <span style="color: #004DBB;" id="mwASA"><b id="mwASE">xor</b></span> Lo(t) <span style="color: green;" id="mwASI"><i id="mwASM">Lo 64-bits of UInt128 <b id="mwASQ">t</b></i></span> V<sub id="mwASU">13</sub> ← V<sub id="mwASY">13</sub> <span style="color: #004DBB;" id="mwASc"><b id="mwASg">xor</b></span> Hi(t) <span style="color: green;" id="mwASk"><i id="mwASo">Hi 64-bits of UInt128 <b id="mwASs">t</b></i></span> <span style="color: green;" id="mwASw"><i id="mwAS0">If this is the last block then invert all the bits in V<sub id="mwAS4">14</sub></i></span> <span style="color: #004DBB;" id="mwAS8"><b id="mwATA">if</b></span> IsLastBlock <span style="color: #004DBB;" id="mwATE"><b id="mwATI">then</b></span> V<sub id="mwATM">14</sub> ← V<sub id="mwATQ">14</sub> <span style="color: #004DBB;" id="mwATU"><b id="mwATY">xor</b></span> 0xFFFFFFFFFFFFFFFF <span style="color: green;" id="mwATc"><i id="mwATg">Treat each 128-byte message <b id="mwATk">chunk</b> as sixteen 8-byte (64-bit) words <b id="mwATo">m</b></i></span> m<sub id="mwATs">0..15</sub> ← chunk <span style="color: green;" id="mwATw"><i id="mwAT0">Twelve rounds of cryptographic message mixing</i></span> <span style="color: #004DBB;" id="mwAT4"><b id="mwAT8">for</b></span> i <span style="color: #004DBB;" id="mwAUA"><b id="mwAUE">from</b></span> 0 <span style="color: #004DBB;" id="mwAUI"><b id="mwAUM">to</b></span> 11 <span style="color: #004DBB;" id="mwAUQ"><b id="mwAUU">do</b></span> <span style="color: green;" id="mwAUY"><i id="mwAUc">Select message mixing schedule for this round.</i> <i id="mwAUg">BLAKE2b uses 12 rounds, while σ has only 10 entries.</i></span> S<sub id="mwAUk">0..15</sub> ← σ[i <span style="color: #004DBB;" id="mwAUo"><b id="mwAUs">mod</b></span> 10] <span style="color: green;" id="mwAUw"><i id="mwAU0">Rounds 10 and 11 use σ[0] and σ[1] respectively</i></span> Mix(V<sub id="mwAU4">0</sub>, V<sub id="mwAU8">4</sub>, V<sub id="mwAVA">8</sub>, V<sub id="mwAVE">12</sub>, m[S<sub id="mwAVI">0</sub>], m[S<sub id="mwAVM">1</sub>]) Mix(V<sub id="mwAVQ">1</sub>, V<sub id="mwAVU">5</sub>, V<sub id="mwAVY">9</sub>, V<sub id="mwAVc">13</sub>, m[S<sub id="mwAVg">2</sub>], m[S<sub id="mwAVk">3</sub>]) Mix(V<sub id="mwAVo">2</sub>, V<sub id="mwAVs">6</sub>, V<sub id="mwAVw">10</sub>, V<sub id="mwAV0">14</sub>, m[S<sub id="mwAV4">4</sub>], m[S<sub id="mwAV8">5</sub>]) Mix(V<sub id="mwAWA">3</sub>, V<sub id="mwAWE">7</sub>, V<sub id="mwAWI">11</sub>, V<sub id="mwAWM">15</sub>, m[S<sub id="mwAWQ">6</sub>], m[S<sub id="mwAWU">7</sub>]) Mix(V<sub id="mwAWY">0</sub>, V<sub id="mwAWc">5</sub>, V<sub id="mwAWg">10</sub>, V<sub id="mwAWk">15</sub>, m[S<sub id="mwAWo">8</sub>], m[S<sub id="mwAWs">9</sub>]) Mix(V<sub id="mwAWw">1</sub>, V<sub id="mwAW0">6</sub>, V<sub id="mwAW4">11</sub>, V<sub id="mwAW8">12</sub>, m[S<sub id="mwAXA">10</sub>], m[S<sub id="mwAXE">11</sub>]) Mix(V<sub id="mwAXI">2</sub>, V<sub id="mwAXM">7</sub>, V<sub id="mwAXQ">8</sub>, V<sub id="mwAXU">13</sub>, m[S<sub id="mwAXY">12</sub>], m[S<sub id="mwAXc">13</sub>]) Mix(V<sub id="mwAXg">3</sub>, V<sub id="mwAXk">4</sub>, V<sub id="mwAXo">9</sub>, V<sub id="mwAXs">14</sub>, m[S<sub id="mwAXw">14</sub>], m[S<sub id="mwAX0">15</sub>]) <span style="color: #004DBB;" id="mwAX4"><b id="mwAX8">end for</b></span> <span style="color: green;" id="mwAYA"><i id="mwAYE">Mix the upper and lower halves of V into ongoing state vector h</i></span> h<sub id="mwAYI">0..7</sub> ← h<sub id="mwAYM">0..7</sub> <span style="color: #004DBB;" id="mwAYQ"><b id="mwAYU">xor</b></span> V<sub id="mwAYY">0..7</sub> h<sub id="mwAYc">0..7</sub> ← h<sub id="mwAYg">0..7</sub> <span style="color: #004DBB;" id="mwAYk"><b id="mwAYo">xor</b></span> V<sub id="mwAYs">8..15</sub> <b id="mwAYw">Result</b> ← h <span style="color: #004DBB;" id="mwAY0"><b id="mwAY4">End Function</b></span> Compress
Mix
The Mix function is called by the Compress function, and mixes two 8-byte words from the message into the hash state. In most implementations this function would be written inline, or as an inlined function.
<span style="color: #004DBB;" id="mwAZQ"><b id="mwAZU">Function</b></span> Mix <span style="color: #004DBB;" id="mwAZY"><b id="mwAZc">Inputs:</b></span> V<sub id="mwAZg">a</sub>, V<sub id="mwAZk">b</sub>, V<sub id="mwAZo">c</sub>, V<sub id="mwAZs">d</sub> <span style="color: green;" id="mwAZw"><i id="mwAZ0">four 8-byte word entries from the work vector V</i></span> x, y <span style="color: green;" id="mwAZ4"><i id="mwAZ8">two 8-byte word entries from padded message m</i></span> <span style="color: #004DBB;" id="mwAaA"><b id="mwAaE">Output:</b></span> V<sub id="mwAaI">a</sub>, V<sub id="mwAaM">b</sub>, V<sub id="mwAaQ">c</sub>, V<sub id="mwAaU">d</sub> <span style="color: green;" id="mwAaY"><i id="mwAac">the modified versions of V<sub id="mwAag">a</sub>, V<sub id="mwAak">b</sub>, V<sub id="mwAao">c</sub>, V<sub id="mwAas">d</sub></i></span> V<sub id="mwAaw">a</sub> ← V<sub id="mwAa0">a</sub> + V<sub id="mwAa4">b</sub> + x <span style="color: green;" id="mwAa8"><i id="mwAbA">with input</i></span> V<sub id="mwAbE">d</sub> ← (V<sub id="mwAbI">d</sub> <span style="color: #004DBB;" id="mwAbM"><b id="mwAbQ">xor</b></span> V<sub id="mwAbU">a</sub>) <span style="color: #004DBB;" id="mwAbY"><b id="mwAbc">rotateright</b></span> 32 V<sub id="mwAbg">c</sub> ← V<sub id="mwAbk">c</sub> + V<sub id="mwAbo">d</sub> <span style="color: green;" id="mwAbs"><i id="mwAbw">no input</i></span> V<sub id="mwAb0">b</sub> ← (V<sub id="mwAb4">b</sub> <span style="color: #004DBB;" id="mwAb8"><b id="mwAcA">xor</b></span> V<sub id="mwAcE">c</sub>) <span style="color: #004DBB;" id="mwAcI"><b id="mwAcM">rotateright</b></span> 24 V<sub id="mwAcQ">a</sub> ← V<sub id="mwAcU">a</sub> + V<sub id="mwAcY">b</sub> + y <span style="color: green;" id="mwAcc"><i id="mwAcg">with input</i></span> V<sub id="mwAck">d</sub> ← (V<sub id="mwAco">d</sub> <span style="color: #004DBB;" id="mwAcs"><b id="mwAcw">xor</b></span> V<sub id="mwAc0">a</sub>) <span style="color: #004DBB;" id="mwAc4"><b id="mwAc8">rotateright</b></span> 16 V<sub id="mwAdA">c</sub> ← V<sub id="mwAdE">c</sub> + V<sub id="mwAdI">d</sub> <span style="color: green;" id="mwAdM"><i id="mwAdQ">no input</i></span> V<sub id="mwAdU">b</sub> ← (V<sub id="mwAdY">b</sub> <span style="color: #004DBB;" id="mwAdc"><b id="mwAdg">xor</b></span> V<sub id="mwAdk">c</sub>) <span style="color: #004DBB;" id="mwAdo"><b id="mwAds">rotateright</b></span> 63 <b id="mwAdw">Result</b> ← V<sub id="mwAd0">a</sub>, V<sub id="mwAd4">b</sub>, V<sub id="mwAd8">c</sub>, V<sub id="mwAeA">d</sub> <span style="color: #004DBB;" id="mwAeE"> <b id="mwAeI">End Function</b></span> Mix
Example digests
Hash values of an empty string:
<link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1239334494" about="#mwt52" typeof="mw:Extension/templatestyles mw:Transclusion" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"},"parts":[{"template":{"target":{"wt":"color","href":"./Template:Color"},"params":{"1":{"wt":"green"},"2":{"wt":"BLAKE2s-224(\"\")"}},"i":0}}]}' id="mwAeY"/><span class="tmp-color" style="color:green" about="#mwt52" id="mwAec">BLAKE2s-224("")</span> = 1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4 <link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1239334494" about="#mwt54" typeof="mw:Extension/templatestyles mw:Transclusion" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"},"parts":[{"template":{"target":{"wt":"color","href":"./Template:Color"},"params":{"1":{"wt":"green"},"2":{"wt":"BLAKE2s-256(\"\")"}},"i":0}}]}' id="mwAeg"/><span class="tmp-color" style="color:green" about="#mwt54" id="mwAek">BLAKE2s-256("")</span> = 69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9 <link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1239334494" about="#mwt56" typeof="mw:Extension/templatestyles mw:Transclusion" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"},"parts":[{"template":{"target":{"wt":"color","href":"./Template:Color"},"params":{"1":{"wt":"green"},"2":{"wt":"BLAKE2b-384(\"\")"}},"i":0}}]}' id="mwAeo"/><span class="tmp-color" style="color:green" about="#mwt56" id="mwAes">BLAKE2b-384("")</span> = b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100 <link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1239334494" about="#mwt58" typeof="mw:Extension/templatestyles mw:Transclusion" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"},"parts":[{"template":{"target":{"wt":"color","href":"./Template:Color"},"params":{"1":{"wt":"green"},"2":{"wt":"BLAKE2b-512(\"\")"}},"i":0}}]}' id="mwAew"/><span class="tmp-color" style="color:green" about="#mwt58" id="mwAe0">BLAKE2b-512("")</span> = 786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ceChanging a single bit causes each bit in the output to change with 50% probability, demonstrating an avalanche effect:
<link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1239334494" about="#mwt60" typeof="mw:Extension/templatestyles mw:Transclusion" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"},"parts":[{"template":{"target":{"wt":"color","href":"./Template:Color"},"params":{"1":{"wt":"green"},"2":{"wt":"BLAKE2b-512(\"The quick brown fox jumps over the lazy dog\")"}},"i":0}}]}' id="mwAfE"/><span class="tmp-color" style="color:green" about="#mwt60" id="mwAfI">BLAKE2b-512("The quick brown fox jumps over the lazy dog")</span> = a8add4bdddfd93e4877d2746e62817b116364a1fa7bc148d95090bc7333b3673f82401cf7aa2e4cb1ecd90296e3f14cb5413f8ed77be73045b13914cdcd6a918 <link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1239334494" about="#mwt62" typeof="mw:Extension/templatestyles mw:Transclusion" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"},"parts":[{"template":{"target":{"wt":"color","href":"./Template:Color"},"params":{"1":{"wt":"green"},"2":{"wt":"BLAKE2b-512(\"The quick brown fox jumps over the lazy do{{color|red|f}}\")"}},"i":0}}]}' id="mwAfM"/><span class="tmp-color" style="color:green" about="#mwt62" id="mwAfQ">BLAKE2b-512("The quick brown fox jumps over the lazy do<link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1239334494" about="#mwt64" typeof="mw:Extension/templatestyles" data-mw='{"name":"templatestyles","attrs":{"src":"Template:Color/styles.css"}}'/><span class="tmp-color" style="color:red">f</span>")</span> = ab6b007747d8068c02e25a6008db8a77c218d94f3b40d2291a7dc8a62090a744c082ea27af01521a102e42f480a31e9844053f456b4b41e8aa78bbe5c12957bbUsers of BLAKE2
- Argon2, the winner of the Password Hashing Competition, uses BLAKE2b
- Chef's Habitat deployment system uses BLAKE2b for package signing
- FreeBSD Ports package management tool uses BLAKE2b
- GNU Core Utilities implements BLAKE2b in its b2sum command
- IPFS allows use of BLAKE2b for tree hashing
- librsync uses BLAKE2b
- Noise Protocol Framework, which is used in WhatsApp and WireGuard, includes BLAKE2 as an option.
- RAR archive format version 5 supports an optional 256-bit BLAKE2sp file checksum instead of the default 32-bit CRC-32; it was implemented in WinRAR v5+
- 7-Zip (in order to support the RAR archive format version 5) can generate the BLAKE2sp signature for each file in the Explorer shell via "CRC SHA" context menu, and choosing '*'
- rmlint uses BLAKE2b for duplicate file detection
- WireGuard uses BLAKE2s for hashing
- Zcash, a cryptocurrency, uses BLAKE2b in the Equihash proof of work, and as a key derivation function
- NANO, a cryptocurrency, uses BLAKE2b in the proof of work, for hashing digital signatures and as a key derivation function
- Polkadot, a multi-chain blockchain uses BLAKE2b as its hashing algorithm.
- Linux kernel, version 5.17 replaced SHA-1 with BLAKE2s for hashing the entropy pool in the random number generator.
- btrfs file system supports BLAKE2b to checksum data and metadata.
- Open Network for Digital Commerce, a Government of India initiative, uses BLAKE-512 to sign API requests.
- checksum, a Windows file hashing program has Blake2s as one of its algorithms
Implementations
In addition to the reference implementation, the following cryptography libraries provide implementations of BLAKE2:
- Botan
- Bouncy Castle
- Crypto++
- Libgcrypt
- libsodium
- OpenSSL
- wolfSSL
BLAKE3
BLAKE3 is a cryptographic hash function based on Bao and BLAKE2, created by Jack O'Connor, Jean-Philippe Aumasson, Samuel Neves, and Zooko Wilcox-O'Hearn. It was announced on January 9, 2020, at Real World Crypto.
BLAKE3 is a single algorithm with many desirable features (parallelism, XOF, KDF, PRF and MAC), in contrast to BLAKE and BLAKE2, which are algorithm families with multiple variants. BLAKE3 has a binary tree structure, so it supports a practically unlimited degree of parallelism (both SIMD and multithreading) given long enough input. The official Rust and C implementations are dual-licensed as public domain (CC0) and the Apache License.
BLAKE3 is designed to be as fast as possible. It is consistently a few times faster than BLAKE2. The BLAKE3 compression function is closely based on that of BLAKE2s, with the biggest difference being that the number of rounds is reduced from 10 to 7, a change based on an argument that past cryptography is too conservative compared to current cryptoanalysis records. In addition to providing parallelism, the Merkle tree format also allows for verified streaming (on-the-fly verifying) and incremental updates.
Users of BLAKE3
- Bazel build system supports using BLAKE3 as a file digest function.
- Ccache uses it for its hash function.
- ClickHouse has it as dependency.
- Total Commander supports BLAKE3 for file checksums.
- IPFS again has support for BLAKE3 hashes.
- OpenZFS supports BLAKE3 from version 2.2
- Cargo (Rust) uses BLAKE3 for checksums.
- Czkawka files janitor https://github.com/qarmin/czkawka
- LLVM has introduced BLAKE3 implementation.
- Wasmer a WebAssembly runtime that uses BLAKE3 hashing.
- Software bill of material software CycloneDX uses it as part of its suite of hash functions.
- Mosaic uses BLAKE3 instead of SHA-512 (SHA-2) for its Ed25519 signature.
- Epic games Lore version control system uses BLAKE3 for its address function.

