From c8d7c3153d989704db06a5ddbc8df17aea82b103 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Wed, 23 Mar 2016 19:08:16 +1000 Subject: [PATCH] Keyed hashing for BLAKE2 according to RFC7693 --- doc/crypto.dox | 26 ++-- libraries/Crypto/BLAKE2b.cpp | 76 +++++++++- libraries/Crypto/BLAKE2b.h | 2 + libraries/Crypto/BLAKE2s.cpp | 75 +++++++++- libraries/Crypto/BLAKE2s.h | 2 + .../examples/TestBLAKE2b/TestBLAKE2b.ino | 134 +++++++++++++++++- .../examples/TestBLAKE2s/TestBLAKE2s.ino | 122 ++++++++++++++++ 7 files changed, 421 insertions(+), 16 deletions(-) diff --git a/doc/crypto.dox b/doc/crypto.dox index e9a3aa82..07af41c1 100644 --- a/doc/crypto.dox +++ b/doc/crypto.dox @@ -58,6 +58,8 @@ BLAKE2s and BLAKE2b are variations on the ChaCha stream cipher, designed for hashing, with 256-bit and 512-bit hash outputs respectively. They are intended as high performance replacements for SHA256 and SHA512 for when speed is critical but exact bit-compatibility of hash values is not. +BLAKE2s and BLAKE2b support regular hashing, BLAKE2 keyed hashing, +and HMAC modes. \section crypto_other Examples and other topics @@ -71,7 +73,7 @@ All figures are for the Arduino Uno running at 16 MHz. Figures for the Ardunino Mega 2560 running at 16 MHz are similar: - + @@ -88,7 +90,7 @@ Ardunino Mega 2560 running at 16 MHz are similar: - + @@ -106,11 +108,13 @@ Ardunino Mega 2560 running at 16 MHz are similar: - + - + + + @@ -136,7 +140,7 @@ maximum is shown above. All figures are for the Arduino Due running at 84 MHz:
Encryption AlgorithmEncryption (per byte)Decryption (per byte)Key SetupState Size (bytes)
Encryption AlgorithmEncryption (per byte)Decryption (per byte)Key SetupState Size (bytes)
AES128 (ECB mode)33.28us63.18us160.00us181
AES192 (ECB mode)39.94us76.48us166.54us213
AES256 (ECB mode)46.61us89.78us227.97us245
SpeckTiny (192-bit key, ECB mode)36.56us 13.62us35
SpeckTiny (256-bit key, ECB mode)37.87us 16.89us35
AEAD AlgorithmEncryption (per byte)Decryption (per byte)Key SetupState Size (bytes)
AEAD AlgorithmEncryption (per byte)Decryption (per byte)Key SetupState Size (bytes)
ChaChaPoly41.20us41.19us902.36us221
GCM<AES128>109.71us109.26us1265.69us284
GCM<AES192>116.38us115.92us1485.56us316
SHA3_25660.69us8180.24us 205
SHA3_512113.88us8196.34us 205
BLAKE2s20.65us1335.25us 107
BLAKE2b65.22us8375.36us 211
BLAKE2b65.22us8375.34us 211
Authentication AlgorithmHashing (per byte)FinalizationKey SetupState Size (bytes)
Authentication AlgorithmHashing (per byte)FinalizationKey SetupState Size (bytes)
SHA256 (HMAC mode)43.85us8552.61us2836.49us107
BLAKE2s (Keyed mode)20.65us1335.25us1339.51us107
BLAKE2s (HMAC mode)20.65us4055.56us1350.00us107
BLAKE2b (Keyed mode)65.22us8375.34us8357.25us211
Poly130526.26us489.11us17.06us53
GHASH74.59us15.91us14.79us33
- + @@ -153,7 +157,7 @@ All figures are for the Arduino Due running at 84 MHz: - + @@ -170,12 +174,14 @@ All figures are for the Arduino Due running at 84 MHz: - - + + - + - + + + diff --git a/libraries/Crypto/BLAKE2b.cpp b/libraries/Crypto/BLAKE2b.cpp index 8cd8a880..7352ec06 100644 --- a/libraries/Crypto/BLAKE2b.cpp +++ b/libraries/Crypto/BLAKE2b.cpp @@ -36,7 +36,35 @@ * replacement for SHA512 for when speed is critical but exact SHA512 * compatibility is not. * - * Reference: https://blake2.net/ + * This class supports two types of keyed hash. The BLAKE2 keyed hash and + * traditional HMAC. The BLAKE2 keyed hash is recommended unless there is + * some higher-level application need to be compatible with the HMAC + * construction. The keyed hash is computed as follows: + * + * \code + * BLAKE2b blake; + * blake.reset(key, sizeof(key), outputLength); + * blake.update(data1, sizeof(data1)); + * blake.update(data2, sizeof(data2)); + * ... + * blake.update(dataN, sizeof(dataN)); + * blake.finalize(hash, outputLength); + * \endcode + * + * The HMAC is computed as follows (the output length is always 64): + * + * \code + * BLAKE2b blake; + * blake.resetHMAC(key, sizeof(key)); + * blake.update(data1, sizeof(data1)); + * blake.update(data2, sizeof(data2)); + * ... + * blake.update(dataN, sizeof(dataN)); + * blake.finalizeHMAC(key, sizeof(key), hash, 32); + * \endcode + * + * References: https://blake2.net/, + * RFC 7693 * * \sa BLAKE2s, SHA512, SHA3_512 */ @@ -102,6 +130,10 @@ void BLAKE2b::reset() */ void BLAKE2b::reset(uint8_t outputLength) { + if (outputLength < 1) + outputLength = 1; + else if (outputLength > 64) + outputLength = 64; state.h[0] = BLAKE2b_IV0 ^ 0x01010000 ^ outputLength; state.h[1] = BLAKE2b_IV1; state.h[2] = BLAKE2b_IV2; @@ -115,6 +147,48 @@ void BLAKE2b::reset(uint8_t outputLength) state.lengthHigh = 0; } +/** + * \brief Resets the hash ready for a new hashing process with a specified + * key and output length. + * + * \param key Points to the key. + * \param keyLen The length of the key in bytes, between 0 and 64. + * \param outputLength The output length to use for the final hash in bytes, + * between 1 and 64. + * + * If \a keyLen is greater than 64, then the \a key will be truncated to + * the first 64 bytes. + */ +void BLAKE2b::reset(const void *key, size_t keyLen, uint8_t outputLength) +{ + if (keyLen > 64) + keyLen = 64; + if (outputLength < 1) + outputLength = 1; + else if (outputLength > 64) + outputLength = 64; + state.h[0] = BLAKE2b_IV0 ^ 0x01010000 ^ (keyLen << 8) ^ outputLength; + state.h[1] = BLAKE2b_IV1; + state.h[2] = BLAKE2b_IV2; + state.h[3] = BLAKE2b_IV3; + state.h[4] = BLAKE2b_IV4; + state.h[5] = BLAKE2b_IV5; + state.h[6] = BLAKE2b_IV6; + state.h[7] = BLAKE2b_IV7; + if (keyLen > 0) { + // Set the first block to the key and pad with zeroes. + memcpy(state.m, key, keyLen); + memset(((uint8_t *)state.m) + keyLen, 0, 128 - keyLen); + state.chunkSize = 128; + state.lengthLow = 128; + } else { + // No key. The first data block is the first hashed block. + state.chunkSize = 0; + state.lengthLow = 0; + } + state.lengthHigh = 0; +} + void BLAKE2b::update(const void *data, size_t len) { // Break the input up into 1024-bit chunks and process each in turn. diff --git a/libraries/Crypto/BLAKE2b.h b/libraries/Crypto/BLAKE2b.h index 7f876647..e3f78684 100644 --- a/libraries/Crypto/BLAKE2b.h +++ b/libraries/Crypto/BLAKE2b.h @@ -36,6 +36,8 @@ public: void reset(); void reset(uint8_t outputLength); + void reset(const void *key, size_t keyLen, uint8_t outputLength = 64); + void update(const void *data, size_t len); void finalize(void *hash, size_t len); diff --git a/libraries/Crypto/BLAKE2s.cpp b/libraries/Crypto/BLAKE2s.cpp index e99117b3..a707ff7e 100644 --- a/libraries/Crypto/BLAKE2s.cpp +++ b/libraries/Crypto/BLAKE2s.cpp @@ -36,7 +36,35 @@ * replacement for SHA256 for when speed is critical but exact SHA256 * compatibility is not. * - * Reference: https://blake2.net/ + * This class supports two types of keyed hash. The BLAKE2 keyed hash and + * traditional HMAC. The BLAKE2 keyed hash is recommended unless there is + * some higher-level application need to be compatible with the HMAC + * construction. The keyed hash is computed as follows: + * + * \code + * BLAKE2s blake; + * blake.reset(key, sizeof(key), outputLength); + * blake.update(data1, sizeof(data1)); + * blake.update(data2, sizeof(data2)); + * ... + * blake.update(dataN, sizeof(dataN)); + * blake.finalize(hash, outputLength); + * \endcode + * + * The HMAC is computed as follows (the output length is always 32): + * + * \code + * BLAKE2s blake; + * blake.resetHMAC(key, sizeof(key)); + * blake.update(data1, sizeof(data1)); + * blake.update(data2, sizeof(data2)); + * ... + * blake.update(dataN, sizeof(dataN)); + * blake.finalizeHMAC(key, sizeof(key), hash, 32); + * \endcode + * + * References: https://blake2.net/, + * RFC 7693 * * \sa BLAKE2b, SHA256, SHA3_256 */ @@ -101,6 +129,10 @@ void BLAKE2s::reset() */ void BLAKE2s::reset(uint8_t outputLength) { + if (outputLength < 1) + outputLength = 1; + else if (outputLength > 32) + outputLength = 32; state.h[0] = BLAKE2s_IV0 ^ 0x01010000 ^ outputLength; state.h[1] = BLAKE2s_IV1; state.h[2] = BLAKE2s_IV2; @@ -113,6 +145,47 @@ void BLAKE2s::reset(uint8_t outputLength) state.length = 0; } +/** + * \brief Resets the hash ready for a new hashing process with a specified + * key and output length. + * + * \param key Points to the key. + * \param keyLen The length of the key in bytes, between 0 and 32. + * \param outputLength The output length to use for the final hash in bytes, + * between 1 and 32. + * + * If \a keyLen is greater than 32, then the \a key will be truncated to + * the first 32 bytes. + */ +void BLAKE2s::reset(const void *key, size_t keyLen, uint8_t outputLength) +{ + if (keyLen > 32) + keyLen = 32; + if (outputLength < 1) + outputLength = 1; + else if (outputLength > 32) + outputLength = 32; + state.h[0] = BLAKE2s_IV0 ^ 0x01010000 ^ (keyLen << 8) ^ outputLength; + state.h[1] = BLAKE2s_IV1; + state.h[2] = BLAKE2s_IV2; + state.h[3] = BLAKE2s_IV3; + state.h[4] = BLAKE2s_IV4; + state.h[5] = BLAKE2s_IV5; + state.h[6] = BLAKE2s_IV6; + state.h[7] = BLAKE2s_IV7; + if (keyLen > 0) { + // Set the first block to the key and pad with zeroes. + memcpy(state.m, key, keyLen); + memset(((uint8_t *)state.m) + keyLen, 0, 64 - keyLen); + state.chunkSize = 64; + state.length = 64; + } else { + // No key. The first data block is the first hashed block. + state.chunkSize = 0; + state.length = 0; + } +} + void BLAKE2s::update(const void *data, size_t len) { // Break the input up into 512-bit chunks and process each in turn. diff --git a/libraries/Crypto/BLAKE2s.h b/libraries/Crypto/BLAKE2s.h index 1131e282..3ebae2e6 100644 --- a/libraries/Crypto/BLAKE2s.h +++ b/libraries/Crypto/BLAKE2s.h @@ -36,6 +36,8 @@ public: void reset(); void reset(uint8_t outputLength); + void reset(const void *key, size_t keyLen, uint8_t outputLength = 32); + void update(const void *data, size_t len); void finalize(void *hash, size_t len); diff --git a/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino b/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino index a21b4a1c..683bbc6a 100644 --- a/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino +++ b/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino @@ -27,6 +27,7 @@ This example runs tests on the BLAKE2b implementation to verify correct behaviou #include #include #include +#include #define HASH_SIZE 64 #define BLOCK_SIZE 128 @@ -39,7 +40,7 @@ struct TestHashVector }; // Test vectors generated with the reference implementation of BLAKE2b. -static TestHashVector const testVectorBLAKE2b_1 = { +static TestHashVector const testVectorBLAKE2b_1 PROGMEM = { "BLAKE2b #1", "", {0x78, 0x6a, 0x02, 0xf7, 0x42, 0x01, 0x59, 0x03, @@ -51,7 +52,7 @@ static TestHashVector const testVectorBLAKE2b_1 = { 0x90, 0x3a, 0x68, 0x5b, 0x14, 0x48, 0xb7, 0x55, 0xd5, 0x6f, 0x70, 0x1a, 0xfe, 0x9b, 0xe2, 0xce} }; -static TestHashVector const testVectorBLAKE2b_2 = { +static TestHashVector const testVectorBLAKE2b_2 PROGMEM = { "BLAKE2b #2", "abc", {0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d, @@ -63,7 +64,7 @@ static TestHashVector const testVectorBLAKE2b_2 = { 0x18, 0xd3, 0x8a, 0xa8, 0xdb, 0xf1, 0x92, 0x5a, 0xb9, 0x23, 0x86, 0xed, 0xd4, 0x00, 0x99, 0x23} }; -static TestHashVector const testVectorBLAKE2b_3 = { +static TestHashVector const testVectorBLAKE2b_3 PROGMEM = { "BLAKE2b #3", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", {0x72, 0x85, 0xff, 0x3e, 0x8b, 0xd7, 0x68, 0xd6, @@ -75,7 +76,7 @@ static TestHashVector const testVectorBLAKE2b_3 = { 0x47, 0x13, 0x0b, 0x44, 0xf3, 0x3a, 0x02, 0xe8, 0x73, 0x0e, 0x5a, 0xd8, 0xe1, 0x66, 0xe8, 0x88} }; -static TestHashVector const testVectorBLAKE2b_4 = { +static TestHashVector const testVectorBLAKE2b_4 PROGMEM = { "BLAKE2b #4", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", @@ -116,6 +117,10 @@ bool testHash_N(Hash *hash, const struct TestHashVector *test, size_t inc) void testHash(Hash *hash, const struct TestHashVector *test) { bool ok; + TestHashVector vec; + + memcpy_P(&vec, test, sizeof(vec)); + test = &vec; Serial.print(test->name); Serial.print(" ... "); @@ -224,6 +229,125 @@ void testHMAC(Hash *hash, size_t keyLen) Serial.println("Failed"); } +// Deterministic sequences (Fibonacci generator). From RFC 7693. +static void selftest_seq(uint8_t *out, size_t len, uint32_t seed) +{ + size_t i; + uint32_t t, a , b; + + a = 0xDEAD4BAD * seed; // prime + b = 1; + + for (i = 0; i < len; i++) { // fill the buf + t = a + b; + a = b; + b = t; + out[i] = (t >> 24) & 0xFF; + } +} + +// Incremental version of above to save memory. +static void selftest_seq_incremental(BLAKE2b *blake, size_t len, uint32_t seed) +{ + size_t i; + uint32_t t, a , b; + + a = 0xDEAD4BAD * seed; // prime + b = 1; + + for (i = 0; i < len; i++) { // fill the buf + t = a + b; + a = b; + b = t; + buffer[i % 128] = (t >> 24) & 0xFF; + if ((i % 128) == 127) + blake->update(buffer, 128); + } + + blake->update(buffer, len % 128); +} + +// Run the self-test from Appendix E of RFC 7693. Most of this code +// is from RFC 7693, with modifications to use the Crypto library. +void testRFC7693() +{ + // Grand hash of hash results. + static const uint8_t blake2b_res[32] PROGMEM = { + 0xC2, 0x3A, 0x78, 0x00, 0xD9, 0x81, 0x23, 0xBD, + 0x10, 0xF5, 0x06, 0xC6, 0x1E, 0x29, 0xDA, 0x56, + 0x03, 0xD7, 0x63, 0xB8, 0xBB, 0xAD, 0x2E, 0x73, + 0x7F, 0x5E, 0x76, 0x5A, 0x7B, 0xCC, 0xD4, 0x75 + }; + // Parameter sets. + static const uint8_t b2b_md_len[4] PROGMEM = { 20, 32, 48, 64 }; + static const uint16_t b2b_in_len[6] PROGMEM = { 0, 3, 128, 129, 255, 1024 }; + + size_t i, j, outlen, inlen; + uint8_t md[64], key[64]; + BLAKE2b inner; + + Serial.print("BLAKE2b RFC 7693 ... "); + + // 256-bit hash for testing. + blake2b.reset(32); + + for (i = 0; i < 4; i++) { + outlen = pgm_read_byte(&(b2b_md_len[i])); + for (j = 0; j < 6; j++) { + inlen = pgm_read_word(&(b2b_in_len[j])); + + inner.reset(outlen); // unkeyed hash + selftest_seq_incremental(&inner, inlen, inlen); + inner.finalize(md, outlen); + blake2b.update(md, outlen); // hash the hash + + selftest_seq(key, outlen, outlen); // keyed hash + inner.reset(key, outlen, outlen); + selftest_seq_incremental(&inner, inlen, inlen); + inner.finalize(md, outlen); + blake2b.update(md, outlen); // hash the hash + } + } + + // Compute and compare the hash of hashes. + bool ok = true; + blake2b.finalize(md, 32); + for (i = 0; i < 32; i++) { + if (md[i] != pgm_read_byte(&(blake2b_res[i]))) + ok = false; + } + + // Report the results. + if (ok) + Serial.println("Passed"); + else + Serial.println("Failed"); +} + +void perfKeyed(BLAKE2b *hash) +{ + unsigned long start; + unsigned long elapsed; + int count; + + Serial.print("Keyed Reset ... "); + + for (size_t posn = 0; posn < sizeof(buffer); ++posn) + buffer[posn] = (uint8_t)posn; + + start = micros(); + for (count = 0; count < 1000; ++count) { + hash->reset(buffer, hash->hashSize()); + hash->update(buffer, 1); // To flush the key chunk. + } + elapsed = micros() - start; + + Serial.print(elapsed / 1000.0); + Serial.print("us per op, "); + Serial.print((1000.0 * 1000000.0) / elapsed); + Serial.println(" ops per second"); +} + void perfFinalize(Hash *hash) { unsigned long start; @@ -267,11 +391,13 @@ void setup() testHMAC(&blake2b, BLOCK_SIZE); testHMAC(&blake2b, BLOCK_SIZE + 1); testHMAC(&blake2b, BLOCK_SIZE + 2); + testRFC7693(); Serial.println(); Serial.println("Performance Tests:"); perfHash(&blake2b); + perfKeyed(&blake2b); perfFinalize(&blake2b); } diff --git a/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino b/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino index 1c06d7cb..153e9b35 100644 --- a/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino +++ b/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino @@ -27,6 +27,7 @@ This example runs tests on the BLAKE2s implementation to verify correct behaviou #include #include #include +#include #define HASH_SIZE 32 #define BLOCK_SIZE 64 @@ -208,6 +209,101 @@ void testHMAC(Hash *hash, size_t keyLen) Serial.println("Failed"); } +// Deterministic sequences (Fibonacci generator). From RFC 7693. +static void selftest_seq(uint8_t *out, size_t len, uint32_t seed) +{ + size_t i; + uint32_t t, a , b; + + a = 0xDEAD4BAD * seed; // prime + b = 1; + + for (i = 0; i < len; i++) { // fill the buf + t = a + b; + a = b; + b = t; + out[i] = (t >> 24) & 0xFF; + } +} + +// Incremental version of above to save memory. +static void selftest_seq_incremental(BLAKE2s *blake, size_t len, uint32_t seed) +{ + size_t i; + uint32_t t, a , b; + + a = 0xDEAD4BAD * seed; // prime + b = 1; + + for (i = 0; i < len; i++) { // fill the buf + t = a + b; + a = b; + b = t; + buffer[i % 128] = (t >> 24) & 0xFF; + if ((i % 128) == 127) + blake->update(buffer, sizeof(buffer)); + } + + blake->update(buffer, len % 128); +} + +// Run the self-test from Appendix E of RFC 7693. Most of this code +// is from RFC 7693, with modifications to use the Crypto library. +void testRFC7693() +{ + // Grand hash of hash results. + static const uint8_t blake2s_res[32] PROGMEM = { + 0x6A, 0x41, 0x1F, 0x08, 0xCE, 0x25, 0xAD, 0xCD, + 0xFB, 0x02, 0xAB, 0xA6, 0x41, 0x45, 0x1C, 0xEC, + 0x53, 0xC5, 0x98, 0xB2, 0x4F, 0x4F, 0xC7, 0x87, + 0xFB, 0xDC, 0x88, 0x79, 0x7F, 0x4C, 0x1D, 0xFE + }; + // Parameter sets. + static const uint8_t b2s_md_len[4] PROGMEM = { 16, 20, 28, 32 }; + static const uint16_t b2s_in_len[6] PROGMEM = { 0, 3, 64, 65, 255, 1024 }; + + size_t i, j, outlen, inlen; + uint8_t md[32], key[32]; + BLAKE2s inner; + + Serial.print("BLAKE2s RFC 7693 ... "); + + // 256-bit hash for testing. + blake2s.reset(32); + + for (i = 0; i < 4; i++) { + outlen = pgm_read_byte(&(b2s_md_len[i])); + for (j = 0; j < 6; j++) { + inlen = pgm_read_word(&(b2s_in_len[j])); + + inner.reset(outlen); // unkeyed hash + selftest_seq_incremental(&inner, inlen, inlen); + inner.finalize(md, outlen); + blake2s.update(md, outlen); // hash the hash + + selftest_seq(key, outlen, outlen); // keyed hash + inner.reset(key, outlen, outlen); + selftest_seq_incremental(&inner, inlen, inlen); + inner.finalize(md, outlen); + blake2s.update(md, outlen); // hash the hash + } + } + + // Compute and compare the hash of hashes. + bool ok = true; + blake2s.finalize(md, 32); + for (i = 0; i < 32; i++) { + if (md[i] != pgm_read_byte(&(blake2s_res[i]))) + ok = false; + } + + // Report the results. + if (ok) + Serial.println("Passed"); + else + Serial.println("Failed"); +} + void perfFinalize(Hash *hash) { unsigned long start; @@ -230,6 +326,30 @@ void perfFinalize(Hash *hash) Serial.println(" ops per second"); } +void perfKeyed(BLAKE2s *hash) +{ + unsigned long start; + unsigned long elapsed; + int count; + + Serial.print("Keyed Reset ... "); + + for (size_t posn = 0; posn < sizeof(buffer); ++posn) + buffer[posn] = (uint8_t)posn; + + start = micros(); + for (count = 0; count < 1000; ++count) { + hash->reset(buffer, hash->hashSize()); + hash->update(buffer, 1); // To flush the key chunk. + } + elapsed = micros() - start; + + Serial.print(elapsed / 1000.0); + Serial.print("us per op, "); + Serial.print((1000.0 * 1000000.0) / elapsed); + Serial.println(" ops per second"); +} + void perfHMAC(Hash *hash) { unsigned long start; @@ -289,12 +409,14 @@ void setup() testHMAC(&blake2s, BLOCK_SIZE); testHMAC(&blake2s, BLOCK_SIZE + 1); testHMAC(&blake2s, sizeof(buffer)); + testRFC7693(); Serial.println(); Serial.println("Performance Tests:"); perfHash(&blake2s); perfFinalize(&blake2s); + perfKeyed(&blake2s); perfHMAC(&blake2s); }
Encryption AlgorithmEncryption (per byte)Decryption (per byte)Key SetupState Size (bytes)
Encryption AlgorithmEncryption (per byte)Decryption (per byte)Key SetupState Size (bytes)
AES128 (ECB mode)5.71us10.41us34.73us188
AES192 (ECB mode)6.87us12.57us36.51us220
AES256 (ECB mode)8.04us14.7249.96us252
SpeckTiny (192-bit key, ECB mode)2.81us 1.54us48
SpeckTiny (256-bit key, ECB mode)2.90us 1.83us48
AEAD AlgorithmEncryption (per byte)Decryption (per byte)Key SetupState Size (bytes)
AEAD AlgorithmEncryption (per byte)Decryption (per byte)Key SetupState Size (bytes)
ChaChaPoly1.71us1.71us45.08us240
GCM<AES128>10.90us10.90us248.83us312
GCM<AES192>12.30us12.31us296.83us344
SHA5122.87us370.37us 224
SHA3_2565.64us735.29us 224
SHA3_51210.42us735.49us 224
BLAKE2s0.72us48.24us 120
BLAKE2b1.29us165.28us 224
BLAKE2s0.80us53.39us 120
BLAKE2b1.28us164.66us 224
Authentication AlgorithmHashing (per byte)FinalizationKey SetupState Size (bytes)
Authentication AlgorithmHashing (per byte)FinalizationKey SetupState Size (bytes)
SHA256 (HMAC mode)1.15us238.98us80.44us120
BLAKE2s (HMAC mode)0.72us157.75us57.18us120
BLAKE2s (Keyed mode)0.80us53.39us55.10us120
BLAKE2s (HMAC mode)0.80us168.20us57.60us120
BLAKE2b (Keyed mode)1.28us164.66us166.68us224
Poly13050.81us19.01us2.57us60
GHASH4.47us1.52us2.60us36