Added SHAKE128/256 code and test vectors.

This commit is contained in:
Markku-Juhani O. Saarinen
2015-12-27 13:27:27 +00:00
parent e827929647
commit cc3d33a961
4 changed files with 109 additions and 11 deletions

View File

@@ -1,9 +1,17 @@
# tiny_sha3
Very small, readable implementation of the SHA3 hash function.
Updated 03-Sep-15:
Very small, readable implementation of the FIPS 202 and SHA3 hash function.
Public domain.
### Updated 27-Dec-15:
Added SHAKE128 and SHAKE256 code and test vectors. The code can actually do
a XOF of arbitrary size (like "SHAKE512").
### Updated 03-Sep-15:
Made the implementation portable. The API is now pretty much the
same that OpenSSL uses. Public domain.
same that OpenSSL uses.
### Updated 07-Aug-15:
@@ -25,7 +33,7 @@ Cheers,
- markku
### Original README.TXT from 2011:
### Original README.TXT from 19-Nov-11:
Hi.

62
main.c
View File

@@ -89,9 +89,64 @@ int test_sha3()
sha3(msg, msg_len, buf, sha_len);
if (memcmp(sha, buf, sha_len) != 0) {
fails++;
fprintf(stderr, "[%d] SHA3-%d, len %d test FAILED.\n",
i, sha_len * 8, msg_len);
fails++;
}
}
return fails;
}
// test for SHAKE128 and SHAKE256
int test_shake()
{
// Test vectors have bytes 480..511 of XOF output for given inputs.
// From http://csrc.nist.gov/groups/ST/toolkit/examples.html#aHashing
const char *testhex[4] = {
// SHAKE128, message of length 0
"43E41B45A653F2A5C4492C1ADD544512DDA2529833462B71A41A45BE97290B6F",
// SHAKE256, message of length 0
"AB0BAE316339894304E35877B0C28A9B1FD166C796B9CC258A064A8F57E27F2A",
// SHAKE128, 1600-bit test pattern
"44C9FB359FD56AC0A9A75A743CFF6862F17D7259AB075216C0699511643B6439",
// SHAKE256, 1600-bit test pattern
"6A1A9D7846436E4DCA5728B6F760EEF0CA92BF0BE5615E96959D767197A0BEEB"
};
int i, j, fails;
sha3_ctx_t sha3;
uint8_t buf[32], ref[32];
fails = 0;
for (i = 0; i < 4; i++) {
if ((i & 1) == 0) { // test each twice
shake128_init(&sha3);
} else {
shake256_init(&sha3);
}
if (i >= 2) { // 1600-bit test pattern
memset(buf, 0xA3, 20);
for (j = 0; j < 200; j += 20)
shake_update(&sha3, buf, 20);
}
shake_xof(&sha3); // switch to extensible output
for (j = 0; j < 512; j += 32) // output. discard bytes 0..479
shake_out(&sha3, buf, 32);
// compare to reference
test_readhex(ref, testhex[i], sizeof(ref));
if (memcmp(buf, ref, 32) != 0) {
fprintf(stderr, "[%d] SHAKE%d, len %d test FAILED.\n",
i, i & 1 ? 256 : 128, i >= 2 ? 1600 : 0);
fails++;
}
}
@@ -101,8 +156,9 @@ int test_sha3()
// main
int main(int argc, char **argv)
{
if (test_sha3() == 0)
printf("SHA-3 Self-Test OK!\n");
if (test_sha3() == 0 && test_shake() == 0)
printf("FIPS 202 / SHA3, SHAKE128, SHAKE256 Self-Tests OK!\n");
return 0;
}

30
sha3.c
View File

@@ -124,7 +124,7 @@ int sha3_update(sha3_ctx_t *c, const void *data, size_t len)
for (i = 0; i < len; i++) {
c->st.b[j++] ^= ((const uint8_t *) data)[i];
if (j >= c->rsiz) {
sha3_keccakf(c->st.q, SHA3_ROUNDS);
sha3_keccakf(c->st.q, KECCAKF_ROUNDS);
j = 0;
}
}
@@ -141,7 +141,7 @@ int sha3_final(void *md, sha3_ctx_t *c)
c->st.b[c->pt] ^= 0x06;
c->st.b[c->rsiz - 1] ^= 0x80;
sha3_keccakf(c->st.q, SHA3_ROUNDS);
sha3_keccakf(c->st.q, KECCAKF_ROUNDS);
for (i = 0; i < c->mdlen; i++) {
((uint8_t *) md)[i] = c->st.b[i];
@@ -163,3 +163,29 @@ void *sha3(const void *in, size_t inlen, void *md, int mdlen)
return md;
}
// SHAKE128 and SHAKE256 extensible-output functionality
void shake_xof(sha3_ctx_t *c)
{
c->st.b[c->pt] ^= 0x1F;
c->st.b[c->rsiz - 1] ^= 0x80;
sha3_keccakf(c->st.q, KECCAKF_ROUNDS);
c->pt = 0;
}
void shake_out(sha3_ctx_t *c, void *out, size_t len)
{
size_t i;
int j;
j = c->pt;
for (i = 0; i < len; i++) {
if (j >= c->rsiz) {
sha3_keccakf(c->st.q, KECCAKF_ROUNDS);
j = 0;
}
((uint8_t *) out)[i] = c->st.b[j++];
}
c->pt = j;
}

12
sha3.h
View File

@@ -7,8 +7,8 @@
#include <stddef.h>
#include <stdint.h>
#ifndef SHA3_ROUNDS
#define SHA3_ROUNDS 24
#ifndef KECCAKF_ROUNDS
#define KECCAKF_ROUNDS 24
#endif
#ifndef ROTL64
@@ -32,5 +32,13 @@ int sha3_final(void *md, sha3_ctx_t *c); // digest goes to md
// compute a sha3 hash (md) of given byte length from "in"
void *sha3(const void *in, size_t inlen, void *md, int mdlen);
// SHAKE128 and SHAKE256 extensible-output functions
#define shake128_init(c) sha3_init(c, 16)
#define shake256_init(c) sha3_init(c, 32)
#define shake_update sha3_update
void shake_xof(sha3_ctx_t *c);
void shake_out(sha3_ctx_t *c, void *out, size_t len);
#endif