From 2b2bad44b01eb3d32766475dc04d0f8c246ec726 Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Thu, 16 Apr 2026 13:16:59 +0200 Subject: [PATCH 1/6] BLAKE3 --- doc/crypt.tex | 75 ++++ src/hashes/blake3.c | 396 +++++++++++++++++++++ src/headers/tomcrypt_custom.h | 1 + src/headers/tomcrypt_hash.h | 26 ++ src/misc/crypt/crypt.c | 3 + src/misc/crypt/crypt_register_all_hashes.c | 5 +- tests/test.c | 3 + 7 files changed, 508 insertions(+), 1 deletion(-) create mode 100644 src/hashes/blake3.c diff --git a/doc/crypt.tex b/doc/crypt.tex index fc879fa9a..27b8691e3 100644 --- a/doc/crypt.tex +++ b/doc/crypt.tex @@ -2998,6 +2998,7 @@ \subsection{Hash Registration} \hline RIPEMD-256 & rmd160\_desc & 32 & 13 \\ \hline BLAKE2S-256 & blake2s\_256\_desc & 32 & 24 \\ \hline BLAKE2B-256 & blake2b\_256\_desc & 32 & 26 \\ + \hline BLAKE3 & blake3\_desc & 32 & 34 \\ \hline SHA-512/224 & sha512\_224\_desc & 28 & 15 \\ \hline Keccak224 & keccak\_224\_desc & 28 & 29 \\ \hline SHA3-224 & sha3\_224\_desc & 28 & 17 \\ @@ -3075,6 +3076,80 @@ \subsection{Hash Registration} } \end{verbatim} +\mysection{BLAKE3} +\index{BLAKE3} +BLAKE3 is a cryptographic hash function that also supports keyed hashing (MAC/PRF) and key derivation. +The standard unkeyed hash uses the normal hash descriptor interface: + +\begin{verbatim} +int blake3_init(hash_state *md); +int blake3_process(hash_state *md, const unsigned char *in, + unsigned long inlen); +int blake3_done(hash_state *md, unsigned char *out); +\end{verbatim} + +The default output is 32 bytes (256 bits). +To enable BLAKE3, define \texttt{LTC\_BLAKE3} in \textit{tomcrypt\_custom.h}. + +\subsection{BLAKE3 Keyed Hash} +\index{blake3\_keyed\_init()} +BLAKE3 keyed hashing can be used as a MAC or PRF with a 32-byte key. It replaces the need for a +separate HMAC construction. + +\begin{verbatim} +int blake3_keyed_init(hash_state *md, const unsigned char *key, + unsigned long keylen); +\end{verbatim} + +The \textit{keylen} parameter must be exactly 32. After initialization, use the standard +\texttt{blake3\_process()} and \texttt{blake3\_done()} to hash data and obtain the tag. + +\subsection{BLAKE3 Key Derivation} +\index{blake3\_derive\_key\_init()} +BLAKE3 key derivation uses a two-pass construction: first the application-specific context string is +hashed internally, then the resulting context key is used to hash the input key material. + +\begin{verbatim} +int blake3_derive_key_init(hash_state *md, + const unsigned char *context, + unsigned long contextlen); +\end{verbatim} + +The \textit{context} should be a globally unique, application-specific string (e.g.\ +\texttt{"myapp 2024-01-01 session-key"}). After initialization, feed the input key material via +\texttt{blake3\_process()} and retrieve the derived key via \texttt{blake3\_done()}. + +\begin{small} +\begin{verbatim} +#include +int main(void) +{ + hash_state md; + unsigned char out[32]; + const unsigned char key[32] = "whats the Elvish word for friend"; + const unsigned char msg[] = "hello"; + + /* Unkeyed hash */ + blake3_init(&md); + blake3_process(&md, msg, 5); + blake3_done(&md, out); + + /* Keyed hash (MAC) */ + blake3_keyed_init(&md, key, 32); + blake3_process(&md, msg, 5); + blake3_done(&md, out); + + /* Key derivation */ + blake3_derive_key_init(&md, + (const unsigned char *)"myapp 2024-01-01 session-key", 28); + blake3_process(&md, key, 32); /* input key material */ + blake3_done(&md, out); /* derived key */ + + return 0; +} +\end{verbatim} +\end{small} + \mysection{Extendable Output Functions (XOF)} Some algorithms provide a special XOF (Extendable Output Functions) mode which allow to generate message digests of an arbitrary length. diff --git a/src/hashes/blake3.c b/src/hashes/blake3.c new file mode 100644 index 000000000..f6383dd17 --- /dev/null +++ b/src/hashes/blake3.c @@ -0,0 +1,396 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file blake3.c + BLAKE3 hash, keyed hash and key derivation, + based on blake3-tiny by Michael Forney (public domain) + https://github.com/michaelforney/blake3-tiny +*/ + +#ifdef LTC_BLAKE3 + +/* Domain-separation flags */ +#define BLAKE3_CHUNK_START (1u << 0) +#define BLAKE3_CHUNK_END (1u << 1) +#define BLAKE3_PARENT (1u << 2) +#define BLAKE3_ROOT (1u << 3) +#define BLAKE3_KEYED_HASH (1u << 4) +#define BLAKE3_DERIVE_KEY_CONTEXT (1u << 5) +#define BLAKE3_DERIVE_KEY_MATERIAL (1u << 6) + +/* BLAKE3 IV -- same as SHA-256 constants */ +static const ulong32 s_iv[8] = { 0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL, 0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL }; + +/* Load 16 little-endian 32-bit words from a 64-byte buffer */ +static void s_load(ulong32 d[16], const unsigned char *s) +{ + int i; + for (i = 0; i < 16; ++i, s += 4) { + d[i] = (ulong32)s[0] + | ((ulong32)s[1] << 8) + | ((ulong32)s[2] << 16) + | ((ulong32)s[3] << 24); + } +} + +/* Load 8 little-endian 32-bit words from a 32-byte key */ +static void s_load_key(ulong32 d[8], const unsigned char *s) +{ + int i; + for (i = 0; i < 8; ++i, s += 4) { + d[i] = (ulong32)s[0] + | ((ulong32)s[1] << 8) + | ((ulong32)s[2] << 16) + | ((ulong32)s[3] << 24); + } +} + +/* BLAKE3 compression function + out - output words (8 always; 16 when BLAKE3_ROOT is set in d) + m - 16-word message block (may alias out) + h - 8-word chaining value + t - chunk counter (64-bit) + b - byte count for this block (0-64) + d - domain flags +*/ +static void s_compress(ulong32 *out, const ulong32 *m, const ulong32 *h, ulong64 t, ulong32 b, ulong32 d) +{ + static const unsigned char s_sigma[7][16] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + { 2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8}, + { 3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1}, + {10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6}, + {12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4}, + { 9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7}, + {11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13}, + }; + ulong32 v[16]; + unsigned int i; + + v[0] = h[0]; v[1] = h[1]; v[2] = h[2]; v[3] = h[3]; + v[4] = h[4]; v[5] = h[5]; v[6] = h[6]; v[7] = h[7]; + v[8] = s_iv[0]; v[9] = s_iv[1]; v[10] = s_iv[2]; v[11] = s_iv[3]; + v[12] = (ulong32)t; + v[13] = (ulong32)(t >> 32); + v[14] = b; + v[15] = d; + +#define B3G(ri, ai, bi, ci, di, mx, my) \ + v[ai] += v[bi] + m[s_sigma[ri][mx]]; \ + v[di] = RORc(v[di] ^ v[ai], 16); \ + v[ci] += v[di]; \ + v[bi] = RORc(v[bi] ^ v[ci], 12); \ + v[ai] += v[bi] + m[s_sigma[ri][my]]; \ + v[di] = RORc(v[di] ^ v[ai], 8); \ + v[ci] += v[di]; \ + v[bi] = RORc(v[bi] ^ v[ci], 7); + +#define B3ROUND(ri) \ + B3G(ri, 0, 4, 8, 12, 0, 1) \ + B3G(ri, 1, 5, 9, 13, 2, 3) \ + B3G(ri, 2, 6, 10, 14, 4, 5) \ + B3G(ri, 3, 7, 11, 15, 6, 7) \ + B3G(ri, 0, 5, 10, 15, 8, 9) \ + B3G(ri, 1, 6, 11, 12, 10, 11) \ + B3G(ri, 2, 7, 8, 13, 12, 13) \ + B3G(ri, 3, 4, 9, 14, 14, 15) + + B3ROUND(0) B3ROUND(1) B3ROUND(2) B3ROUND(3) + B3ROUND(4) B3ROUND(5) B3ROUND(6) + +#undef B3G +#undef B3ROUND + + if (d & BLAKE3_ROOT) { + for (i = 8; i < 16; ++i) out[i] = v[i] ^ h[i - 8]; + } + for (i = 0; i < 8; ++i) out[i] = v[i] ^ v[i + 8]; +} + +/* Process one 64-byte block during update (only called when more data follows, so this block is never the ROOT) */ +static void s_blake3_block(hash_state *md, const unsigned char *buf) +{ + ulong32 m[16]; + ulong32 *cv; + ulong64 t; + ulong32 flags; + + flags = md->blake3.flags; + if (md->blake3.block == 0) flags |= BLAKE3_CHUNK_START; + if (md->blake3.block == 15) flags |= BLAKE3_CHUNK_END; + + cv = &md->blake3.cv_buf[md->blake3.cv_off * 8u]; + s_load(m, buf); + s_compress(cv, m, cv, md->blake3.chunk, 64, flags); + + if (++md->blake3.block == 16) { + md->blake3.block = 0; + for (t = ++md->blake3.chunk; (t & 1) == 0; t >>= 1) { + --md->blake3.cv_off; + cv = &md->blake3.cv_buf[md->blake3.cv_off * 8u]; + s_compress(cv, cv, md->blake3.key, 0, 64, BLAKE3_PARENT | md->blake3.flags); + } + ++md->blake3.cv_off; + cv = &md->blake3.cv_buf[md->blake3.cv_off * 8u]; + XMEMCPY(cv, md->blake3.key, sizeof(md->blake3.key)); + } +} + +/** + Initialize a BLAKE3 hash state (unkeyed hash mode). + @param md The hash state to initialize + @return CRYPT_OK on success +*/ +int blake3_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + XMEMSET(&md->blake3, 0, sizeof(md->blake3)); + XMEMCPY(md->blake3.key, s_iv, sizeof(md->blake3.key)); + XMEMCPY(md->blake3.cv_buf, s_iv, sizeof(md->blake3.key)); + return CRYPT_OK; +} + +/** + Initialize a BLAKE3 keyed-hash state (MAC / PRF mode). + @param md The hash state to initialize + @param key The 32-byte key + @param keylen Length of key (must be 32) + @return CRYPT_OK on success +*/ +int blake3_keyed_init(hash_state *md, const unsigned char *key, unsigned long keylen) +{ + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(key != NULL); + if (keylen != 32) return CRYPT_INVALID_KEYSIZE; + + XMEMSET(&md->blake3, 0, sizeof(md->blake3)); + s_load_key(md->blake3.key, key); + XMEMCPY(md->blake3.cv_buf, md->blake3.key, sizeof(md->blake3.key)); + md->blake3.flags = BLAKE3_KEYED_HASH; + return CRYPT_OK; +} + +/** + Initialize a BLAKE3 key-derivation state. + Hashes the context string internally, then prepares the state so that + subsequent process/done calls derive a key from the input material. + @param md The hash state to initialize + @param context Application-specific context string + @param contextlen Length of the context string in bytes + @return CRYPT_OK on success +*/ +int blake3_derive_key_init(hash_state *md, const unsigned char *context, unsigned long contextlen) +{ + unsigned char context_key[32]; + int err; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(context != NULL); + + /* Pass 1: hash the context string with DERIVE_KEY_CONTEXT */ + XMEMSET(&md->blake3, 0, sizeof(md->blake3)); + XMEMCPY(md->blake3.key, s_iv, sizeof(md->blake3.key)); + XMEMCPY(md->blake3.cv_buf, s_iv, sizeof(md->blake3.key)); + md->blake3.flags = BLAKE3_DERIVE_KEY_CONTEXT; + + if ((err = blake3_process(md, context, contextlen)) != CRYPT_OK) return err; + if ((err = blake3_done(md, context_key)) != CRYPT_OK) return err; + + /* Pass 2: set up for key material hashing with DERIVE_KEY_MATERIAL; blake3_done already zeroed the state */ + s_load_key(md->blake3.key, context_key); + XMEMCPY(md->blake3.cv_buf, md->blake3.key, sizeof(md->blake3.key)); + md->blake3.flags = BLAKE3_DERIVE_KEY_MATERIAL; + + zeromem(context_key, sizeof(context_key)); + return CRYPT_OK; +} + +/** + Process data through BLAKE3. + @param md The hash state + @param in Data to hash + @param inlen Length of data in bytes + @return CRYPT_OK on success +*/ +int blake3_process(hash_state *md, const unsigned char *in, unsigned long inlen) +{ + unsigned long n; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(in != NULL); + + if (md->blake3.bytes > 0) { + n = 64uL - md->blake3.bytes; + if (inlen < n) n = inlen; + XMEMCPY(md->blake3.input + md->blake3.bytes, in, n); + in += n; + inlen -= n; + md->blake3.bytes += (ulong32)n; + if (inlen == 0) return CRYPT_OK; + s_blake3_block(md, md->blake3.input); + } + while (inlen > 64) { + s_blake3_block(md, in); + in += 64; + inlen -= 64; + } + md->blake3.bytes = (ulong32)inlen; + XMEMCPY(md->blake3.input, in, inlen); + return CRYPT_OK; +} + +/** + Finalize BLAKE3 and produce the 32-byte digest. + @param md The hash state + @param out [out] 32-byte digest + @return CRYPT_OK on success +*/ +int blake3_done(hash_state *md, unsigned char *out) +{ + ulong32 m[16], root[16]; + ulong32 flags, b, x; + unsigned long i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + XMEMSET(md->blake3.input + md->blake3.bytes, 0, 64u - md->blake3.bytes); + s_load(m, md->blake3.input); + + flags = BLAKE3_CHUNK_END | md->blake3.flags; + if (md->blake3.block == 0) flags |= BLAKE3_CHUNK_START; + + if (md->blake3.cv_off == 0) { + b = md->blake3.bytes; + s_compress(root, m, md->blake3.cv_buf, 0, b, flags | BLAKE3_ROOT); + } + else { + ulong32 *cv = &md->blake3.cv_buf[md->blake3.cv_off * 8u]; + s_compress(cv, m, cv, md->blake3.chunk, md->blake3.bytes, flags); + while ((cv -= 8) != md->blake3.cv_buf) s_compress(cv, cv, md->blake3.key, 0, 64, BLAKE3_PARENT | md->blake3.flags); + s_compress(root, md->blake3.cv_buf, md->blake3.key, 0, 64, BLAKE3_PARENT | BLAKE3_ROOT | md->blake3.flags); + } + + for (i = 0, x = 0; i < 32; ++i) { + if ((i & 3) == 0) x = root[i >> 2]; + out[i] = (unsigned char)(x & 0xff); + x >>= 8; + } + + zeromem(&md->blake3, sizeof(md->blake3)); + return CRYPT_OK; +} + +/* + Self-test with official BLAKE3 test vectors + https://github.com/BLAKE3-team/BLAKE3/blob/master/test_vectors/test_vectors.json + + Input: byte[i] = i % 251. Key: "whats the Elvish word for friend" + Context: "BLAKE3 2019-12-27 16:29:52 test vectors context" +*/ + +int blake3_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned long input_len; + unsigned char hash[32]; + unsigned char keyed_hash[32]; + unsigned char derive_key[32]; + } tests[] = { + /* input_len = 0 */ + { 0, + { 0xaf, 0x13, 0x49, 0xb9, 0xf5, 0xf9, 0xa1, 0xa6, 0xa0, 0x40, 0x4d, 0xea, 0x36, 0xdc, 0xc9, 0x49, + 0x9b, 0xcb, 0x25, 0xc9, 0xad, 0xc1, 0x12, 0xb7, 0xcc, 0x9a, 0x93, 0xca, 0xe4, 0x1f, 0x32, 0x62 }, + { 0x92, 0xb2, 0xb7, 0x56, 0x04, 0xed, 0x3c, 0x76, 0x1f, 0x9d, 0x6f, 0x62, 0x39, 0x2c, 0x8a, 0x92, + 0x27, 0xad, 0x0e, 0xa3, 0xf0, 0x95, 0x73, 0xe7, 0x83, 0xf1, 0x49, 0x8a, 0x4e, 0xd6, 0x0d, 0x26 }, + { 0x2c, 0xc3, 0x97, 0x83, 0xc2, 0x23, 0x15, 0x4f, 0xea, 0x8d, 0xfb, 0x7c, 0x1b, 0x16, 0x60, 0xf2, + 0xac, 0x2d, 0xcb, 0xd1, 0xc1, 0xde, 0x82, 0x77, 0xb0, 0xb0, 0xdd, 0x39, 0xb7, 0xe5, 0x0d, 0x7d } + }, + /* input_len = 1 */ + { 1, + { 0x2d, 0x3a, 0xde, 0xdf, 0xf1, 0x1b, 0x61, 0xf1, 0x4c, 0x88, 0x6e, 0x35, 0xaf, 0xa0, 0x36, 0x73, + 0x6d, 0xcd, 0x87, 0xa7, 0x4d, 0x27, 0xb5, 0xc1, 0x51, 0x02, 0x25, 0xd0, 0xf5, 0x92, 0xe2, 0x13 }, + { 0x6d, 0x78, 0x78, 0xdf, 0xff, 0x2f, 0x48, 0x56, 0x35, 0xd3, 0x90, 0x13, 0x27, 0x8a, 0xe1, 0x4f, + 0x14, 0x54, 0xb8, 0xc0, 0xa3, 0xa2, 0xd3, 0x4b, 0xc1, 0xab, 0x38, 0x22, 0x8a, 0x80, 0xc9, 0x5b }, + { 0xb3, 0xe2, 0xe3, 0x40, 0xa1, 0x17, 0xa4, 0x99, 0xc6, 0xcf, 0x23, 0x98, 0xa1, 0x9e, 0xe0, 0xd2, + 0x9c, 0xca, 0x2b, 0xb7, 0x40, 0x4c, 0x73, 0x06, 0x33, 0x82, 0x69, 0x3b, 0xf6, 0x6c, 0xb0, 0x6c } + }, + /* input_len = 65 */ + { 65, + { 0xde, 0x1e, 0x5f, 0xa0, 0xbe, 0x70, 0xdf, 0x6d, 0x2b, 0xe8, 0xff, 0xfd, 0x0e, 0x99, 0xce, 0xaa, + 0x8e, 0xb6, 0xe8, 0xc9, 0x3a, 0x63, 0xf2, 0xd8, 0xd1, 0xc3, 0x0e, 0xcb, 0x6b, 0x26, 0x3d, 0xee }, + { 0xc0, 0xa4, 0xed, 0xef, 0xa2, 0xd2, 0xac, 0xcb, 0x92, 0x77, 0xc3, 0x71, 0xac, 0x12, 0xfc, 0xdb, + 0xb5, 0x29, 0x88, 0xa8, 0x6e, 0xdc, 0x54, 0xf0, 0x71, 0x6e, 0x15, 0x91, 0xb4, 0x32, 0x6e, 0x72 }, + { 0x51, 0xfd, 0x05, 0xc3, 0xc1, 0xcf, 0xbc, 0x8e, 0xd6, 0x7d, 0x13, 0x9a, 0xd7, 0x6f, 0x5c, 0xf8, + 0x23, 0x6c, 0xd2, 0xac, 0xd2, 0x66, 0x27, 0xa3, 0x0c, 0x10, 0x4d, 0xfd, 0x9d, 0x3f, 0xf8, 0xa8 } + }, + /* input_len = 1024 (single chunk boundary) */ + { 1024, + { 0x42, 0x21, 0x47, 0x39, 0xf0, 0x95, 0xa4, 0x06, 0xf3, 0xfc, 0x83, 0xde, 0xb8, 0x89, 0x74, 0x4a, + 0xc0, 0x0d, 0xf8, 0x31, 0xc1, 0x0d, 0xaa, 0x55, 0x18, 0x9b, 0x5d, 0x12, 0x1c, 0x85, 0x5a, 0xf7 }, + { 0x75, 0xc4, 0x6f, 0x6f, 0x3d, 0x9e, 0xb4, 0xf5, 0x5e, 0xca, 0xae, 0xe4, 0x80, 0xdb, 0x73, 0x2e, + 0x6c, 0x21, 0x05, 0x54, 0x6f, 0x1e, 0x67, 0x50, 0x03, 0x68, 0x7c, 0x31, 0x71, 0x9c, 0x7b, 0xa4 }, + { 0x73, 0x56, 0xcd, 0x77, 0x20, 0xd5, 0xb6, 0x6b, 0x6d, 0x06, 0x97, 0xeb, 0x31, 0x77, 0xd9, 0xf8, + 0xd7, 0x3a, 0x4a, 0x5c, 0x5e, 0x96, 0x88, 0x96, 0xeb, 0x6a, 0x68, 0x96, 0x84, 0x30, 0x27, 0x06 } + }, + /* input_len = 1025 (multi-chunk) */ + { 1025, + { 0xd0, 0x02, 0x78, 0xae, 0x47, 0xeb, 0x27, 0xb3, 0x4f, 0xae, 0xcf, 0x67, 0xb4, 0xfe, 0x26, 0x3f, + 0x82, 0xd5, 0x41, 0x29, 0x16, 0xc1, 0xff, 0xd9, 0x7c, 0x8c, 0xb7, 0xfb, 0x81, 0x4b, 0x84, 0x44 }, + { 0x35, 0x7d, 0xc5, 0x5d, 0xe0, 0xc7, 0xe3, 0x82, 0xc9, 0x00, 0xfd, 0x6e, 0x32, 0x0a, 0xcc, 0x04, + 0x14, 0x6b, 0xe0, 0x1d, 0xb6, 0xa8, 0xce, 0x72, 0x10, 0xb7, 0x18, 0x9b, 0xd6, 0x64, 0xea, 0x69 }, + { 0xef, 0xfa, 0xa2, 0x45, 0xf0, 0x65, 0xfb, 0xf8, 0x2a, 0xc1, 0x86, 0x83, 0x9a, 0x24, 0x97, 0x07, + 0xc3, 0xbd, 0xdf, 0x6d, 0x3f, 0xdd, 0xa2, 0x2d, 0x1b, 0x95, 0xa3, 0xc9, 0x70, 0x37, 0x9b, 0xcb } + }, + }; + + static const unsigned char test_key[32] = "whats the Elvish word for friend"; + static const char test_context[] = "BLAKE3 2019-12-27 16:29:52 test vectors context"; + unsigned char input[1025], tmp[32]; + hash_state md; + unsigned long j; + int i; + + /* Build test input: byte[i] = i % 251 */ + for (j = 0; j < sizeof(input); ++j) input[j] = (unsigned char)(j % 251); + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); ++i) { + /* hash mode */ + blake3_init(&md); + blake3_process(&md, input, tests[i].input_len); + blake3_done(&md, tmp); + if (ltc_compare_testvector(tmp, 32, tests[i].hash, 32, "BLAKE3", i)) return CRYPT_FAIL_TESTVECTOR; + /* keyed_hash mode */ + blake3_keyed_init(&md, test_key, 32); + blake3_process(&md, input, tests[i].input_len); + blake3_done(&md, tmp); + if (ltc_compare_testvector(tmp, 32, tests[i].keyed_hash, 32, "BLAKE3 keyed", i)) return CRYPT_FAIL_TESTVECTOR; + /* derive_key mode */ + blake3_derive_key_init(&md, (const unsigned char *)test_context, XSTRLEN(test_context)); + blake3_process(&md, input, tests[i].input_len); + blake3_done(&md, tmp); + if (ltc_compare_testvector(tmp, 32, tests[i].derive_key, 32, "BLAKE3 derive_key", i)) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; +#endif +} + +const struct ltc_hash_descriptor blake3_desc = { + "blake3", + 34, /* unique internal ID */ + 32, /* 256-bit digest */ + 64, /* 64-byte input block */ + { 0 }, 0, /* no ASN.1 OID assigned yet */ + &blake3_init, + &blake3_process, + &blake3_done, + &blake3_test, + NULL +}; + +#endif /* LTC_BLAKE3 */ diff --git a/src/headers/tomcrypt_custom.h b/src/headers/tomcrypt_custom.h index ed1440082..e31ef45d9 100644 --- a/src/headers/tomcrypt_custom.h +++ b/src/headers/tomcrypt_custom.h @@ -280,6 +280,7 @@ #define LTC_RIPEMD320 #define LTC_BLAKE2S #define LTC_BLAKE2B +#define LTC_BLAKE3 #define LTC_HASH_HELPERS diff --git a/src/headers/tomcrypt_hash.h b/src/headers/tomcrypt_hash.h index a6bd75028..7bab7486e 100644 --- a/src/headers/tomcrypt_hash.h +++ b/src/headers/tomcrypt_hash.h @@ -155,6 +155,19 @@ struct blake2b_state { }; #endif +#ifdef LTC_BLAKE3 +struct blake3_state { + unsigned char input[64]; /* current input block (not yet compressed) */ + ulong32 cv_buf[54 * 8]; /* chaining-value stack (54 levels x 8 words) */ + ulong32 key[8]; /* mode key: IV, user key, or derived context key */ + ulong32 cv_off; /* top-of-stack index into cv_buf (units: 8 words) */ + ulong32 bytes; /* bytes buffered in input[] */ + ulong32 block; /* block index within current chunk (0-15) */ + ulong32 flags; /* mode flags ORed into every compress call */ + ulong64 chunk; /* completed-chunk counter */ +}; +#endif + typedef union Hash_state { char dummy[1]; #ifdef LTC_CHC_HASH @@ -208,6 +221,9 @@ typedef union Hash_state { #ifdef LTC_BLAKE2B struct blake2b_state blake2b; #endif +#ifdef LTC_BLAKE3 + struct blake3_state blake3; +#endif void *data; } hash_state; @@ -488,6 +504,16 @@ int blake2b_process(hash_state * md, const unsigned char *in, unsigned long inle int blake2b_done(hash_state * md, unsigned char *out); #endif +#ifdef LTC_BLAKE3 +int blake3_init(hash_state *md); +int blake3_keyed_init(hash_state *md, const unsigned char *key, unsigned long keylen); +int blake3_derive_key_init(hash_state *md, const unsigned char *context, unsigned long contextlen); +int blake3_process(hash_state *md, const unsigned char *in, unsigned long inlen); +int blake3_done(hash_state *md, unsigned char *out); +int blake3_test(void); +extern const struct ltc_hash_descriptor blake3_desc; +#endif + #ifdef LTC_MD5 int md5_init(hash_state * md); int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen); diff --git a/src/misc/crypt/crypt.c b/src/misc/crypt/crypt.c index ccef4a0c7..81804ace5 100644 --- a/src/misc/crypt/crypt.c +++ b/src/misc/crypt/crypt.c @@ -220,6 +220,9 @@ const char *crypt_build_settings = #if defined(LTC_BLAKE2B) " BLAKE2B\n" #endif +#if defined(LTC_BLAKE3) + " BLAKE3\n" +#endif #if defined(LTC_CHC_HASH) " CHC_HASH\n" #endif diff --git a/src/misc/crypt/crypt_register_all_hashes.c b/src/misc/crypt/crypt_register_all_hashes.c index 91f1cadb1..4bce1e05f 100644 --- a/src/misc/crypt/crypt_register_all_hashes.c +++ b/src/misc/crypt/crypt_register_all_hashes.c @@ -60,12 +60,15 @@ int register_all_hashes(void) REGISTER_HASH(&blake2s_224_desc); REGISTER_HASH(&blake2s_256_desc); #endif -#ifdef LTC_BLAKE2S +#ifdef LTC_BLAKE2B REGISTER_HASH(&blake2b_160_desc); REGISTER_HASH(&blake2b_256_desc); REGISTER_HASH(&blake2b_384_desc); REGISTER_HASH(&blake2b_512_desc); #endif +#ifdef LTC_BLAKE3 + REGISTER_HASH(&blake3_desc); +#endif #ifdef LTC_KECCAK REGISTER_HASH(&keccak_224_desc); REGISTER_HASH(&keccak_256_desc); diff --git a/tests/test.c b/tests/test.c index 8eb7d7d0b..790a26bbd 100644 --- a/tests/test.c +++ b/tests/test.c @@ -275,6 +275,9 @@ static void s_unregister_all(void) unregister_hash(&blake2b_384_desc); unregister_hash(&blake2b_512_desc); #endif +#ifdef LTC_BLAKE3 + unregister_hash(&blake3_desc); +#endif #ifdef LTC_CHC_HASH unregister_hash(&chc_desc); #endif From cf2ea3fab0bc6f7e71aa37f75297477b659cbfdd Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Thu, 16 Apr 2026 13:17:02 +0200 Subject: [PATCH 2/6] Update makefiles --- libtomcrypt_VS2008.vcproj | 4 ++++ makefile.mingw | 4 ++-- makefile.msvc | 4 ++-- makefile.unix | 4 ++-- makefile_include.mk | 4 ++-- sources.cmake | 1 + 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/libtomcrypt_VS2008.vcproj b/libtomcrypt_VS2008.vcproj index 987f3a33e..b6b7ee079 100644 --- a/libtomcrypt_VS2008.vcproj +++ b/libtomcrypt_VS2008.vcproj @@ -855,6 +855,10 @@ RelativePath="src\hashes\blake2s.c" > + + diff --git a/makefile.mingw b/makefile.mingw index 1d3135eec..b338350cb 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -65,8 +65,8 @@ src/encauth/ocb3/ocb3_decrypt_verify_memory.o src/encauth/ocb3/ocb3_done.o \ src/encauth/ocb3/ocb3_encrypt.o src/encauth/ocb3/ocb3_encrypt_authenticate_memory.o \ src/encauth/ocb3/ocb3_encrypt_last.o src/encauth/ocb3/ocb3_init.o src/encauth/ocb3/ocb3_int_ntz.o \ src/encauth/ocb3/ocb3_int_xor_blocks.o src/encauth/ocb3/ocb3_test.o src/encauth/siv/siv.o \ -src/hashes/blake2b.o src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper/hash_file.o \ -src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \ +src/hashes/blake2b.o src/hashes/blake2s.o src/hashes/blake3.o src/hashes/chc/chc.o \ +src/hashes/helper/hash_file.o src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \ src/hashes/helper/hash_memory_multi.o src/hashes/md2.o src/hashes/md4.o src/hashes/md5.o \ src/hashes/rmd128.o src/hashes/rmd160.o src/hashes/rmd256.o src/hashes/rmd320.o src/hashes/sha1.o \ src/hashes/sha1_desc.o src/hashes/sha1_x86.o src/hashes/sha2/sha224.o src/hashes/sha2/sha224_desc.o \ diff --git a/makefile.msvc b/makefile.msvc index 5770c4682..d5006da1f 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -58,8 +58,8 @@ src/encauth/ocb3/ocb3_decrypt_verify_memory.obj src/encauth/ocb3/ocb3_done.obj \ src/encauth/ocb3/ocb3_encrypt.obj src/encauth/ocb3/ocb3_encrypt_authenticate_memory.obj \ src/encauth/ocb3/ocb3_encrypt_last.obj src/encauth/ocb3/ocb3_init.obj src/encauth/ocb3/ocb3_int_ntz.obj \ src/encauth/ocb3/ocb3_int_xor_blocks.obj src/encauth/ocb3/ocb3_test.obj src/encauth/siv/siv.obj \ -src/hashes/blake2b.obj src/hashes/blake2s.obj src/hashes/chc/chc.obj src/hashes/helper/hash_file.obj \ -src/hashes/helper/hash_filehandle.obj src/hashes/helper/hash_memory.obj \ +src/hashes/blake2b.obj src/hashes/blake2s.obj src/hashes/blake3.obj src/hashes/chc/chc.obj \ +src/hashes/helper/hash_file.obj src/hashes/helper/hash_filehandle.obj src/hashes/helper/hash_memory.obj \ src/hashes/helper/hash_memory_multi.obj src/hashes/md2.obj src/hashes/md4.obj src/hashes/md5.obj \ src/hashes/rmd128.obj src/hashes/rmd160.obj src/hashes/rmd256.obj src/hashes/rmd320.obj src/hashes/sha1.obj \ src/hashes/sha1_desc.obj src/hashes/sha1_x86.obj src/hashes/sha2/sha224.obj src/hashes/sha2/sha224_desc.obj \ diff --git a/makefile.unix b/makefile.unix index 5130bef3b..31a3501cd 100644 --- a/makefile.unix +++ b/makefile.unix @@ -79,8 +79,8 @@ src/encauth/ocb3/ocb3_decrypt_verify_memory.o src/encauth/ocb3/ocb3_done.o \ src/encauth/ocb3/ocb3_encrypt.o src/encauth/ocb3/ocb3_encrypt_authenticate_memory.o \ src/encauth/ocb3/ocb3_encrypt_last.o src/encauth/ocb3/ocb3_init.o src/encauth/ocb3/ocb3_int_ntz.o \ src/encauth/ocb3/ocb3_int_xor_blocks.o src/encauth/ocb3/ocb3_test.o src/encauth/siv/siv.o \ -src/hashes/blake2b.o src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper/hash_file.o \ -src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \ +src/hashes/blake2b.o src/hashes/blake2s.o src/hashes/blake3.o src/hashes/chc/chc.o \ +src/hashes/helper/hash_file.o src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \ src/hashes/helper/hash_memory_multi.o src/hashes/md2.o src/hashes/md4.o src/hashes/md5.o \ src/hashes/rmd128.o src/hashes/rmd160.o src/hashes/rmd256.o src/hashes/rmd320.o src/hashes/sha1.o \ src/hashes/sha1_desc.o src/hashes/sha1_x86.o src/hashes/sha2/sha224.o src/hashes/sha2/sha224_desc.o \ diff --git a/makefile_include.mk b/makefile_include.mk index b849f810d..db3f31238 100644 --- a/makefile_include.mk +++ b/makefile_include.mk @@ -250,8 +250,8 @@ src/encauth/ocb3/ocb3_decrypt_verify_memory.o src/encauth/ocb3/ocb3_done.o \ src/encauth/ocb3/ocb3_encrypt.o src/encauth/ocb3/ocb3_encrypt_authenticate_memory.o \ src/encauth/ocb3/ocb3_encrypt_last.o src/encauth/ocb3/ocb3_init.o src/encauth/ocb3/ocb3_int_ntz.o \ src/encauth/ocb3/ocb3_int_xor_blocks.o src/encauth/ocb3/ocb3_test.o src/encauth/siv/siv.o \ -src/hashes/blake2b.o src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper/hash_file.o \ -src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \ +src/hashes/blake2b.o src/hashes/blake2s.o src/hashes/blake3.o src/hashes/chc/chc.o \ +src/hashes/helper/hash_file.o src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \ src/hashes/helper/hash_memory_multi.o src/hashes/md2.o src/hashes/md4.o src/hashes/md5.o \ src/hashes/rmd128.o src/hashes/rmd160.o src/hashes/rmd256.o src/hashes/rmd320.o src/hashes/sha1.o \ src/hashes/sha1_desc.o src/hashes/sha1_x86.o src/hashes/sha2/sha224.o src/hashes/sha2/sha224_desc.o \ diff --git a/sources.cmake b/sources.cmake index 38c5d9b25..71b3eba7c 100644 --- a/sources.cmake +++ b/sources.cmake @@ -88,6 +88,7 @@ src/encauth/ocb3/ocb3_test.c src/encauth/siv/siv.c src/hashes/blake2b.c src/hashes/blake2s.c +src/hashes/blake3.c src/hashes/chc/chc.c src/hashes/helper/hash_file.c src/hashes/helper/hash_filehandle.c From 07270c1d0c24849d6df2dd6339a45ef62cceb49c Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Thu, 16 Apr 2026 18:22:40 +0200 Subject: [PATCH 3/6] BLAKE3 update of hash_tv.txt --- notes/hash_tv.txt | 131 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/notes/hash_tv.txt b/notes/hash_tv.txt index c9f8e72a7..9225f3b7a 100644 --- a/notes/hash_tv.txt +++ b/notes/hash_tv.txt @@ -4046,6 +4046,137 @@ Hash: blake2b-512 255: 5B21C5FD8868367612474FA2E70E9CFA2201FFEEE8FAFAB5797AD58FEFA17C9B5B107DA4A3DB6320BAAF2C8617D5A51DF914AE88DA3867C2D41F0CC14FA67928 256: 1ECC896F34D3F9CAC484C73F75F6A5FB58EE6784BE41B35F46067B9C65C63A6794D3D744112C653F73DD7DEB6666204C5A9BFA5B46081FC10FDBE7884FA5CBF8 +Hash: blake3 + 0: AF1349B9F5F9A1A6A0404DEA36DCC9499BCB25C9ADC112B7CC9A93CAE41F3262 + 1: 2D3ADEDFF11B61F14C886E35AFA036736DCD87A74D27B5C1510225D0F592E213 + 2: 7B7015BB92CF0B318037702A6CDD81DEE41224F734684C2C122CD6359CB1EE63 + 3: E1BE4D7A8AB5560AA4199EEA339849BA8E293D55CA0A81006726D184519E647F + 4: F30F5AB28FE047904037F77B6DA4FEA1E27241C5D132638D8BEDCE9D40494F32 + 5: B40B44DFD97E7A84A996A91AF8B85188C66C126940BA7AAD2E7AE6B385402AA2 + 6: 06C4E8FFB6872FAD96F9AACA5EEE1553EB62AED0AD7198CEF42E87F6A616C844 + 7: 3F8770F387FAAD08FAA9D8414E9F449AC68E6FF0417F673F602A646A891419FE + 8: 2351207D04FC16ADE43CCAB08600939C7C1FA70A5C0AACA76063D04C3228EAEB + 9: A0FC27E5D7318B723207637BDEEBA4F7DCB22F7F9EC3E8B6F3588DDCD4FDF861 + 10: 87FCF07CAC5BE3C91735B34E535C67286E4E7A63BF152D95F2CF4CD1A244758B + 11: 02662E12EA8B243F0A8E970EFE19D8955FCC71EA7DC10F7FDA89492D07CD9730 + 12: 46771FD4C72C26DE414671D8C8634B327FD12BA240E3739E011B4E64BFBB898C + 13: E1C0BBB02CB1622397CED750A9F712A2D5EF5B1E17E7CC01A3DABCF448613A51 + 14: CBFA77A4531D0D07800518C49CAD65E7130CB2C225AFC718BECFEA56904870D1 + 15: 163475FC98871015D19097D29536653BDEAC6A9C3A18AD4B3A629CFAA1BBF32E + 16: A6A492965517A830CB75FDB713465AA465F2F098233896FEA44C1D98268BF9E3 + 17: 8462AA7BE93B09FDA7B93CF9F9CDDB703F6DD2CC0C8EDD5F9EEE092EDF8ABF0C + 18: 66A671E4FB354B7FA37D12B506D557F9170C8247494DF4591B6A38C4C1ED8CD2 + 19: 9F9CC8084631848151B09AA51B05A96A5CF674DB8BE5D1C5E8054BAA87A3B3F8 + 20: A418FAEC67BAAEB5177880C3673A125F1C1123AA18370B007C3E707EF9A7946C + 21: 7FE1802DDAC5BBAFE5BA26848B95252590EECC4937CCFB9C55F3B6EAD2DC56B7 + 22: 2E4D3DCDF0702C936D4E90BA664DED539B53190006CA17A010744B4AD97CA4F5 + 23: 3F3123529EB4B83D3D38A4E79C7A1B6F4176F7A9B435254D402162EFBE74DB47 + 24: 0B3AB94011D18786D51ED60C6B3FA6CE1B10B14D66D594836B2CC38451F7A8D6 + 25: EDF54F99CAD804C52DFC45C54524982D9F0F16A3E193143EF7AF1A3105CB78DE + 26: 2B001B01373DB4C2E8F790CB1CA9372FB53A2818C391224CE9A24B3428025EB6 + 27: 630AF0542832B93F6F9C9A4299C04E06CC89F0609796CBAD0714CEC5B97A21B7 + 28: 4D7694418F33D099AD643D743D98FC1E5BF71EA979B7DCAE3E19BC2AE8732436 + 29: 0A8B04B4686B2D211E13F630B22CB2846D38610B9668619B8C94948DE6A86075 + 30: 4A370926EFD1807A3D7699EFDE168C9A4D128AC5367B95755DB2BE230A085D00 + 31: BDA80C7FE2DB38BE6387B35C870BD7728D67B7B6CC5EB9B0E5C7DCB21EA754C2 + 32: E528E95798037DF410543D9F31E396ECDD458D71B157D6014398BAE32FB56C65 + 33: 4F4E6C1DFFD3A6C9959876D15AA96B5FB0DA8632B995F6CA2E30503F2829FA29 + 34: 0DBEFE45C10F3E35DCA05C85DE406E1DAD035B28A1C70E8476D2FCFCA744CE96 + 35: B1153AB473AFB31831AC2CD78167ED9B49C4EA1AE05A16D4CEFC111CA1D40885 + 36: 02B34DC75E6E7DFB3B020188C7A5C277C7171417B75F91540F34E112B7F3552C + 37: B86799BC285A4A9FF30B36425FA164DEC196DC403A0C62C27EBDDDB6DC4FA40A + 38: D78545492EFD467E227662AA5BFDFBE4327D1C9DC18116CD493F157BE42BDE1C + 39: 6742AD3231B1D91EC920D04F911F8B2CD10AEDADBCB13EF1FD24B7DB4761027F + 40: 9563A50F070B26EEAA1EE0A6AC95B8BA9168C32B1AF71AF2FE55A8B4E268CE5E + 41: F0DBD489DFB0FB6A9206F1F7B9D6FBB6C81350DA461E88812CD4F15C93853ED5 + 42: B4CDEEB0E5B83AD41753011E1B56D497B3CA9785AA0A606610E91B97172A7928 + 43: 051978D4083545DBA07983654DB5C3C82A7A982A53B6005304A1BACBF0684ADB + 44: 062C1BCE7948A70DB0D55355F0E74F13E54A022E8FFFCEAB06FE71041D0AAD47 + 45: 304ACD11CA45BEFA2B9CD55D2AB9C7CF0A75C4301BB8813728F180E31D25696F + 46: F420058BEF32C43E2090BD112A2379FEDFAB0B2BD12737374391A3FC44BFE91E + 47: 39DA10BF36C8498FA071067532BE53492CAE29F6CCAFDCB7E77552E0406A1A60 + 48: 5E9902524B30F4F4CFD5D2180FD357BBF881221A603C84C119580E8BC422911E + 49: B78309B3D5FC5765EA4F02A6DC1DFB63370190470011F1025362DC691E178895 + 50: 475438FC7B1BFBEEBFFC69882E18C7D0C6B505312484EA2B9ADD451ACEF2D743 + 51: C98AAD8B112985E7D532D6F48F93FB0B26BFE90DF5A161FB3CE4FED674991911 + 52: D9B171EEE2809CF0A020E7367FC83413EC7C2A2E46A400D81297D98EBCA3464D + 53: 0F4245901611D426CA9BA9700E64F267DBCD36221CA20C3B9643F5DFE38C8EDE + 54: 6FE71231259609F9D0A6F799F983DF408A6104A1510E69D0050C6E4DBF63980C + 55: D04EC5F6F5E7DAF5CED7A1671FBE912580A56576C8BF6A2ED4B80E35548F9C13 + 56: 60F238116F2936698A88CDA03D8DF79D7431249373B048EE7A063849FE6E9742 + 57: AE097943D385BC9B2CD9369D91ED13A97C59B9B654B04514CD87C74BF4B9A80C + 58: CA204CEB059EA73A688A2C7D485418C3BB3BE97756E5FA1583D3A0FB582AB966 + 59: 4F174ACAFF29FF88AAA4DDE9404634FDCAE5A895F90DD5D610F91595C042D751 + 60: FE59BA0025B061E837DB84910371240D9B417DB56C14DDFF68D4AFE36DC39658 + 61: 86A2CF17CE886A3BE084862AE3C2AACF64F50E88B7334E675AFB34365CB9A5BF + 62: 1F5EBF4B2ABEA4E78C2AB709D5AB298E13F494F9237F6DD19C8B90B3B7C83A13 + 63: E9BC37A594DAAD83BE9470DF7F7B3798297C3D834CE80BA85D6E207627B7DB7B + 64: 4EED7141EA4A5CD4B788606BD23F46E212AF9CACEBACDC7D1F4C6DC7F2511B98 + 65: DE1E5FA0BE70DF6D2BE8FFFD0E99CEAA8EB6E8C93A63F2D8D1C30ECB6B263DEE + 66: 191625E0BE4C2B741C2FEDABF54031AAA6E1991C95ACF95DECA48B925110F7E4 + 67: 810943751089482736CA4A0E7E04D4CE0244008F7ED6332D82AAB40AA1976EA2 + 68: 8720B909015D7A29AF3DD7A06F78729449F07BBCB56DF6954C032C0920491406 + 69: 0F0DB3C00DA61EAE613F02881890C3B896C5EEBFD94CD0DC385CE4002D4349E0 + 70: B0AE0E326C4BE7A0E1306C6C24DDAB88D01611863BCD6780B39D932227AC8510 + 71: 1E8633CB3FBA5DEDC5D22549E27CFAB03C8AC37884305EF25E9937A6F5F52E93 + 72: 028EB97D80291FC1F4AB846657FB2277CAE9D7EDA639C09BD220A9C869F0E9E6 + 73: EF0DE8AF9F7EB55976C1E97C2B5B2B61BD449BAD7B4D2F6C0C1D395DB1B0F247 + 74: C5BBC18015106771C91226EF36B7B1BC3849F92BB3D007F5AF78862677A27FD5 + 75: C730688E8971293A5F824E3B33AE03CC93A8790599C195F613FDF2124AC35520 + 76: CFCC0C08E078C3A7932293976A901A95C8CB0F2F75112D1C0BC45AC7ACBFAD9C + 77: 5EF9C11ABD40A9FEB17F524FC574F1834C009841FEFCD75086970CC7B812BD34 + 78: FC6AB94E91AC711546E915926ACB19C1B2E12A60FABFA99B4AA375A28301F3E1 + 79: 28B11E5D82FD3FB24CADD8110715134DDA8485E0314C163558A30A81C665D67B + 80: 4A6847EF66BCE6C14CA05EC8F8AD7383BF2931F4BCFD0373C18E059E93F9DEF6 + 81: B17155C79EE1E856F9264C526C7E2BC7EE4CB29AC0F4EEEA5F5351D7EA571C0C + 82: B96458DAF30EE72C5140B45774A981A13E847AF40DB3217EE2998773F3587EDC + 83: 0B7AD6C45101C2146728C4419691CDC8AFCADD7B2BD76F38818AB136BADE4224 + 84: A377584849A6890B585DDA9E9DC594DFCC91FB60FD4D00808D34AE379DCDB456 + 85: 3D173931FD3D576785D9FD8FA7179AB4C0768E2C2D264E193B1EC9EB9B01EE0E + 86: 34B9CC80478E5665EF5BF79B7DAC4B85F74E8768CADEC19AEAE6323DE332FE2A + 87: 672D2D2E6E995CFF226475999449BE91A43DF70F7CDEFF4CD39B6CAE60ACFD67 + 88: 87D03D704A84FFC46F5BB2A8000BD15743FAA303D2C59E2CEC61F3F7CC9EC2E5 + 89: D90E8853272707ABF2A7C7CF54233085D8D05140E433F94F27BDA873EF265F31 + 90: 2A9770A82D76F371336FD4FBE9999216F2B3C28C90FA25B1D42323691BC7F3EC + 91: 27D3BF094C5083D31AE11F855239116D6220AE1C113FA74AEE4560C4888598F6 + 92: 6C883E2335A2F69DF61B92046069BF5D8FE0EB5DD255F2BAA5FC230F7EC37968 + 93: B9A19A0E32E5D04C7110F0771C652D0406ED152C3474AAAC198ABD3EC7C8BCA2 + 94: 00F92A5B63E1FB1B3D3ED08CA14389C8BCACEE494B1F80FA839A7CD64339E7B0 + 95: 45376CE6418ED3454D301CC373671D35BFF7447860D86C545D380C8ACEB8B65B + 96: FD3748482969397A57DC96FA5646AF44BB4928DCBEBB795BE6D61975C3766BD6 + 97: 8A06220CAED39C22D8889B73351488D6550C43D4B4A777BFFA9FAB4F2074A4AF + 98: C0828951F49A694C8D807B2997BF0BF2D0123BE7D10B3DF23FA3D642DD67AEE8 + 99: A2C85460E965626580E9CFA7A8AEF6047720EE48EFDD0EF27613ED358425E57A +100: 8E2EB1BBA3040B8F611A1240A0E111C74B45CFC9CAED10B95F6372DB1C40B8B5 +101: 8F5BA69BF1882498FA92515D3105FC580EF070D2A4213580F0279D70B7406D38 +102: 9DB10F45A5CA40F4502316DAB6ACC63A4C5F8A1B95BF76B05C3E7896368AE24F +103: 7BF6852F77BC98DC83DAFCC4165933C9D600669406415653501D2C32E4CBE395 +104: 49F7F1D30B977E3F9D07C54B2A0DAD64513045B5942B634374B05365BBF4AF1D +105: 04FA0B7C1592B3F19E1D4981871E5E69DA3CAECFB07F11929ECC0CFAC34146E5 +106: 4E57D05348408846A3EA0D5C3D189CAD70FDD7DCCAC390CB52CAB05508E22E90 +107: E539064D0DE3B8698A336FBDEFA2B6E534AF90B37D7C8D8CB7054F2EB6403290 +108: 5F13A0F0307C6000C5AE6C5FEF866E4952517DD3BB824CB1D41E4326898E987E +109: E26DEA917FE9AB2CB7AD7FE19092160A630976EF0BBD809B5FCBE63609DF5978 +110: 5A2464499E08A48FCAE32B408B8BB608254E19A5758C66D9F77BA63CCAF81005 +111: 929DCDAF9B6A6E500A34978B5C9206D0258BC190F38C9E8E42FB19A4820B2171 +112: C881A3C5BA84905A418F3DA19726541B5BACD9E3438A741FFD980E00865FE13C +113: A2B62D6E7C7314E92E01DE6C10643B7B0BFC2C780670D243E676763D7C41E390 +114: 6D543DD890F0694C149B0E974730F05BADCAE792D50865744FAAB9005FF36DBC +115: 028C05BFF2A54FD6F85427EDB0CFFD878105602F7F72075E7DD60C3A252C1691 +116: 957DB4F3CED7164C7F23081A8B332C2C3738D292732D2D5809CD8DB522E2C4C2 +117: 2CDDF24AA6075E12E81AD2E5FE81F6A1DAB64660B5821B441E4F6A35C45DB8F5 +118: 4F3EC99446A61A12091364F8F542CB4940120A44B4448E13E696C5FE7583439D +119: 82878AA8005C85F2B3E847DA4B825891409A00D2950AAFE87D39BF07F8FA1077 +120: 1C5F22834AD113CFBCA3CFDB2884327061DBC873924AB2A35C8EE470594F074B +121: B94206155D4D699CC65E1D81D67F26CB50DB0170127FBFB6D300E2B521CC1C6A +122: A1DC94BFB2389377402CC7DE5AEEC1CE0B306265B57C0BD145255CE1DBAFB758 +123: 790451D31FF33EB38F077906A26D5A6C096814E8BDA984291E57315D1BBDA82C +124: AD8129C5BDF91F2B8932311CA036558EEBA072C70255D8917B13527E0C6BB6CF +125: B3FDB34BF7F8B89DC3031ED06310EFB3D92CE11749F7B4601684D7AC5B857CB6 +126: 67CB8BF7A00ADDC70A4947D055558A500802F9A2CF685CAA1A38A577CD308325 +127: D81293FDA863F008C09E92FC382A81F5A0B4A1251CBA1634016A0F86A6BD640D +128: F17E570564B26578C33BB7F44643F539624B05DF1A76C81F30ACD548C44B45EF + Hash: keccak224 0: F71837502BA8E10837BDD8D365ADB85591895602FC552B48B7390ABD 1: B7E52D015AFB9BB56C19955720964F1A68B1ABA96A7A9454472927BE From de2426e5f0a06a783f29f148c33ac262337094ae Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Thu, 16 Apr 2026 18:26:07 +0200 Subject: [PATCH 4/6] BLAKE3 update of hmac_tv.txt --- notes/hmac_tv.txt | 131 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/notes/hmac_tv.txt b/notes/hmac_tv.txt index 17270fe3f..29a2c2120 100644 --- a/notes/hmac_tv.txt +++ b/notes/hmac_tv.txt @@ -4046,6 +4046,137 @@ HMAC-blake2b-512 255: 2B72B3BAAA241F977917BDF8BB019DEBE7444559A1CD329274377154B00E0BEB78CCD9B13F8733388EA7B23245BF3233414754CF0AFB1932E0879DF415133A4A 256: C21D6454682743DAA662B443FF48FD57A493950E7D2F8CAD749E5FB398DAC7AB7D0D9EFC3E6ADC3B66DC45D59A95551AA0A928C676D0FF2E09FAB8C77954FD1E +HMAC-blake3 + 0: DED7A86325A5CA8BC29C391AF63969C5C60DF823EFE5C2256857AE98C8851FE7 + 1: 12AE5BF7DC7D719BAD62BB21A66AA88301400DC6F744D015BD05ADF9C5D704B0 + 2: A1D6A2C21E2887C526B95F90E3B48B85FA600E780CEED6A677EEBBFAD52B179B + 3: EA79523FF0F9257877DBA02FD48E8799068E38866382BC18A532890CA12D1E52 + 4: 8145F50F8E0E792EDADB5638586ED4D0306766C9F96AFE8FE1CD76441F6F9416 + 5: 60043135E4A77EF2886982FB344C558A394127C7233A524570A487AC729A5954 + 6: 351892CB1A5D20D96E8BDAF719D332F4D17EE0DB9E722C799BD602D69317F7C6 + 7: 352FFD3952CEB3B73C5941D15691C2CFE10B1DD1F5C395CA13844FDA0ED650FA + 8: 65E559BD462B34B12ECC8A0D680BD3B18EEF640A193E4AC9097FE9FB2BD19EF7 + 9: 46F421D1D9B5CF8F4F556EB73533C4711C8BD81366871CEF4660DD9278CF192D + 10: E5DA318FBE3ABD2AAAC554A6CC855E3E3DB17947DCD601EF9800D45F9024193E + 11: 0AB6855EFFF8541EB782A63120457A294B94F8D025D3BACE9543AC510005B25B + 12: 29B34D925BD37C801D044612D0D92F179E64ED152D1ECEF8B99C1530647172C1 + 13: 43067F492168FDC581FF2DAED459B44113F1BCD2C58811ACAA0C0A6B31452BE9 + 14: 0077515BD13E7DB6FCDC8D638AED14CD230F102D4923A3D3246DA68C64FFCD33 + 15: 3A3DDFBE7A3BFA81C2FC2BFCE0BEA69BA15885CAD6C7D99381E29CF8251817E7 + 16: 41E224D8DAAD25E6D3E4D1ED172F9A25764FC0892A95E10E58863DF18C231FA3 + 17: 9403EB023D9C23B82A985EA11B411C058C42CF78A8D19D46801A140F5913D03F + 18: B89D0C5F2BD264C6C047226FDDEC7FA3BDC6423056B14D2BEEA58E7850423D5C + 19: 2D8DC6990823354F18496D91BC90A256A61D26B212C9D58EA5C08A12B3C292DF + 20: 93B4E4884B13089435FDCEEDDD9621C9B120D200D6FCCE84C566CCEB8A86C63F + 21: 2D598DA80A8C888B85E414AA7532ABB524C2E69DEE619BCEA744C48C6B9A5AFF + 22: B5E763E63DDCD678020A4C115E798EAB1824C7D929295F2C80D3706DC079F2AD + 23: 210E1C516361AC95570B65F958AFCC1316297B8FDAF5ADDB55BCBDB1BA350205 + 24: 4822C34CE97EEF5D29E6AAACFA7BB15068AA6EBA1589C33065DF54D6667B6999 + 25: EDE67392D184BFA183F861D3B56119BA6EB7638A204473AEE046BB912A59DB1D + 26: 8084BEEC7D865C08F5CA9A97F5BADF896159D84CFB5E9FD79D75638023826103 + 27: C94CC8E2DBEE5331FEC95C7BE5A3A3B268FB58A25E835B8DE06167A5262E14A5 + 28: 9E9B87FCA91D8E2DEAB5FEF979AD6CB30E522BCA691ECB64C681440A14D49C8B + 29: 9C6110653C42B1F293AAE4C7D2A05B6E92CF5B5B4CD6F42EE98CA0AEB3A7E134 + 30: 3A81FB92319D2C3A97BBC73B2D45995496AC48F5752D6E600B1530E61DC41950 + 31: 01EAD34F362DA0DCAEE738690DFC0CC1E2E26FE6416AAA7E93FCEE7C96C04BFC + 32: A803ED71879D12D66BC9B3EE65E806651821517C49768002A0FBB1AEF4F63201 + 33: BB35AC5F01495108BE7E9E122C8DE19D0D5BC102B2FCF246AAF322FB3EB7A20E + 34: 4F2290EA4945F77A8F41E4C776F0716551C8333F2C3E07691C409A19390C54EA + 35: 5F3A35C28D4C7506D9CC24D6DA5BDC761218D3570AE6DA9E2AE9149EB3F11776 + 36: 87FCFF25B8284176C37BD95C2C4C1B61B5EA05C079421443AB7B6FC638914C7D + 37: 7D8C9269E635832AA92536D03F4EF6CCA1ACE30506515C47A53D8602AFA59A49 + 38: E58D99A9AB41802EECA223DEA94C1E4F93EC82D5E1CEF236E02FC19FDCCA1B12 + 39: 2A8E82DF55C7BDD4349506500250E40526982FDF8FBA5829CDDB6FCAE0E47F47 + 40: 5038B1E54401CAC2CBB9C2B7874E334675D4EC9C38A0196C4091CBF87221FFC9 + 41: B8256B74B9793FF4BE2B176985471A79E38F887AFB9FB45B4EC26F056EBE7B79 + 42: 18753FEA5879E456F1D29D053048E2988806F817E651450E263E4B5254938784 + 43: CBE7984EC0BBB8E68C714A83D3310B68675ABED5FA5108623E179CF1A2C1CBAE + 44: ABD2B8D87D11DA6A68B85F9E9FC5A84DB907D7B32B2BC13E3A549A83ABF53669 + 45: 5F3B48CBCD573FC33E87F67FF0D62D556DCA9F0B5D6B79293688BE766FA35B24 + 46: 205BBF9A799F4F97C0EDAAA5D5CE1DA42BAE5710A9B179B9D2D6AA7CDA09E546 + 47: 464A4CBB4F0DD2AEA7B9C290058A3FF8A7CC473B556A8526A2233B2ECC967180 + 48: F6C1AC7A589D49BACE7A2631D7FC9A815110CD7DCD4CC5EDC30CCFF4C5AE231E + 49: 8B17F095EC40CE055F508B28944A226487A2F2514700D040EFD9786681CCC5A8 + 50: C8AE6EB0D3B5480475CEFE5F27559E55A8CAF1DC84A0D19BCF96E5634C0520F9 + 51: 3896AA7B007182D0E747B371F36934E1B1E3520DB2153609D84112C05B02DF5B + 52: 1A0603F02690BB94368767BF1C5466DA04DC624C4B86576F68EB262015C77C52 + 53: 207BC2BB06651147C20FFC74285620D66AE274F969593FC9E5B04E00B1DA3F0C + 54: 8BC276BBDC88CB29152658079F5B8AB127494952B109983063A0CAA6FECF7FB8 + 55: 89B878FF7FDC22498E2C67C12B83216C0EE1CC981DBA52685F3469BD2BADD418 + 56: 0AA919F8DDB428CD042976922436755963956E560A9A95084D4AE0BA6DCD3AB9 + 57: A8809A0BCD68889E660262032594B2B0C1466023208EE585EAA3824361F52F3B + 58: EA994D64386E248FD101A71C44B208B6513EA339F132591085C503F7D1C6E992 + 59: 2F005083C2D224867A0D399AAB5842C97CB0F3A92A947D0102B7A50EB3EDB95E + 60: A326BFF4A13B37237C8E1EF2D7408BDB0C320654D81640A778A042249AD37F97 + 61: D66CA56ED0B3E49B64517FDF69FAE7BDF84460787792C365E4B5E646EB77BC20 + 62: 98B7D9CC0FFE8948D6C81CC1D35191F0C5543A265855F4D5380123A7868B6B5D + 63: ED9986E7B5ADBD2E942D2BEB6C72CE4328C87C35E69686BF33741F5022E9B337 + 64: FFB027F54A3271217F0BD0606138B8DB65710742088F583A9340C3940219BC32 + 65: F8AE6ACAFC700669A24EA64EC3DB8FA465E28DF91B933D5BEF0250A45A91B6B6 + 66: 0839A1BE1F4858E929C8A47281F6BC5D4F9BE467DABA74452A275E09157A52BE + 67: F60B5E6A29435A2BE9199149BBF4C9B2622A33DD7A9D8B478AAA372387D7B269 + 68: CACF3CCD926C87843E027F534A1B3CEDA46B3CA4B8BE5A8D88AF98F5A9CBF2BC + 69: 660343AFEF303EC0CD2B0A1AD6E2457CC4E4264BA58E382C10BD5F85C911FE46 + 70: E85DF68A067B98E3AACFEE097D2508BDFB9149B7E78E874AF665F846A4F64AA7 + 71: F4E8E257DB4D88B7F9885A5BAA227E89E7287254AA17EA8E076D6E5626B36EB1 + 72: F58638811703C9EEB401B4D4C2D8AF445E9D860B3A3468E9485A1B5D04BC17C6 + 73: A1E20FF0A1B916FD722303533635EBB6EF1A7B4BE3B010381E8AC06E98BFBA2E + 74: 14FA94D90F31EC5AB539CBC45BD7F8BC5D587BB69B8CD80B08418BF5CE17E4AE + 75: B6EFA204D16AD53C4547353640E9F6224A1E1F7555AEE65B9E83C901FBF0167B + 76: 3AF9CB9CB91DC73CBBD6659E9E972C5E0A58BB1796140287A6A4C41A6E107624 + 77: A4D4D4AB58D5DE34805980322BD75EE57BA9867E38B138FE80D0B6BA0B968868 + 78: 6C0DBE7844EF5E13720FD1DF1BF95F18FFA4F11E07E356334CFDF5041BA55F12 + 79: 28D85DE5BD8F1F691880F84538A8C63433E7CE59D5C050FC614273C7F4C86282 + 80: C4756DEDC866BCB689B991AF5BDF6D648D45C91615C3265A22C391CB1AF58ED1 + 81: BC6D69B89C938CF480DF2524A21346A330B24450FE0D3A59CFE0DB5402EEF903 + 82: 2FCA04F030A54A4A3B449FD0F31009A7013F71F4616D81410CC68ED18601321F + 83: DBD4D61D0923E1B1554C315E0452D6FC09520D5BAF79C6E562709E8E979B95BD + 84: 38D9DA39140099F940F6BB1E456424690296330DC306A1F88A5A937F78C7FC0F + 85: 42FB7444F0D74AD83FC40481F7ADBB4F7072334AF8E7B5CF1DA53B84F020C847 + 86: 36CB8249A1D4F589A96A419579445D2A94DCB3567D4C1590BC0816F57D4D643E + 87: E797CE1AA07CB411E6D6ABF2571C98565A89AA4DAA7A74CD57A0EF1801526B5D + 88: 2C182365F5AD9241CB18FAC1F14D833CC9A55924065C82E3EB7C26072116CEDC + 89: 967E777E24AEE0673821D51398C0F3D098E5AEE4F4C290F04AE6A53A9D93D371 + 90: AC89F0B40F52CD52587A49715810E5E73E8BEFCAFA069357A30D29545C4DB285 + 91: 5530557A5F73C024A403CAC5405BED6D7A0AC93C6EBF2AEF79C4DAF9B9B938E2 + 92: 8403E31A1244CC37DA6EC44A7959FACD4F12E1933A40DE18A4C4862E97EE8D31 + 93: E849298C206F76AC0BE8ACAA4030EB64EC509DE08DAB7BFADFC8D941E1FA5E0E + 94: D5B45A7F0E5874BFE2BBFDABF871663E4E6D8A6839BEF771DA848634E264B64C + 95: E0B37E2B91CF57E21213A3FC5C297F8A6868E80A7447165A55EE8612B86EC31A + 96: 2E864718D55766016739D612A50CDC188963D8B133680443BA4803806B513428 + 97: 99D7F26575E8CC6032AB17C3A42BE95E3BB78FEC080647721D1D03F8736F2A2C + 98: 98408351706E3612DF789DF17EA9F84F11E96E52849150D38630679C9BFF6245 + 99: 0D61444991088BD3FB631425DE9E0FDE8E0F948B007D57C2AC5FC8362601FBF2 +100: 5C34AE2761345B7F3E19EE9AC7CEDD6BEC66F81A795FB87B31B3DDE161BE1517 +101: 817DA201A7F9D50935242865DC7AD0BD529C58F3C02274F59860861B4187970D +102: 9E75CF39A6FE660AB151B3B80FE422CDDABDC2D79635CC37F505B0954BA81F97 +103: CC37709592DA35A973C21CC7A46B475508FA83784B74191CED57B2DA53077673 +104: 2A9B2B0C8FBA6B99BA2AE9D95B2362F22D1F92E868A8430607D7D113259953F6 +105: 6C8409E177663A626CEDA698C1D30252818F809AF444492A9B7868E7558F6EB1 +106: CFEFC7ABA6E2AFEC628CA547BAA2899EB093DC88763CB76B19074F36B377109E +107: 126EA51990C0EAB32314B6C4792AF2FC39036CBAF44CBE0C72B722F8A3D28B11 +108: 9F094FF97D9442DC2232E8C6B2163FACB7822FAF068863835141DC8477054C1B +109: B2469335C5E0DAFD06D6378F8FF33B63CAA660332F81F9152087059867C041C6 +110: 53A3A55A48EB5FBC8992EA8BF2075A661D37DBC01A5C36A2E31A96D42DE409FC +111: B26410F728E4674291FF92EFACD2249514B5B003D516D625DBF92EFE5FE3C36C +112: 83DAAB0BBE3ADEA5060998D0506144FFD3EB18EC019FB5250416C5A73041E793 +113: 264BFF6B70375F0C0F3F55E7FD83C32D619700D9883FB16A48C930E47F890E53 +114: BF3792940E59FBBA64673507F5A002CA00E3677A7A8036578BC98FFF2098572C +115: 8D07724295293A5DE51417FCC012DA81412906B4CBA1A131C40A73C155442332 +116: C01AD4C087F815A467D7D5778E436FC6ADD1A51125C5C10C1DC37FD763449A21 +117: C4B21D239172C0C9010AE728B5AB21A169A3A939859575605602AF764BACD700 +118: 98C3C91C8C3B805437B5F5B4CCAC02B2BFDACB5375CAFB68678390E534E45487 +119: F6CFA41BA662F9D111E8F50B6684120B1E7F06CA793235A5DDBB6C44A33D81F5 +120: 0B7F4897BFD8C77D93605EE2892D03D7C08EC9973D32B9B386F5FD74DEC1B420 +121: 5C8B70C53CAB849F8D8E72442816A29C46CC1662357A010B54D9C9391A5E7782 +122: 2E8360ECEEC700C58DA7F224078B4C84A0727AA6CDBD878805012816C4A02B77 +123: 5CBF14C05CD274F81602474E86C37CA3195998F4855CF64F2DF6C59656A13008 +124: 5A43F80424C82669FBC1F993C7DFF3E1DF17A65A1814D9BAB86F0545719AFF4F +125: 7F908DD70B5709BF5BE382811B7F044FD76B750F48A30AF87E77953B444D6E1F +126: 60E02FB02114D545F58B3E07A720E88D8872418EFE1872B275B8A3935966328F +127: 4B33496640014C275C8A533CE90B5C417B4AD083EB6AA698376A33F996AC9B88 +128: 344C7F49EFA5E705454578DF53E3C5C140B83B3A71B8F371FA8515FD943FEF9E + HMAC-keccak224 0: 7A6078AD4088D4CEA8C8E76296ACF1119FD9FC36B1845B3831C3E870 1: 496659732FFA50DD3157DB556B8552FA6FDC19A9582764BFF56902B9 From 7afdac5dceb9825d0ae76d6ee1b764e35cabed82 Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Thu, 16 Apr 2026 20:37:10 +0200 Subject: [PATCH 5/6] improved diagnostics in .ci/coverage_more.sh --- .ci/coverage_more.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci/coverage_more.sh b/.ci/coverage_more.sh index 40fbe4cea..9331c7a98 100755 --- a/.ci/coverage_more.sh +++ b/.ci/coverage_more.sh @@ -24,7 +24,8 @@ done > hashsum_tv.txt pdiv "Compare hashsum_tv.txt" difftroubles=$(diff -i -w -B hashsum_tv.txt notes/hashsum_tv.txt | grep '^<') || true if [ -n "$difftroubles" ]; then - echo "FAILURE: hashsum_tv.tx" + echo "FAILURE: hashsum_tv.txt" >&2 + echo "$difftroubles" >&2 diff -i -w -B hashsum_tv.txt notes/hashsum_tv.txt echo "hashsum failed" exit 1 From 476f62198320a82322e792c512eb9c130ce65e67 Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Thu, 16 Apr 2026 20:40:53 +0200 Subject: [PATCH 6/6] BLAKE3 update of hashsum_tv.txt --- notes/hashsum_tv.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/notes/hashsum_tv.txt b/notes/hashsum_tv.txt index 2bf53d300..8118f4df4 100644 --- a/notes/hashsum_tv.txt +++ b/notes/hashsum_tv.txt @@ -6,6 +6,7 @@ blake2s-128: 7e1f9b6de11a3c597308f9d8aacd7321 *tests/test.key blake2s-160: 3d1c9ae1a0afe8a6ef8b61d5380de7b061cd353c *tests/test.key blake2s-224: 95dacd83d0421b2d69a52d92ee54143bb97c91a61450d917a88d4388 *tests/test.key blake2s-256: 92ac6dc88b9ce4a75b2a54783435a37919303f713396db0e9ccd976d8c55f1cf *tests/test.key +blake3: 634ba3ee0627293fe3ef89fe7200434fdbf2c40b08266e0fd09708bfd486af0c *tests/test.key chc_hash: d50da1ea9b53c0b891c8bcb0a4c6e5e0 *tests/test.key keccak224: c056b64ec1d8066aeb148d38aded0ff96cdb1e17eecaaca407b3bf66 *tests/test.key keccak256: af91c0982f5f79d51df0f6ccb28c7f0075ef330e09371cbefa660119a74f28c3 *tests/test.key