/SHA3IUF

Single-file C implementation of the SHA-3 implementation with Init/Update/Finalize hashing (NIST FIPS 202)

Primary LanguageC

A single-file C implementation of SHA-3 with Init/Update/Finalize API

The purpose of this project is:

  • provide an API that hashes bytes, not bits
  • provide a simple single-file reference implementation of a SHA-3 message digest algorithm, as defined in the FIPS 202 standard;
  • 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).

License, prior work

This work is in public domain.

I would appreciate 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.

1600-bit message hashing test vectors are NIST test vectors.

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.

Building

$ make

See Makefile for details. See also below for specific examples.

Self-tests

$ gcc -Wall sha3.c sha3test.c -o _ && ./_
SHA3-256, SHA3-384, SHA3-512 tests passed OK

or

$ gcc -m32 -Wall sha3.c sha3test.c -o _ && ./_
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

For 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

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 for the exact interface.

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 work, but it applies to other protocols and formats, e.g. TLS.