1
0
mirror of https://github.com/taigrr/arduinolibs synced 2025-01-18 04:33:12 -08:00

Simplify the hashing API by removing the need to remember the final hash

This commit is contained in:
Rhys Weatherley 2015-03-14 15:36:40 +10:00
parent e7175a80f3
commit 0c52bf0d50
17 changed files with 94 additions and 196 deletions

View File

@ -63,13 +63,13 @@ Ardunino Mega 2560 running at 16 MHz are similar:
<tr><td>ChaCha (20 rounds)</td><td align="right">14.87us</td><td align="right">14.88us</td><td align="right">43.74us</td><td align="right">130</td></tr>
<tr><td>ChaCha (12 rounds)</td><td align="right">10.38us</td><td align="right">10.38us</td><td align="right">43.74us</td><td align="right">130</td></tr>
<tr><td>ChaCha (8 rounds)</td><td align="right">8.13us</td><td align="right">8.14us</td><td align="right">43.74us</td><td align="right">130</td></tr>
<tr><td>SHA1</td><td align="right">21.90us</td><td> </td><td align="right"> </td><td align="right">94</td></tr>
<tr><td>SHA256</td><td align="right">43.85us</td><td> </td><td align="right"> </td><td align="right">106</td></tr>
<tr><td>SHA512</td><td align="right">123.25us</td><td> </td><td align="right"> </td><td align="right">210</td></tr>
<tr><td>SHA1</td><td align="right">21.90us</td><td> </td><td align="right"> </td><td align="right">93</td></tr>
<tr><td>SHA256</td><td align="right">43.85us</td><td> </td><td align="right"> </td><td align="right">105</td></tr>
<tr><td>SHA512</td><td align="right">123.24us</td><td> </td><td align="right"> </td><td align="right">209</td></tr>
<tr><td>SHA3_256</td><td align="right">121.69us</td><td> </td><td align="right"> </td><td align="right">403</td></tr>
<tr><td>SHA3_512</td><td align="right">229.12us</td><td> </td><td align="right"> </td><td align="right">403</td></tr>
<tr><td>BLAKE2s</td><td align="right">18.54us</td><td> </td><td align="right"> </td><td align="right">170</td></tr>
<tr><td>BLAKE2b</td><td align="right">50.59us</td><td> </td><td align="right"> </td><td align="right">338</td></tr>
<tr><td>BLAKE2s</td><td align="right">18.54us</td><td> </td><td align="right"> </td><td align="right">169</td></tr>
<tr><td>BLAKE2b</td><td align="right">50.58us</td><td> </td><td align="right"> </td><td align="right">337</td></tr>
</table>
Where a cipher supports more than one key size (such as ChaCha), the values

View File

