Repository: brainhub/SHA3IUF
Branch: master
Commit: fc8504750a5c
Files: 52
Total size: 36.1 KB
Directory structure:
gitextract_5tj02dc8/
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── fuzz/
│ ├── run.sh
│ ├── seeds/
│ │ ├── 01ec548baccbe69625b54206ef7100f5ed03719f
│ │ ├── 0a5dec3f2ed57a024ccba1041dc85e54e09f74d4
│ │ ├── 0bfb1ece6a9278c2fc475bb8901308f8a9cafbb4
│ │ ├── 13817dae42cce3b01da9435b035a8b8ea94d2df8
│ │ ├── 1511dc059ee7a55d9ac4d4a91b5bf8929f846d0f
│ │ ├── 19852f1f4d08174b77ba2c88e0d8ec1455348b22
│ │ ├── 1f8cc307c05de3bf9d98f90dcfa11583d187d15a
│ │ ├── 27c554131c35630341a2b84ecaab53072fbfe6ca
│ │ ├── 28b9d530ca4a5765c6def1393d1252acb9f3de90
│ │ ├── 2daa36d007df33c974630657696ef4fbc665ca12
│ │ ├── 30f28e65f01f0af35a4b1b8dbc20dafa5cfb5584
│ │ ├── 355a748ff0b67ea9fa417f1ed773a3641ebd4929
│ │ ├── 363323cbf90a34023130dbba0777f6ddd3063d4f
│ │ ├── 3c363836cf4e16666669a25da280a1865c2d2874
│ │ ├── 3d838f2ff09a1f5f0405fc46b63127f2ae00032e
│ │ ├── 4c767fec38e38bc45cbe9f4c97b298944183ac15
│ │ ├── 520b1aab7fdbbdfaa160e777878116a119ff3200
│ │ ├── 5d7ecbb52e7818d4d2d5c68ebd26dd3b5ad67cc3
│ │ ├── 5e47ec79910a8df76747862af0aec850d7b3f29a
│ │ ├── 6f7ca473e2aee8204381b00777801535151c58bd
│ │ ├── 71853c6197a6a7f222db0f1978c7cb232b87c5ee
│ │ ├── 744dd71fe66027d943e84151fda2555e9a67c0cb
│ │ ├── 759e0d4e0d765166c3b1aa9e66ece0d146cb68e6
│ │ ├── 819c227c2780b372be25bbd8028fd806ab0cba35
│ │ ├── 8519208c0cb8cbb2c2731dae901752df10c2ab7e
│ │ ├── 885f051ffcf79b45bee97b7b52d7f9087533f192
│ │ ├── 98fc3c55ad129219ed5ffa43cd36a83fd6c2248e
│ │ ├── a03822c4ce67e2d8d243fc3b0f0d96338b6555d2
│ │ ├── a4bf6fc7ed78f9cdc178168a3a60070f3fae68ab
│ │ ├── a60cbf05a3f86e96123bc6a87803f3fe0de1a272
│ │ ├── a979ef10cc6f6a36df6b8a323307ee3bb2e2db9c
│ │ ├── b69e21c4d029acf5779df9a7167cb0b3d76b6a91
│ │ ├── b6dd110c53d944c083ae6e45383b73310ef11856
│ │ ├── bab01b936511366f8048d15679eeb875db818a1f
│ │ ├── c63ae6dd4fc9f9dda66970e827d13f7c73fe841c
│ │ ├── e0bb4ab56fc584ad6992e3b4de55e96d9f626b25
│ │ ├── e9c3d0af3f6d6b0897bb52bd597ecbee5559ec34
│ │ ├── f45250b51fd7511ea177e87492cfb303b73517b3
│ │ ├── f5424addd46d466b132717d8f9cf0dc2d7bbc5eb
│ │ ├── f5c5efe3024d0f2e32d53036cd1954b99dff03d8
│ │ ├── f6183b6a7bbe75583b8061d8438db6f9ed47fba3
│ │ └── f6c3c3c3fc3d562e27461eda971ba56df05c22fd
│ └── sha3fuzz.c
├── sha3.c
├── sha3.h
├── sha3sum.c
└── sha3test.c
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
/*.o
/*.a
/sha3sum
/sha3test
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020 brainhub
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Makefile
================================================
.POSIX:
CC = c99
CFLAGS = -std=c99 -Wall -Wextra -Wpedantic -O2 -g
LDFLAGS =
LDLIBS =
PREFIX = /usr/local
all: libsha3.a sha3sum sha3test
.SUFFIXES: .c .o
.c.o:
$(CC) -c $(CFLAGS) -o $@ $<
libsha3.a: sha3.o
ar rsv $@ sha3.o
sha3sum: sha3.o sha3sum.o
$(CC) $(LDFLAGS) -o $@ sha3.o sha3sum.o $(LDLIBS)
sha3fuzz: sha3.c fuzz/sha3fuzz.c
clang -g --std=c99 -fsanitize=fuzzer,address -O0 -I . -o $@ $^
sha3test: sha3.o sha3test.o
$(CC) $(LDFLAGS) -o $@ sha3.o sha3test.o $(LDLIBS)
check: sha3test
./sha3test
clean:
rm -f *.o libsha3.a sha3sum sha3test sha3fuzz
install:
mkdir -p $(DESTDIR)$(PREFIX)/include \
$(DESTDIR)$(PREFIX)/lib \
$(DESTDIR)$(PREFIX)/bin
install sha3.h $(DESTDIR)$(PREFIX)/include
install -m 755 libsha3.a $(DESTDIR)$(PREFIX)/lib
install -m 755 sha3sum $(DESTDIR)$(PREFIX)/bin
uninstall:
rm -f \
$(DESTDIR)$(PREFIX)/include/sha3.h \
$(DESTDIR)$(PREFIX)/lib/libsha3.a \
$(DESTDIR)$(PREFIX)/bin/sha3sum
.PHONY: all check clean install uninstall
================================================
FILE: README.md
================================================
# C implementation of SHA-3 and Keccak with Init/Update/Finalize API
The purpose of this project is:
* provide an API that hashes bytes, not bits
* provide a simple reference implementation of a SHA-3 message digest algorithm, as defined in the [FIPS 202][fips202_standard] standard
* assist developers in the [Ethereum](https://www.ethereum.org/) blockchain ecosystem by providing the Keccak function used there
* implement the hashing API that employs the __IUF__ paradigm (or `Init`, `Update`, `Finalize` style)
* answer the design questions, such as:
* what does the state for IUF look like?
* how small can the state be (224 bytes on a 64-bit system for a unified SHA-3 algorithm)
* what is the incremental cost of adding e.g. SHA3-384 to a SHA3-256 implementation?
The implementation is written in C and uses `uint64_t` types to manage the SHA-3 state. The code will compile and run on 64-bit and 32-bit architectures (`gcc` and `gcc -m32` on `x86_64` were tested).
[fips202_standard]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf "FIPS 202 standard"
## License, prior work
This work is licensed with a standard [MIT license](LICENSE). I appreciate, but do not require, any attribution to this work if you used the code or ideas. I thank you for this in advance.
This is a clean-room implementation of IUF API for SHA3. The `keccakf()` is based on the code from [keccak.noekeon.org](http://keccak.noekeon.org/).
1600-bit message hashing test vectors are [NIST test vectors](http://csrc.nist.gov/groups/ST/toolkit/examples.html).
## Overview of the API
Let's hash 'abc' with SHA3-256 using two methods: single buffer (but using IUF paradigm), and using the IUF API.
sha3_context c;
uint8_t *hash;
Single-buffer hashing:
sha3_Init256(&c);
sha3_Update(&c, "abc", 3);
hash = sha3_Finalize(&c);
// 'hash' points to a buffer inside 'c'
// with the value of SHA3-256
Alternatively, IUF hashing:
sha3_Init256(&c);
sha3_Update(&c, "a", 1);
sha3_Update(&c, "bc", 2);
hash = sha3_Finalize(&c);
// no free for 'c' is needed
The `hash` points to the same `256/8=32` bytes in both cases.
There is also a single-call hashing API:
sha3_HashBuffer(256, SHA3_FLAGS_KECCAK, "abc", 3, out, sizeof(out));
// out contains 256 bits of Keccak256, or less if sizeof(out)<32
## How to use Keccak version
Call `sha3_SetFlags(&c, SHA3_FLAGS_KECCAK)` immediately after `sha3_InitX` or no later than `sha3_Finalize`. This change cannot be undone for the given hash context.
## Building
$ make
See `Makefile` for details. See also below for specific examples.
## Self-tests
$ make test
Keccak-256 tests passed OK
SHA3-256, SHA3-384, SHA3-512 tests passed OK
or
$ make CFLAGS=-m32 LDFLAGS=-m32 test
Keccak-256 tests passed OK
SHA3-256, SHA3-384, SHA3-512 tests passed OK
There is also `sha3sum` test program that takes following parameters:
sha3sum 256|384|512 file_path
or for Keccak version:
sha3sum 256|384|512 -k file_path
### SHA-3 / Linux sha3sum example
$ touch empty.txt
$ gcc -Wall sha3.c sha3sum.c -o sha3sum && ./sha3sum 256 empty.txt
a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a empty.txt
Compare with Linux `sha3sum`:
$ sha3sum -a 256 empty.txt
a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a empty.txt
### Keccak256 / Solidity example
$ echo -n "abc" > abc
$ sha3sum 256 -k abc
4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 abc
This corresponds to the result obtained in Solidity JavaScript test framework.
console.log(web3.utils.sha3('abc'));
// prints 0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45
## API
* the same `sha3_context` object maintains the state for SHA3-256, SHA3-384, or SHA3-512 algorithm;
* the hash algorithm used is determined by how the context was initialized with `sha3_InitX`, e.g. `sha3_Init256`, `sha3_Init384`, or `sha3_Init512` call;
* `sha3_Update` and `sha3_Finalize` are the same for regardless the type of the algorithm (`X`);
* the buffer returned by `sha3_Finalize` will have `X` bits of hash;
* `sha3_InitX` also works as Reset (zeroization) of the hash context; no Free function is needed;
See [`sha3.h`](sha3.h) for the exact interface.
## API fuzzing
$ fuzz/run.sh
The fuzzing script expects clang installed.
## Credits
Thanks to @ralight for moving the test code into separate `sha3test.c`
## Notes
SHA3-224 is not supported, but can easily be added.
The code was written to work with the Microsoft Visual Studio compiler (under `_MSC_VER`), but this build target was not tested.
This project was created to support [SHA3 in OpenPGP](https://tools.ietf.org/html/draft-jivsov-openpgp-sha3) work, but it applies to other protocols and formats, e.g. TLS.
================================================
FILE: fuzz/run.sh
================================================
#!/bin/sh
THIS_SCRIPT=$(readlink -f $0)
P=`dirname $THIS_SCRIPT`
TOP=`dirname $P`
cd $TOP
make sha3fuzz && ./sha3fuzz $P/seeds -max_total_time=100
================================================
FILE: fuzz/seeds/0a5dec3f2ed57a024ccba1041dc85e54e09f74d4
================================================
+
================================================
FILE: fuzz/seeds/19852f1f4d08174b77ba2c88e0d8ec1455348b22
================================================
3
================================================
FILE: fuzz/seeds/2daa36d007df33c974630657696ef4fbc665ca12
================================================
dd
================================================
FILE: fuzz/seeds/3c363836cf4e16666669a25da280a1865c2d2874
================================================
d
================================================
FILE: fuzz/seeds/71853c6197a6a7f222db0f1978c7cb232b87c5ee
================================================
================================================
FILE: fuzz/seeds/98fc3c55ad129219ed5ffa43cd36a83fd6c2248e
================================================
================================================
FILE: fuzz/seeds/a4bf6fc7ed78f9cdc178168a3a60070f3fae68ab
================================================
:
================================================
FILE: fuzz/seeds/a979ef10cc6f6a36df6b8a323307ee3bb2e2db9c
================================================
+
================================================
FILE: fuzz/seeds/b69e21c4d029acf5779df9a7167cb0b3d76b6a91
================================================
vvvvv3
================================================
FILE: fuzz/seeds/c63ae6dd4fc9f9dda66970e827d13f7c73fe841c
================================================
M
================================================
FILE: fuzz/seeds/f45250b51fd7511ea177e87492cfb303b73517b3
================================================
================================================
FILE: fuzz/sha3fuzz.c
================================================
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "sha3.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
sha3_context c;
const void *hash;
uint8_t b;
uint8_t buf[512/8];
unsigned is_keccak;
if( Size < 1 )
return 0;
b = Data[0];
Size --;
Data ++;
is_keccak = b & (1<<2);
switch(b & 3) {
case 0:
sha3_Init256(&c);
break;
case 1:
sha3_Init384(&c);
break;
case 2:
sha3_Init512(&c);
break;
case 3:
if(Size >= 2)
sha3_HashBuffer((unsigned)Data[0] << 1,
Data[1]/*SHA3_FLAGS_KECCAK or NONE*/,
Data + 2, Size-2, buf, sizeof(buf));
return 0;
}
if( is_keccak )
sha3_SetFlags( &c, SHA3_FLAGS_KECCAK );
sha3_Update(&c, Data, Size);
hash = sha3_Finalize(&c);
return 0;
}
================================================
FILE: sha3.c
================================================
/* -------------------------------------------------------------------------
* Works when compiled for either 32-bit or 64-bit targets, optimized for
* 64 bit.
*
* Canonical implementation of Init/Update/Finalize for SHA-3 byte input.
*
* SHA3-256, SHA3-384, SHA-512 are implemented. SHA-224 can easily be added.
*
* Based on code from http://keccak.noekeon.org/ .
*
* I place the code that I wrote into public domain, free to use.
*
* I would appreciate if you give credits to this work if you used it to
* write or test * your code.
*
* Aug 2015. Andrey Jivsov. crypto@brainhub.org
* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "sha3.h"
#define SHA3_ASSERT( x )
#define SHA3_TRACE( format, ...)
#define SHA3_TRACE_BUF(format, buf, l)
/*
* This flag is used to configure "pure" Keccak, as opposed to NIST SHA3.
*/
#define SHA3_USE_KECCAK_FLAG 0x80000000
#define SHA3_CW(x) ((x) & (~SHA3_USE_KECCAK_FLAG))
#if defined(_MSC_VER)
#define SHA3_CONST(x) x
#else
#define SHA3_CONST(x) x##L
#endif
#ifndef SHA3_ROTL64
#define SHA3_ROTL64(x, y) \
(((x) << (y)) | ((x) >> ((sizeof(uint64_t)*8) - (y))))
#endif
static const uint64_t keccakf_rndc[24] = {
SHA3_CONST(0x0000000000000001UL), SHA3_CONST(0x0000000000008082UL),
SHA3_CONST(0x800000000000808aUL), SHA3_CONST(0x8000000080008000UL),
SHA3_CONST(0x000000000000808bUL), SHA3_CONST(0x0000000080000001UL),
SHA3_CONST(0x8000000080008081UL), SHA3_CONST(0x8000000000008009UL),
SHA3_CONST(0x000000000000008aUL), SHA3_CONST(0x0000000000000088UL),
SHA3_CONST(0x0000000080008009UL), SHA3_CONST(0x000000008000000aUL),
SHA3_CONST(0x000000008000808bUL), SHA3_CONST(0x800000000000008bUL),
SHA3_CONST(0x8000000000008089UL), SHA3_CONST(0x8000000000008003UL),
SHA3_CONST(0x8000000000008002UL), SHA3_CONST(0x8000000000000080UL),
SHA3_CONST(0x000000000000800aUL), SHA3_CONST(0x800000008000000aUL),
SHA3_CONST(0x8000000080008081UL), SHA3_CONST(0x8000000000008080UL),
SHA3_CONST(0x0000000080000001UL), SHA3_CONST(0x8000000080008008UL)
};
static const unsigned keccakf_rotc[24] = {
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62,
18, 39, 61, 20, 44
};
static const unsigned keccakf_piln[24] = {
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20,
14, 22, 9, 6, 1
};
/* generally called after SHA3_KECCAK_SPONGE_WORDS-ctx->capacityWords words
* are XORed into the state s
*/
static void
keccakf(uint64_t s[25])
{
int i, j, round;
uint64_t t, bc[5];
#define KECCAK_ROUNDS 24
for(round = 0; round < KECCAK_ROUNDS; round++) {
/* Theta */
for(i = 0; i < 5; i++)
bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
for(i = 0; i < 5; i++) {
t = bc[(i + 4) % 5] ^ SHA3_ROTL64(bc[(i + 1) % 5], 1);
for(j = 0; j < 25; j += 5)
s[j + i] ^= t;
}
/* Rho Pi */
t = s[1];
for(i = 0; i < 24; i++) {
j = keccakf_piln[i];
bc[0] = s[j];
s[j] = SHA3_ROTL64(t, keccakf_rotc[i]);
t = bc[0];
}
/* Chi */
for(j = 0; j < 25; j += 5) {
for(i = 0; i < 5; i++)
bc[i] = s[j + i];
for(i = 0; i < 5; i++)
s[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
}
/* Iota */
s[0] ^= keccakf_rndc[round];
}
}
/* *************************** Public Inteface ************************ */
/* For Init or Reset call these: */
sha3_return_t
sha3_Init(void *priv, unsigned bitSize) {
sha3_context *ctx = (sha3_context *) priv;
if( bitSize != 256 && bitSize != 384 && bitSize != 512 )
return SHA3_RETURN_BAD_PARAMS;
memset(ctx, 0, sizeof(*ctx));
ctx->capacityWords = 2 * bitSize / (8 * sizeof(uint64_t));
return SHA3_RETURN_OK;
}
void
sha3_Init256(void *priv)
{
sha3_Init(priv, 256);
}
void
sha3_Init384(void *priv)
{
sha3_Init(priv, 384);
}
void
sha3_Init512(void *priv)
{
sha3_Init(priv, 512);
}
enum SHA3_FLAGS
sha3_SetFlags(void *priv, enum SHA3_FLAGS flags)
{
sha3_context *ctx = (sha3_context *) priv;
flags &= SHA3_FLAGS_KECCAK;
ctx->capacityWords |= (flags == SHA3_FLAGS_KECCAK ? SHA3_USE_KECCAK_FLAG : 0);
return flags;
}
void
sha3_Update(void *priv, void const *bufIn, size_t len)
{
sha3_context *ctx = (sha3_context *) priv;
/* 0...7 -- how much is needed to have a word */
unsigned old_tail = (8 - ctx->byteIndex) & 7;
size_t words;
unsigned tail;
size_t i;
const uint8_t *buf = bufIn;
SHA3_TRACE_BUF("called to update with:", buf, len);
SHA3_ASSERT(ctx->byteIndex < 8);
SHA3_ASSERT(ctx->wordIndex < sizeof(ctx->u.s) / sizeof(ctx->u.s[0]));
if(len < old_tail) { /* have no complete word or haven't started
* the word yet */
SHA3_TRACE("because %d<%d, store it and return", (unsigned)len,
(unsigned)old_tail);
/* endian-independent code follows: */
while (len--)
ctx->saved |= (uint64_t) (*(buf++)) << ((ctx->byteIndex++) * 8);
SHA3_ASSERT(ctx->byteIndex < 8);
return;
}
if(old_tail) { /* will have one word to process */
SHA3_TRACE("completing one word with %d bytes", (unsigned)old_tail);
/* endian-independent code follows: */
len -= old_tail;
while (old_tail--)
ctx->saved |= (uint64_t) (*(buf++)) << ((ctx->byteIndex++) * 8);
/* now ready to add saved to the sponge */
ctx->u.s[ctx->wordIndex] ^= ctx->saved;
SHA3_ASSERT(ctx->byteIndex == 8);
ctx->byteIndex = 0;
ctx->saved = 0;
if(++ctx->wordIndex ==
(SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx->capacityWords))) {
keccakf(ctx->u.s);
ctx->wordIndex = 0;
}
}
/* now work in full words directly from input */
SHA3_ASSERT(ctx->byteIndex == 0);
words = len / sizeof(uint64_t);
tail = len - words * sizeof(uint64_t);
SHA3_TRACE("have %d full words to process", (unsigned)words);
for(i = 0; i < words; i++, buf += sizeof(uint64_t)) {
const uint64_t t = (uint64_t) (buf[0]) |
((uint64_t) (buf[1]) << 8 * 1) |
((uint64_t) (buf[2]) << 8 * 2) |
((uint64_t) (buf[3]) << 8 * 3) |
((uint64_t) (buf[4]) << 8 * 4) |
((uint64_t) (buf[5]) << 8 * 5) |
((uint64_t) (buf[6]) << 8 * 6) |
((uint64_t) (buf[7]) << 8 * 7);
#if defined(__x86_64__ ) || defined(__i386__)
SHA3_ASSERT(memcmp(&t, buf, 8) == 0);
#endif
ctx->u.s[ctx->wordIndex] ^= t;
if(++ctx->wordIndex ==
(SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx->capacityWords))) {
keccakf(ctx->u.s);
ctx->wordIndex = 0;
}
}
SHA3_TRACE("have %d bytes left to process, save them", (unsigned)tail);
/* finally, save the partial word */
SHA3_ASSERT(ctx->byteIndex == 0 && tail < 8);
while (tail--) {
SHA3_TRACE("Store byte %02x '%c'", *buf, *buf);
ctx->saved |= (uint64_t) (*(buf++)) << ((ctx->byteIndex++) * 8);
}
SHA3_ASSERT(ctx->byteIndex < 8);
SHA3_TRACE("Have saved=0x%016" PRIx64 " at the end", ctx->saved);
}
/* This is simply the 'update' with the padding block.
* The padding block is 0x01 || 0x00* || 0x80. First 0x01 and last 0x80
* bytes are always present, but they can be the same byte.
*/
void const *
sha3_Finalize(void *priv)
{
sha3_context *ctx = (sha3_context *) priv;
SHA3_TRACE("called with %d bytes in the buffer", ctx->byteIndex);
/* Append 2-bit suffix 01, per SHA-3 spec. Instead of 1 for padding we
* use 1<<2 below. The 0x02 below corresponds to the suffix 01.
* Overall, we feed 0, then 1, and finally 1 to start padding. Without
* M || 01, we would simply use 1 to start padding. */
uint64_t t;
if( ctx->capacityWords & SHA3_USE_KECCAK_FLAG ) {
/* Keccak version */
t = (uint64_t)(((uint64_t) 1) << (ctx->byteIndex * 8));
}
else {
/* SHA3 version */
t = (uint64_t)(((uint64_t)(0x02 | (1 << 2))) << ((ctx->byteIndex) * 8));
}
ctx->u.s[ctx->wordIndex] ^= ctx->saved ^ t;
ctx->u.s[SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx->capacityWords) - 1] ^=
SHA3_CONST(0x8000000000000000UL);
keccakf(ctx->u.s);
/* Return first bytes of the ctx->s. This conversion is not needed for
* little-endian platforms e.g. wrap with #if !defined(__BYTE_ORDER__)
* || !defined(__ORDER_LITTLE_ENDIAN__) || __BYTE_ORDER__!=__ORDER_LITTLE_ENDIAN__
* ... the conversion below ...
* #endif */
{
unsigned i;
for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
const unsigned t1 = (uint32_t) ctx->u.s[i];
const unsigned t2 = (uint32_t) ((ctx->u.s[i] >> 16) >> 16);
ctx->u.sb[i * 8 + 0] = (uint8_t) (t1);
ctx->u.sb[i * 8 + 1] = (uint8_t) (t1 >> 8);
ctx->u.sb[i * 8 + 2] = (uint8_t) (t1 >> 16);
ctx->u.sb[i * 8 + 3] = (uint8_t) (t1 >> 24);
ctx->u.sb[i * 8 + 4] = (uint8_t) (t2);
ctx->u.sb[i * 8 + 5] = (uint8_t) (t2 >> 8);
ctx->u.sb[i * 8 + 6] = (uint8_t) (t2 >> 16);
ctx->u.sb[i * 8 + 7] = (uint8_t) (t2 >> 24);
}
}
SHA3_TRACE_BUF("Hash: (first 32 bytes)", ctx->u.sb, 256 / 8);
return (ctx->u.sb);
}
sha3_return_t sha3_HashBuffer( unsigned bitSize, enum SHA3_FLAGS flags, const void *in, unsigned inBytes, void *out, unsigned outBytes ) {
sha3_return_t err;
sha3_context c;
err = sha3_Init(&c, bitSize);
if( err != SHA3_RETURN_OK )
return err;
if( sha3_SetFlags(&c, flags) != flags ) {
return SHA3_RETURN_BAD_PARAMS;
}
sha3_Update(&c, in, inBytes);
const void *h = sha3_Finalize(&c);
if(outBytes > bitSize/8)
outBytes = bitSize/8;
memcpy(out, h, outBytes);
return SHA3_RETURN_OK;
}
================================================
FILE: sha3.h
================================================
#ifndef SHA3_H
#define SHA3_H
#include <stdint.h>
/* -------------------------------------------------------------------------
* Works when compiled for either 32-bit or 64-bit targets, optimized for
* 64 bit.
*
* Canonical implementation of Init/Update/Finalize for SHA-3 byte input.
*
* SHA3-256, SHA3-384, SHA-512 are implemented. SHA-224 can easily be added.
*
* Based on code from http://keccak.noekeon.org/ .
*
* I place the code that I wrote into public domain, free to use.
*
* I would appreciate if you give credits to this work if you used it to
* write or test * your code.
*
* Aug 2015. Andrey Jivsov. crypto@brainhub.org
* ---------------------------------------------------------------------- */
/* 'Words' here refers to uint64_t */
#define SHA3_KECCAK_SPONGE_WORDS \
(((1600)/8/*bits to byte*/)/sizeof(uint64_t))
typedef struct sha3_context_ {
uint64_t saved; /* the portion of the input message that we
* didn't consume yet */
union { /* Keccak's state */
uint64_t s[SHA3_KECCAK_SPONGE_WORDS];
uint8_t sb[SHA3_KECCAK_SPONGE_WORDS * 8];
} u;
unsigned byteIndex; /* 0..7--the next byte after the set one
* (starts from 0; 0--none are buffered) */
unsigned wordIndex; /* 0..24--the next word to integrate input
* (starts from 0) */
unsigned capacityWords; /* the double size of the hash output in
* words (e.g. 16 for Keccak 512) */
} sha3_context;
enum SHA3_FLAGS {
SHA3_FLAGS_NONE=0,
SHA3_FLAGS_KECCAK=1
};
enum SHA3_RETURN {
SHA3_RETURN_OK=0,
SHA3_RETURN_BAD_PARAMS=1
};
typedef enum SHA3_RETURN sha3_return_t;
/* For Init or Reset call these: */
sha3_return_t sha3_Init(void *priv, unsigned bitSize);
void sha3_Init256(void *priv);
void sha3_Init384(void *priv);
void sha3_Init512(void *priv);
enum SHA3_FLAGS sha3_SetFlags(void *priv, enum SHA3_FLAGS);
void sha3_Update(void *priv, void const *bufIn, size_t len);
void const *sha3_Finalize(void *priv);
/* Single-call hashing */
sha3_return_t sha3_HashBuffer(
unsigned bitSize, /* 256, 384, 512 */
enum SHA3_FLAGS flags, /* SHA3_FLAGS_NONE or SHA3_FLAGS_KECCAK */
const void *in, unsigned inBytes,
void *out, unsigned outBytes ); /* up to bitSize/8; truncation OK */
#endif
================================================
FILE: sha3sum.c
================================================
/* -------------------------------------------------------------------------
* Run SHA-3 (NIST FIPS 202) on the given file.
*
* Call as
*
* sha3sum 256|384|512 file_path
*
* See sha3.c for additional details.
*
* Jun 2018. Andrey Jivsov. crypto@brainhub.org
* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/mman.h>
#include "sha3.h"
static void help(const char *argv0) {
printf("To call: %s 256|384|512 [-k] file_path.\n", argv0);
}
static void byte_to_hex(uint8_t b, char s[23]) {
unsigned i=1;
s[0] = s[1] = '0';
s[2] = '\0';
while(b) {
unsigned t = b & 0x0f;
if( t < 10 ) {
s[i] = '0' + t;
} else {
s[i] = 'a' + t - 10;
}
i--;
b >>= 4;
}
}
int main(int argc, char *argv[])
{
sha3_context c;
const uint8_t *hash;
unsigned image_size;
const char *file_path;
int fd;
struct stat st;
void *p;
unsigned i;
unsigned use_keccak = 0;
if( argc != 3 && argc != 4 ) {
help(argv[0]);
return 1;
}
image_size = atoi(argv[1]);
switch( image_size ) {
case 256:
case 384:
case 512:
break;
default:
help(argv[0]);
return 1;
}
file_path = argv[2];
if( argc == 4 && file_path[0] == '-' && file_path[1] == 'k' ) {
use_keccak = 1;
file_path = argv[3];
}
if( access(file_path, R_OK)!=0 ) {
printf("Cannot read file '%s'", file_path);
return 2;
}
fd = open(file_path, O_RDONLY);
if( fd == -1 ) {
printf("Cannot open file '%s' for reading", file_path);
return 2;
}
i = fstat(fd, &st);
if( i ) {
close(fd);
printf("Cannot determine the size of file '%s'", file_path);
return 2;
}
p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
if( p==NULL ) {
printf("Cannot memory-map file '%s'", file_path);
return 2;
}
switch(image_size) {
case 256:
sha3_Init256(&c);
break;
case 384:
sha3_Init384(&c);
break;
case 512:
sha3_Init512(&c);
break;
}
if( use_keccak ) {
enum SHA3_FLAGS flags2 = sha3_SetFlags(&c, SHA3_FLAGS_KECCAK);
if( flags2 != SHA3_FLAGS_KECCAK ) {
printf("Failed to set Keccak mode");
return 2;
}
}
sha3_Update(&c, p, st.st_size);
hash = sha3_Finalize(&c);
munmap(p, st.st_size);
for(i=0; i<image_size/8; i++) {
char s[3];
byte_to_hex(hash[i],s);
printf("%s", s);
}
printf(" %s\n", file_path);
return 0;
}
================================================
FILE: sha3test.c
================================================
/* -------------------------------------------------------------------------
* Works when compiled for either 32-bit or 64-bit targets, optimized for
* 64 bit.
*
* Canonical implementation of Init/Update/Finalize for SHA-3 byte input.
*
* SHA3-256, SHA3-384, SHA-512 are implemented. SHA-224 can easily be added.
*
* Based on code from http://keccak.noekeon.org/ .
*
* I place the code that I wrote into public domain, free to use.
*
* I would appreciate if you give credits to this work if you used it to
* write or test * your code.
*
* Aug 2015. Andrey Jivsov. crypto@brainhub.org
* ---------------------------------------------------------------------- */
/* *************************** Self Tests ************************ */
/*
* There are two set of mutually exclusive tests, based on SHA3_USE_KECCAK,
* which is undefined in the production version.
*
* Known answer tests are from NIST SHA3 test vectors at
* http://csrc.nist.gov/groups/ST/toolkit/examples.html
*
* SHA3-256:
* http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA3-256_Msg0.pdf
* http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA3-256_1600.pdf
* SHA3-384:
* http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA3-384_1600.pdf
* SHA3-512:
* http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA3-512_1600.pdf
*
* These are refered to as [FIPS 202] tests.
*
* -----
*
* A few Keccak algorithm tests (when M and not M||01 is hashed) are
* added here. These are from http://keccak.noekeon.org/KeccakKAT-3.zip,
* ShortMsgKAT_256.txt for sizes even to 8. There is also one test for
* ExtremelyLongMsgKAT_256.txt.
*
* These will work with this code when SHA3_USE_KECCAK converts Finalize
* to use "pure" Keccak algorithm.
*
*
* These are referred to as [Keccak] test.
*
* -----
*
* In one case the input from [Keccak] test was used to test SHA3
* implementation. In this case the calculated hash was compared with
* the output of the sha3sum on Fedora Core 20 (which is Perl's based).
*
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "sha3.h"
int
main()
{
uint8_t buf[200];
sha3_context c;
const void *hash;
unsigned i;
const uint8_t c1 = 0xa3;
/* [FIPS 202] KAT follow */
static const uint8_t sha3_256_empty[256 / 8] = {
0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66,
0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62,
0xf5, 0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa,
0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a
};
static const uint8_t sha3_256_0xa3_200_times[256 / 8] = {
0x79, 0xf3, 0x8a, 0xde, 0xc5, 0xc2, 0x03, 0x07,
0xa9, 0x8e, 0xf7, 0x6e, 0x83, 0x24, 0xaf, 0xbf,
0xd4, 0x6c, 0xfd, 0x81, 0xb2, 0x2e, 0x39, 0x73,
0xc6, 0x5f, 0xa1, 0xbd, 0x9d, 0xe3, 0x17, 0x87
};
static const uint8_t sha3_384_0xa3_200_times[384 / 8] = {
0x18, 0x81, 0xde, 0x2c, 0xa7, 0xe4, 0x1e, 0xf9,
0x5d, 0xc4, 0x73, 0x2b, 0x8f, 0x5f, 0x00, 0x2b,
0x18, 0x9c, 0xc1, 0xe4, 0x2b, 0x74, 0x16, 0x8e,
0xd1, 0x73, 0x26, 0x49, 0xce, 0x1d, 0xbc, 0xdd,
0x76, 0x19, 0x7a, 0x31, 0xfd, 0x55, 0xee, 0x98,
0x9f, 0x2d, 0x70, 0x50, 0xdd, 0x47, 0x3e, 0x8f
};
static const uint8_t sha3_512_0xa3_200_times[512 / 8] = {
0xe7, 0x6d, 0xfa, 0xd2, 0x20, 0x84, 0xa8, 0xb1,
0x46, 0x7f, 0xcf, 0x2f, 0xfa, 0x58, 0x36, 0x1b,
0xec, 0x76, 0x28, 0xed, 0xf5, 0xf3, 0xfd, 0xc0,
0xe4, 0x80, 0x5d, 0xc4, 0x8c, 0xae, 0xec, 0xa8,
0x1b, 0x7c, 0x13, 0xc3, 0x0a, 0xdf, 0x52, 0xa3,
0x65, 0x95, 0x84, 0x73, 0x9a, 0x2d, 0xf4, 0x6b,
0xe5, 0x89, 0xc5, 0x1c, 0xa1, 0xa4, 0xa8, 0x41,
0x6d, 0xf6, 0x54, 0x5a, 0x1c, 0xe8, 0xba, 0x00
};
/* ---- "pure" Keccak algorithm begins; from [Keccak] ----- */
sha3_HashBuffer(256, SHA3_FLAGS_KECCAK, "abc", 3, buf, sizeof(buf));
if(memcmp(buf, "\x4e\x03\x65\x7a\xea\x45\xa9\x4f"
"\xc7\xd4\x7b\xa8\x26\xc8\xd6\x67"
"\xc0\xd1\xe6\xe3\x3a\x64\xa0\x36"
"\xec\x44\xf5\x8f\xa1\x2d\x6c\x45", 256 / 8) != 0) {
printf("SHA3-256(abc) "
"doesn't match known answer (single buffer)\n");
return 10;
}
sha3_Init256(&c);
sha3_SetFlags(&c, SHA3_FLAGS_KECCAK);
sha3_Update(&c, "\xcc", 1);
hash = sha3_Finalize(&c);
if(memcmp(hash, "\xee\xad\x6d\xbf\xc7\x34\x0a\x56"
"\xca\xed\xc0\x44\x69\x6a\x16\x88"
"\x70\x54\x9a\x6a\x7f\x6f\x56\x96"
"\x1e\x84\xa5\x4b\xd9\x97\x0b\x8a", 256 / 8) != 0) {
printf("SHA3-256(cc) "
"doesn't match known answer (single buffer)\n");
return 11;
}
sha3_Init256(&c);
sha3_SetFlags(&c, SHA3_FLAGS_KECCAK);
sha3_Update(&c, "\x41\xfb", 2);
hash = sha3_Finalize(&c);
if(memcmp(hash, "\xa8\xea\xce\xda\x4d\x47\xb3\x28"
"\x1a\x79\x5a\xd9\xe1\xea\x21\x22"
"\xb4\x07\xba\xf9\xaa\xbc\xb9\xe1"
"\x8b\x57\x17\xb7\x87\x35\x37\xd2", 256 / 8) != 0) {
printf("SHA3-256(41fb) "
"doesn't match known answer (single buffer)\n");
return 12;
}
sha3_Init256(&c);
sha3_SetFlags(&c, SHA3_FLAGS_KECCAK);
sha3_Update(&c,
"\x52\xa6\x08\xab\x21\xcc\xdd\x8a"
"\x44\x57\xa5\x7e\xde\x78\x21\x76", 128 / 8);
hash = sha3_Finalize(&c);
if(memcmp(hash, "\x0e\x32\xde\xfa\x20\x71\xf0\xb5"
"\xac\x0e\x6a\x10\x8b\x84\x2e\xd0"
"\xf1\xd3\x24\x97\x12\xf5\x8e\xe0"
"\xdd\xf9\x56\xfe\x33\x2a\x5f\x95", 256 / 8) != 0) {
printf("SHA3-256(52a6...76) "
"doesn't match known answer (single buffer)\n");
return 13;
}
sha3_Init256(&c);
sha3_SetFlags(&c, SHA3_FLAGS_KECCAK);
sha3_Update(&c,
"\x43\x3c\x53\x03\x13\x16\x24\xc0"
"\x02\x1d\x86\x8a\x30\x82\x54\x75"
"\xe8\xd0\xbd\x30\x52\xa0\x22\x18"
"\x03\x98\xf4\xca\x44\x23\xb9\x82"
"\x14\xb6\xbe\xaa\xc2\x1c\x88\x07"
"\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0"
"\x92\xcc\x1b\x06\xce\xdf\x32\x24"
"\xd5\xed\x1e\xc2\x97\x84\x44\x4f"
"\x22\xe0\x8a\x55\xaa\x58\x54\x2b"
"\x52\x4b\x02\xcd\x3d\x5d\x5f\x69"
"\x07\xaf\xe7\x1c\x5d\x74\x62\x22"
"\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" "\x6d\xcb\xb4\xce", 800 / 8);
hash = sha3_Finalize(&c);
if(memcmp(hash, "\xce\x87\xa5\x17\x3b\xff\xd9\x23"
"\x99\x22\x16\x58\xf8\x01\xd4\x5c"
"\x29\x4d\x90\x06\xee\x9f\x3f\x9d"
"\x41\x9c\x8d\x42\x77\x48\xdc\x41", 256 / 8) != 0) {
printf("SHA3-256(433C...CE) "
"doesn't match known answer (single buffer)\n");
return 14;
}
/* SHA3-256 byte-by-byte: 16777216 steps. ExtremelyLongMsgKAT_256
* [Keccak] */
i = 16777216;
sha3_Init256(&c);
sha3_SetFlags(&c, SHA3_FLAGS_KECCAK);
while (i--) {
sha3_Update(&c,
"abcdefghbcdefghicdefghijdefghijk"
"efghijklfghijklmghijklmnhijklmno", 64);
}
hash = sha3_Finalize(&c);
if(memcmp(hash, "\x5f\x31\x3c\x39\x96\x3d\xcf\x79"
"\x2b\x54\x70\xd4\xad\xe9\xf3\xa3"
"\x56\xa3\xe4\x02\x17\x48\x69\x0a"
"\x95\x83\x72\xe2\xb0\x6f\x82\xa4", 256 / 8) != 0) {
printf("SHA3-256( abcdefgh...[16777216 times] ) "
"doesn't match known answer\n");
return 15;
}
printf("Keccak-256 tests passed OK\n");
/* ----- SHA3 testing begins ----- */
/* SHA-256 on an empty buffer */
sha3_Init256(&c);
hash = sha3_Finalize(&c);
if(memcmp(sha3_256_empty, hash, sizeof(sha3_256_empty)) != 0) {
printf("SHA3-256() doesn't match known answer\n");
return 1;
}
sha3_HashBuffer(256, SHA3_FLAGS_NONE, "abc", 3, buf, sizeof(buf));
if(memcmp(buf,
"\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2"
"\x04\x5c\x17\x2d\x6b\xd3\x90\xbd"
"\x85\x5f\x08\x6e\x3e\x9d\x52\x5b"
"\x46\xbf\xe2\x45\x11\x43\x15\x32", 256 / 8) != 0) {
printf("SHA3-256(abc) "
"doesn't match known answer (single buffer)\n");
return 10;
}
memset(buf, c1, sizeof(buf)); /* set to value c1 */
/* SHA3-256 as a single buffer. [FIPS 202] */
sha3_Init256(&c);
sha3_Update(&c, buf, sizeof(buf));
hash = sha3_Finalize(&c);
if(memcmp(sha3_256_0xa3_200_times, hash,
sizeof(sha3_256_0xa3_200_times)) != 0) {
printf("SHA3-256( 0xa3 ... [200 times] ) "
"doesn't match known answer (1 buffer)\n");
return 1;
}
/* SHA3-256 in two steps. [FIPS 202] */
sha3_Init256(&c);
sha3_Update(&c, buf, sizeof(buf) / 2);
sha3_Update(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2);
hash = sha3_Finalize(&c);
if(memcmp(sha3_256_0xa3_200_times, hash,
sizeof(sha3_256_0xa3_200_times)) != 0) {
printf("SHA3-256( 0xa3 ... [200 times] ) "
"doesn't match known answer (2 steps)\n");
return 2;
}
/* SHA3-256 byte-by-byte: 200 steps. [FIPS 202] */
i = 200;
sha3_Init256(&c);
while (i--) {
sha3_Update(&c, &c1, 1);
}
hash = sha3_Finalize(&c);
if(memcmp(sha3_256_0xa3_200_times, hash,
sizeof(sha3_256_0xa3_200_times)) != 0) {
printf("SHA3-256( 0xa3 ... [200 times] ) "
"doesn't match known answer (200 steps)\n");
return 3;
}
/* SHA3-256 byte-by-byte: 135 bytes. Input from [Keccak]. Output
* matched with sha3sum. */
sha3_Init256(&c);
sha3_Update(&c,
"\xb7\x71\xd5\xce\xf5\xd1\xa4\x1a"
"\x93\xd1\x56\x43\xd7\x18\x1d\x2a"
"\x2e\xf0\xa8\xe8\x4d\x91\x81\x2f"
"\x20\xed\x21\xf1\x47\xbe\xf7\x32"
"\xbf\x3a\x60\xef\x40\x67\xc3\x73"
"\x4b\x85\xbc\x8c\xd4\x71\x78\x0f"
"\x10\xdc\x9e\x82\x91\xb5\x83\x39"
"\xa6\x77\xb9\x60\x21\x8f\x71\xe7"
"\x93\xf2\x79\x7a\xea\x34\x94\x06"
"\x51\x28\x29\x06\x5d\x37\xbb\x55"
"\xea\x79\x6f\xa4\xf5\x6f\xd8\x89"
"\x6b\x49\xb2\xcd\x19\xb4\x32\x15"
"\xad\x96\x7c\x71\x2b\x24\xe5\x03"
"\x2d\x06\x52\x32\xe0\x2c\x12\x74"
"\x09\xd2\xed\x41\x46\xb9\xd7\x5d"
"\x76\x3d\x52\xdb\x98\xd9\x49\xd3"
"\xb0\xfe\xd6\xa8\x05\x2f\xbb", 1080 / 8);
hash = sha3_Finalize(&c);
if(memcmp(hash, "\xa1\x9e\xee\x92\xbb\x20\x97\xb6"
"\x4e\x82\x3d\x59\x77\x98\xaa\x18"
"\xbe\x9b\x7c\x73\x6b\x80\x59\xab"
"\xfd\x67\x79\xac\x35\xac\x81\xb5", 256 / 8) != 0) {
printf("SHA3-256( b771 ... ) doesn't match the known answer\n");
return 4;
}
/* SHA3-384 as a single buffer. [FIPS 202] */
sha3_Init384(&c);
sha3_Update(&c, buf, sizeof(buf));
hash = sha3_Finalize(&c);
if(memcmp(sha3_384_0xa3_200_times, hash,
sizeof(sha3_384_0xa3_200_times)) != 0) {
printf("SHA3-384( 0xa3 ... [200 times] ) "
"doesn't match known answer (1 buffer)\n");
return 5;
}
/* SHA3-384 in two steps. [FIPS 202] */
sha3_Init384(&c);
sha3_Update(&c, buf, sizeof(buf) / 2);
sha3_Update(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2);
hash = sha3_Finalize(&c);
if(memcmp(sha3_384_0xa3_200_times, hash,
sizeof(sha3_384_0xa3_200_times)) != 0) {
printf("SHA3-384( 0xa3 ... [200 times] ) "
"doesn't match known answer (2 steps)\n");
return 6;
}
/* SHA3-384 byte-by-byte: 200 steps. [FIPS 202] */
i = 200;
sha3_Init384(&c);
while (i--) {
sha3_Update(&c, &c1, 1);
}
hash = sha3_Finalize(&c);
if(memcmp(sha3_384_0xa3_200_times, hash,
sizeof(sha3_384_0xa3_200_times)) != 0) {
printf("SHA3-384( 0xa3 ... [200 times] ) "
"doesn't match known answer (200 steps)\n");
return 7;
}
/* SHA3-512 as a single buffer. [FIPS 202] */
sha3_Init512(&c);
sha3_Update(&c, buf, sizeof(buf));
hash = sha3_Finalize(&c);
if(memcmp(sha3_512_0xa3_200_times, hash,
sizeof(sha3_512_0xa3_200_times)) != 0) {
printf("SHA3-512( 0xa3 ... [200 times] ) "
"doesn't match known answer (1 buffer)\n");
return 8;
}
/* SHA3-512 in two steps. [FIPS 202] */
sha3_Init512(&c);
sha3_Update(&c, buf, sizeof(buf) / 2);
sha3_Update(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2);
hash = sha3_Finalize(&c);
if(memcmp(sha3_512_0xa3_200_times, hash,
sizeof(sha3_512_0xa3_200_times)) != 0) {
printf("SHA3-512( 0xa3 ... [200 times] ) "
"doesn't match known answer (2 steps)\n");
return 9;
}
/* SHA3-512 byte-by-byte: 200 steps. [FIPS 202] */
i = 200;
sha3_Init512(&c);
while (i--) {
sha3_Update(&c, &c1, 1);
}
hash = sha3_Finalize(&c);
if(memcmp(sha3_512_0xa3_200_times, hash,
sizeof(sha3_512_0xa3_200_times)) != 0) {
printf("SHA3-512( 0xa3 ... [200 times] ) "
"doesn't match known answer (200 steps)\n");
return 10;
}
printf("SHA3-256, SHA3-384, SHA3-512 tests passed OK\n");
return 0;
}
gitextract_5tj02dc8/ ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── fuzz/ │ ├── run.sh │ ├── seeds/ │ │ ├── 01ec548baccbe69625b54206ef7100f5ed03719f │ │ ├── 0a5dec3f2ed57a024ccba1041dc85e54e09f74d4 │ │ ├── 0bfb1ece6a9278c2fc475bb8901308f8a9cafbb4 │ │ ├── 13817dae42cce3b01da9435b035a8b8ea94d2df8 │ │ ├── 1511dc059ee7a55d9ac4d4a91b5bf8929f846d0f │ │ ├── 19852f1f4d08174b77ba2c88e0d8ec1455348b22 │ │ ├── 1f8cc307c05de3bf9d98f90dcfa11583d187d15a │ │ ├── 27c554131c35630341a2b84ecaab53072fbfe6ca │ │ ├── 28b9d530ca4a5765c6def1393d1252acb9f3de90 │ │ ├── 2daa36d007df33c974630657696ef4fbc665ca12 │ │ ├── 30f28e65f01f0af35a4b1b8dbc20dafa5cfb5584 │ │ ├── 355a748ff0b67ea9fa417f1ed773a3641ebd4929 │ │ ├── 363323cbf90a34023130dbba0777f6ddd3063d4f │ │ ├── 3c363836cf4e16666669a25da280a1865c2d2874 │ │ ├── 3d838f2ff09a1f5f0405fc46b63127f2ae00032e │ │ ├── 4c767fec38e38bc45cbe9f4c97b298944183ac15 │ │ ├── 520b1aab7fdbbdfaa160e777878116a119ff3200 │ │ ├── 5d7ecbb52e7818d4d2d5c68ebd26dd3b5ad67cc3 │ │ ├── 5e47ec79910a8df76747862af0aec850d7b3f29a │ │ ├── 6f7ca473e2aee8204381b00777801535151c58bd │ │ ├── 71853c6197a6a7f222db0f1978c7cb232b87c5ee │ │ ├── 744dd71fe66027d943e84151fda2555e9a67c0cb │ │ ├── 759e0d4e0d765166c3b1aa9e66ece0d146cb68e6 │ │ ├── 819c227c2780b372be25bbd8028fd806ab0cba35 │ │ ├── 8519208c0cb8cbb2c2731dae901752df10c2ab7e │ │ ├── 885f051ffcf79b45bee97b7b52d7f9087533f192 │ │ ├── 98fc3c55ad129219ed5ffa43cd36a83fd6c2248e │ │ ├── a03822c4ce67e2d8d243fc3b0f0d96338b6555d2 │ │ ├── a4bf6fc7ed78f9cdc178168a3a60070f3fae68ab │ │ ├── a60cbf05a3f86e96123bc6a87803f3fe0de1a272 │ │ ├── a979ef10cc6f6a36df6b8a323307ee3bb2e2db9c │ │ ├── b69e21c4d029acf5779df9a7167cb0b3d76b6a91 │ │ ├── b6dd110c53d944c083ae6e45383b73310ef11856 │ │ ├── bab01b936511366f8048d15679eeb875db818a1f │ │ ├── c63ae6dd4fc9f9dda66970e827d13f7c73fe841c │ │ ├── e0bb4ab56fc584ad6992e3b4de55e96d9f626b25 │ │ ├── e9c3d0af3f6d6b0897bb52bd597ecbee5559ec34 │ │ ├── f45250b51fd7511ea177e87492cfb303b73517b3 │ │ ├── f5424addd46d466b132717d8f9cf0dc2d7bbc5eb │ │ ├── f5c5efe3024d0f2e32d53036cd1954b99dff03d8 │ │ ├── f6183b6a7bbe75583b8061d8438db6f9ed47fba3 │ │ └── f6c3c3c3fc3d562e27461eda971ba56df05c22fd │ └── sha3fuzz.c ├── sha3.c ├── sha3.h ├── sha3sum.c └── sha3test.c
SYMBOL INDEX (20 symbols across 5 files)
FILE: fuzz/sha3fuzz.c
function LLVMFuzzerTestOneInput (line 7) | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
FILE: sha3.c
function keccakf (line 75) | static void
function sha3_return_t (line 119) | sha3_return_t
function sha3_Init256 (line 129) | void
function sha3_Init384 (line 135) | void
function sha3_Init512 (line 141) | void
function sha3_SetFlags (line 147) | enum SHA3_FLAGS
function sha3_Update (line 157) | void
function sha3_return_t (line 306) | sha3_return_t sha3_HashBuffer( unsigned bitSize, enum SHA3_FLAGS flags, ...
FILE: sha3.h
type sha3_context (line 27) | typedef struct sha3_context_ {
type SHA3_FLAGS (line 42) | enum SHA3_FLAGS {
type SHA3_RETURN (line 47) | enum SHA3_RETURN {
type sha3_return_t (line 51) | typedef enum SHA3_RETURN sha3_return_t;
type SHA3_FLAGS (line 60) | enum SHA3_FLAGS
type SHA3_FLAGS (line 60) | enum SHA3_FLAGS
type SHA3_FLAGS (line 69) | enum SHA3_FLAGS
FILE: sha3sum.c
function help (line 27) | static void help(const char *argv0) {
function byte_to_hex (line 31) | static void byte_to_hex(uint8_t b, char s[23]) {
function main (line 47) | int main(int argc, char *argv[])
FILE: sha3test.c
function main (line 65) | int
Condensed preview — 52 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (40K chars).
[
{
"path": ".gitignore",
"chars": 29,
"preview": "/*.o\n/*.a\n/sha3sum\n/sha3test\n"
},
{
"path": "LICENSE",
"chars": 1065,
"preview": "MIT License\n\nCopyright (c) 2020 brainhub\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
},
{
"path": "Makefile",
"chars": 991,
"preview": ".POSIX:\nCC = c99\nCFLAGS = -std=c99 -Wall -Wextra -Wpedantic -O2 -g\nLDFLAGS =\nLDLIBS =\nPREFIX = /usr/local\n\nall: libsha3."
},
{
"path": "README.md",
"chars": 4871,
"preview": "# C implementation of SHA-3 and Keccak with Init/Update/Finalize API\n\nThe purpose of this project is:\n\n* provide an API "
},
{
"path": "fuzz/run.sh",
"chars": 150,
"preview": "#!/bin/sh\n\nTHIS_SCRIPT=$(readlink -f $0)\nP=`dirname $THIS_SCRIPT`\nTOP=`dirname $P`\n\ncd $TOP\nmake sha3fuzz && ./sha3fuzz"
},
{
"path": "fuzz/seeds/0a5dec3f2ed57a024ccba1041dc85e54e09f74d4",
"chars": 2,
"preview": "+\u0002"
},
{
"path": "fuzz/seeds/19852f1f4d08174b77ba2c88e0d8ec1455348b22",
"chars": 3,
"preview": "3\n\u0002"
},
{
"path": "fuzz/seeds/2daa36d007df33c974630657696ef4fbc665ca12",
"chars": 4,
"preview": "\ndd\u001d"
},
{
"path": "fuzz/seeds/3c363836cf4e16666669a25da280a1865c2d2874",
"chars": 1,
"preview": "d"
},
{
"path": "fuzz/seeds/71853c6197a6a7f222db0f1978c7cb232b87c5ee",
"chars": 2,
"preview": "\n\n"
},
{
"path": "fuzz/seeds/98fc3c55ad129219ed5ffa43cd36a83fd6c2248e",
"chars": 1,
"preview": "\n"
},
{
"path": "fuzz/seeds/a4bf6fc7ed78f9cdc178168a3a60070f3fae68ab",
"chars": 3,
"preview": "\n:\n"
},
{
"path": "fuzz/seeds/a979ef10cc6f6a36df6b8a323307ee3bb2e2db9c",
"chars": 1,
"preview": "+"
},
{
"path": "fuzz/seeds/b69e21c4d029acf5779df9a7167cb0b3d76b6a91",
"chars": 8,
"preview": "vvvvv3\n\u0002"
},
{
"path": "fuzz/seeds/c63ae6dd4fc9f9dda66970e827d13f7c73fe841c",
"chars": 1,
"preview": "M"
},
{
"path": "fuzz/seeds/f45250b51fd7511ea177e87492cfb303b73517b3",
"chars": 0,
"preview": ""
},
{
"path": "fuzz/sha3fuzz.c",
"chars": 772,
"preview": "#include <stdio.h>\n#include <stdint.h>\n#include <string.h>\n\n#include \"sha3.h\"\n\nint LLVMFuzzerTestOneInput(const uint8_t "
},
{
"path": "sha3.c",
"chars": 10198,
"preview": "/* -------------------------------------------------------------------------\n * Works when compiled for either 32-bit or"
},
{
"path": "sha3.h",
"chars": 2440,
"preview": "#ifndef SHA3_H\n#define SHA3_H\n\n#include <stdint.h>\n\n/* -----------------------------------------------------------------"
},
{
"path": "sha3sum.c",
"chars": 2809,
"preview": "/* -------------------------------------------------------------------------\n * Run SHA-3 (NIST FIPS 202) on the given f"
},
{
"path": "sha3test.c",
"chars": 13615,
"preview": "/* -------------------------------------------------------------------------\n * Works when compiled for either 32-bit or"
}
]
// ... and 31 more files (download for full content)
About this extraction
This page contains the full source code of the brainhub/SHA3IUF GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 52 files (36.1 KB), approximately 14.5k tokens, and a symbol index with 20 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.