@ -89,7 +89,6 @@ void BLAKE2b::reset()
state.h[6] = BLAKE2b_IV6;
state.h[7] = BLAKE2b_IV7;
state.chunkSize = 0;
state.finalized = false;
state.lengthLow = 0;
state.lengthHigh = 0;
}
@ -112,17 +111,12 @@ void BLAKE2b::reset(uint8_t outputLength)
state.h[6] = BLAKE2b_IV6;
state.h[7] = BLAKE2b_IV7;
state.chunkSize = 0;
state.finalized = false;
state.lengthLow = 0;
state.lengthHigh = 0;
}
void BLAKE2b::update(const void *data, size_t len)
{
// Reset the hashing process if finalize() was called previously.
if (state.finalized)
reset();
// Break the input up into 1024-bit chunks and process each in turn.
const uint8_t *d = (const uint8_t *)data;
while (len > 0) {
@ -148,8 +142,6 @@ void BLAKE2b::update(const void *data, size_t len)
void BLAKE2b::finalize(void *hash, size_t len)
{
// Finalize the hash if necessary.
if (!state.finalized) {
// Pad the last chunk and hash it with f0 set to all-ones.
memset(((uint8_t *)state.m) + state.chunkSize, 0, 128 - state.chunkSize);
processChunk(0xFFFFFFFFFFFFFFFFULL);
@ -157,8 +149,6 @@ void BLAKE2b::finalize(void *hash, size_t len)
// Convert the hash into little-endian in the message buffer.
for (uint8_t posn = 0; posn < 8; ++posn)
state.m[posn] = htole64(state.h[posn]);
state.finalized = true;
}
// Copy the hash to the caller's return buffer.
if (len > 64)

View File

@ -46,10 +46,9 @@ private:
uint64_t h[8];
uint64_t m[16];
uint64_t v[16];
uint8_t chunkSize;
bool finalized;
uint64_t lengthLow;
uint64_t lengthHigh;
uint8_t chunkSize;
} state;
void processChunk(uint64_t f0);

View File

@ -89,7 +89,6 @@ void BLAKE2s::reset()
state.h[6] = BLAKE2s_IV6;
state.h[7] = BLAKE2s_IV7;
state.chunkSize = 0;
state.finalized = false;
state.length = 0;
}
@ -111,16 +110,11 @@ void BLAKE2s::reset(uint8_t outputLength)
state.h[6] = BLAKE2s_IV6;
state.h[7] = BLAKE2s_IV7;
state.chunkSize = 0;
state.finalized = false;
state.length = 0;
}
void BLAKE2s::update(const void *data, size_t len)
{
// Reset the hashing process if finalize() was called previously.
if (state.finalized)
reset();
// Break the input up into 512-bit chunks and process each in turn.
const uint8_t *d = (const uint8_t *)data;
while (len > 0) {
@ -143,8 +137,6 @@ void BLAKE2s::update(const void *data, size_t len)
void BLAKE2s::finalize(void *hash, size_t len)
{
// Finalize the hash if necessary.
if (!state.finalized) {
// Pad the last chunk and hash it with f0 set to all-ones.
memset(((uint8_t *)state.m) + state.chunkSize, 0, 64 - state.chunkSize);
processChunk(0xFFFFFFFF);
@ -152,8 +144,6 @@ void BLAKE2s::finalize(void *hash, size_t len)
// Convert the hash into little-endian in the message buffer.
for (uint8_t posn = 0; posn < 8; ++posn)
state.m[posn] = htole32(state.h[posn]);
state.finalized = true;
}
// Copy the hash to the caller's return buffer.
if (len > 32)

View File

@ -46,9 +46,8 @@ private:
uint32_t h[8];
uint32_t m[16];
uint32_t v[16];
uint8_t chunkSize;
bool finalized;
uint64_t length;
uint8_t chunkSize;
} state;
void processChunk(uint32_t f0);

View File

@ -76,8 +76,8 @@ Hash::~Hash()
* \param data Data to be hashed.
* \param len Number of bytes of data to be hashed.
*
* If finalize() has already been called, then calling update() will
* reset() the hash and start a new hashing process.
* If finalize() has already been called, then the behavior of update() will
* be undefined. Call reset() first to start a new hashing process.
*
* \sa reset(), finalize()
*/
@ -93,8 +93,8 @@ Hash::~Hash()
* truncated to the first \a len bytes. If \a len is greater than
* hashSize(), then the remaining bytes will left unchanged.
*
* If finalize() is called again, the same hash value is returned again until
* the next call to reset() or update().
* If finalize() is called again, then the returned \a hash value is
* undefined. Call reset() first to start a new hashing process.
*
* \sa reset(), update()
*/

View File

@ -69,16 +69,11 @@ void SHA1::reset()
state.h[3] = 0x10325476;
state.h[4] = 0xC3D2E1F0;
state.chunkSize = 0;
state.finalized = false;
state.length = 0;
}
void SHA1::update(const void *data, size_t len)
{
// Reset the hashing process if finalize() was called previously.
if (state.finalized)
reset();
// Update the total length (in bits, not bytes).
state.length += ((uint64_t)len) << 3;
@ -101,8 +96,6 @@ void SHA1::update(const void *data, size_t len)
void SHA1::finalize(void *hash, size_t len)
{
// Finalize the hash if necessary.
if (!state.finalized) {
// Pad the last chunk. We may need two padding chunks if there
// isn't enough room in the first for the padding and length.
uint8_t *wbytes = (uint8_t *)state.w;
@ -125,8 +118,6 @@ void SHA1::finalize(void *hash, size_t len)
// Convert the result into big endian and return it.
for (uint8_t posn = 0; posn < 5; ++posn)
state.w[posn] = htobe32(state.h[posn]);
state.finalized = true;
}
// Copy the hash to the caller's return buffer.
if (len > 20)

View File

@ -44,9 +44,8 @@ private:
struct {
uint32_t h[5];
uint32_t w[16];
uint8_t chunkSize;
bool finalized;
uint64_t length;
uint8_t chunkSize;
} state;
void processChunk();

View File

@ -74,16 +74,11 @@ void SHA256::reset()
state.h[6] = 0x1f83d9ab;
state.h[7] = 0x5be0cd19;
state.chunkSize = 0;
state.finalized = false;
state.length = 0;
}
void SHA256::update(const void *data, size_t len)
{
// Reset the hashing process if finalize() was called previously.
if (state.finalized)
reset();
// Update the total length (in bits, not bytes).
state.length += ((uint64_t)len) << 3;
@ -106,8 +101,6 @@ void SHA256::update(const void *data, size_t len)
void SHA256::finalize(void *hash, size_t len)
{
// Finalize the hash if necessary.
if (!state.finalized) {
// Pad the last chunk. We may need two padding chunks if there
// isn't enough room in the first for the padding and length.
uint8_t *wbytes = (uint8_t *)state.w;
@ -130,8 +123,6 @@ void SHA256::finalize(void *hash, size_t len)
// Convert the result into big endian and return it.
for (uint8_t posn = 0; posn < 8; ++posn)
state.w[posn] = htobe32(state.h[posn]);
state.finalized = true;
}
// Copy the hash to the caller's return buffer.
if (len > 32)

View File

@ -44,9 +44,8 @@ private:
struct {
uint32_t h[8];
uint32_t w[16];
uint8_t chunkSize;
bool finalized;
uint64_t length;
uint8_t chunkSize;
} state;
void processChunk();

View File

@ -72,17 +72,12 @@ void SHA512::reset()
};
memcpy_P(state.h, hashStart, sizeof(hashStart));
state.chunkSize = 0;
state.finalized = false;
state.lengthLow = 0;
state.lengthHigh = 0;
}
void SHA512::update(const void *data, size_t len)
{
// Reset the hashing process if finalize() was called previously.
if (state.finalized)
reset();
// Update the total length in bits, not bytes.
uint64_t temp = state.lengthLow;
state.lengthLow += (((uint64_t)len) << 3);
@ -109,8 +104,6 @@ void SHA512::update(const void *data, size_t len)
void SHA512::finalize(void *hash, size_t len)
{
// Finalize the hash if necessary.
if (!state.finalized) {
// Pad the last chunk. We may need two padding chunks if there
// isn't enough room in the first for the padding and length.
uint8_t *wbytes = (uint8_t *)state.w;
@ -133,8 +126,6 @@ void SHA512::finalize(void *hash, size_t len)
// Convert the result into big endian and return it.
for (uint8_t posn = 0; posn < 8; ++posn)
state.w[posn] = htobe64(state.h[posn]);
state.finalized = true;
}
// Copy the hash to the caller's return buffer.
if (len > 64)

View File

@ -44,10 +44,9 @@ private:
struct {
uint64_t h[8];
uint64_t w[16];
uint8_t chunkSize;
bool finalized;
uint64_t lengthLow;
uint64_t lengthHigh;
uint8_t chunkSize;
} state;
void processChunk();

View File

@ -98,17 +98,7 @@ bool testHash_N(Hash *hash, const struct TestHashVector *test, size_t inc)
size_t posn, len;
uint8_t value[HASH_SIZE];
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)
len = inc;
hash->update(test->data + posn, len);
}
hash->finalize(value, sizeof(value));
if (memcmp(value, test->hash, sizeof(value)) != 0)
return false;
// Try again to make sure the hash resets.
hash->reset();
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)

View File

@ -82,17 +82,7 @@ bool testHash_N(Hash *hash, const struct TestHashVector *test, size_t inc)
size_t posn, len;
uint8_t value[HASH_SIZE];
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)
len = inc;
hash->update(test->data + posn, len);
}
hash->finalize(value, sizeof(value));
if (memcmp(value, test->hash, sizeof(value)) != 0)
return false;
// Try again to make sure the hash resets.
hash->reset();
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)

View File

@ -62,17 +62,7 @@ bool testHash_N(Hash *hash, const struct TestHashVector *test, size_t inc)
size_t posn, len;
uint8_t value[HASH_SIZE];
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)
len = inc;
hash->update(test->data + posn, len);
}
hash->finalize(value, sizeof(value));
if (memcmp(value, test->hash, sizeof(value)) != 0)
return false;
// Try again to make sure the hash resets.
hash->reset();
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)

View File

@ -64,17 +64,7 @@ bool testHash_N(Hash *hash, const struct TestHashVector *test, size_t inc)
size_t posn, len;
uint8_t value[HASH_SIZE];
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)
len = inc;
hash->update(test->data + posn, len);
}
hash->finalize(value, sizeof(value));
if (memcmp(value, test->hash, sizeof(value)) != 0)
return false;
// Try again to make sure the hash resets.
hash->reset();
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)

View File

@ -85,17 +85,7 @@ bool testHash_N(Hash *hash, const struct TestHashVector *test, size_t inc)
size_t posn, len;
uint8_t value[HASH_SIZE];
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)
len = inc;
hash->update(test->data + posn, len);
}
hash->finalize(value, sizeof(value));
if (memcmp(value, test->hash, sizeof(value)) != 0)
return false;
// Try again to make sure the hash resets.
hash->reset();
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)