Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

README.md

Tiny SHA Library

A lightweight, portable C library implementing a wide range of SHA algorithms, fully enabled by default and optimized for both little-endian and big-endian systems.


Features

  • SHA-1/2 variants: SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256
  • SHA-3 variants: SHA3-224, SHA3-256, SHA3-384, SHA3-512
  • SHAKE / XOF variants: SHAKE128, SHAKE256
  • Raw SHAKE / Raw Keccak: RawSHAKE128, RawSHAKE256 (for raw Keccak; can be enabled via ENABLE_RAW_KECCAK)
  • Separate implementation file (tiny_sha.c) and header (tiny_sha.h)
  • Incremental (streaming) API: Init, Absorb/Update, Final, Squeeze (all return bool)
  • Wrapper functions for one-shot hashing
  • Safe Constant-time hash equality comparison using ConstTimeCompare, returning 1 if equal or 0 if different, without leaking timing.
  • Handles endianness automatically
  • Lightweight — entire library under 30 KB

Configurable Feature Flags

The library allows enabling or disabling specific hash algorithms. By default, all are enabled.

You can define flags via CMake for proper build integration:

# Tiny-SHA feature flags
target_compile_definitions(test_sha PRIVATE
    ENABLE_SHA1=1
    ENABLE_SHA224=1
    ENABLE_SHA256=1
    ENABLE_SHA384=1
    ENABLE_SHA512=1
    ENABLE_SHA512_224=1
    ENABLE_SHA512_256=1

    ENABLE_SHA3_224=1
    ENABLE_SHA3_256=1
    ENABLE_SHA3_384=1
    ENABLE_SHA3_512=1

    ENABLE_SHAKE128=1
    ENABLE_SHAKE256=1
    ENABLE_RAWSHAKE128=1
    ENABLE_RAWSHAKE256=1

    ENABLE_RAW_KECCAK=0         # off by default
    TSHASH_PREFIX=MyLib_        # optional function prefix
)

The header handles internal dependencies automatically:

  • SHA-224 → uses SHA-256 internally.
  • SHA-384 → uses SHA-512 internally.
  • SHA-512/224 and SHA-512/256 → use SHA-512 internally.
  • SHA-3 (224, 256, 384, 512) and SHAKE (128, 256) → use internal Keccak permutation functions (k_init_wrap, k_absorb_wrap, k_final_wrap, k_squeeze_wrap) for processing.

Optional Function Name Prefix (TSHASH_PREFIX)

To avoid name collisions, you can add a prefix to all functions:

#define TSHASH_PREFIX MyLib_      // prefix for all functions
#include "tiny_sha.h"

All functions will now have the prefix:

MyLib_SHA256(...);         // wrapper function
MyLib_sha256_init(...);    // incremental API

Note: TSHASH_PREFIX must be defined before including the header. Otherwise, functions will have no prefix (default behavior).


Building with CMake

  1. Open a terminal and navigate to your project folder:
$ cd /path/to/repo/tiny-sha
  1. Create and enter the build directory:
$ mkdir build
$ cd build
  1. Configure the project:
$ cmake ..
  1. Build the project (Release mode recommended):
$ cmake --build . --config Release
  • The final binary will be located in:
$ build/bin/Release/test_sha.exe

Usage Examples

Wrapper / Single-Shot API

#include <stdio.h>
#include "tiny_sha.h"

int main() {
    const char *msg = "Hello, Tiny SHA!";
    uint8_t hash[SHA256_DIGEST_SIZE];

    if (SHA256((const uint8_t*)msg, strlen(msg), hash)) {
        printf("SHA-256: ");
        for (int i = 0; i < SHA256_DIGEST_SIZE; i++) {
            printf("%02x", hash[i]);
        }
        printf("\n");
    } else {
        printf("SHA-256 computation failed!\n");
    }

    return 0;
}

Incremental / Streaming API

#include <stdio.h>
#include "tiny_sha.h"

int main() {
    const char *msg = "Hello, Tiny SHA!";
    uint8_t hash[SHA256_DIGEST_SIZE];
    SHA256_CTX ctx;

    if (sha256_init(&ctx) &&
        sha256_update(&ctx, (const uint8_t*)msg, strlen(msg)) &&
        sha256_final(&ctx, hash)) {

        printf("SHA-256: ");
        for (int i = 0; i < SHA256_DIGEST_SIZE; i++) {
            printf("%02x", hash[i]);
        }
        printf("\n");
    } else {
        printf("SHA-256 computation failed!\n");
    }

    return 0;
}

Comparing Hash Digests

uint8_t hash1[SHA256_DIGEST_SIZE];
uint8_t hash2[SHA256_DIGEST_SIZE];

// Compute hash1 and hash2...

int cmp = SHA256CompareOrder(hash1, hash2);
if (cmp == 0) {
    printf("Hashes are equal\n");
} else if (cmp < 0) {
    printf("hash1 < hash2\n");
} else {
    printf("hash1 > hash2\n");
}

Output Sizes

Algorithm Digest Size
SHA-1 20 bytes
SHA-224 28 bytes
SHA-256 32 bytes
SHA-384 48 bytes
SHA-512 64 bytes
SHA-512/224 28 bytes
SHA-512/256 32 bytes
SHA3-224 28 bytes
SHA3-256 32 bytes
SHA3-384 48 bytes
SHA3-512 64 bytes
SHAKE128 variable
SHAKE256 variable
RawSHAKE128 variable
RawSHAKE256 variable

Notes

  • Fully self-contained — no external dependencies.
  • All functions return bool to indicate success or failure.
  • Designed for simplicity, speed, and easy integration.
  • SHA-3 functions correspond to SHA-2 operations:
    • Init (SHA-2) → Init (SHA-3)
    • Update (SHA-2) → Absorb (SHA-3)
    • Final (SHA-2) → Final / Squeeze (SHA-3)
  • One-shot wrapper functions follow the same style across all algorithms, ensuring a consistent API.
  • SHAKE and RawSHAKE functions support variable-length output for flexible byte-level operations.
  • Raw Keccak API can be enabled via ENABLE_RAW_KECCAK.
  • Optional bit-level helpers (enabled with ENABLE_SHAKE128 or ENABLE_SHAKE256):
    • Trunc_s(X, Xlen, s, out) — truncates a byte array X to the first s bits, storing the result in out.
    • concat_bits(X, x_bits, Y, y_bits, out) — concatenates x_bits from X and y_bits from Y into out.

Why I made this

Hi!

I wrote Tiny SHA because I wanted a small, self-contained hashing library I can easily include in my C projects (for example, my PE dumper) without pulling in large dependencies like OpenSSL or relying on copying/stealing other people’s code. It's both a learning tool, helping me understand padding, endianness, and incremental hashing, and a practical library: configurable (enable/disable algorithms), prefixable to avoid name collisions, and straightforward to compile and link. The code is minimal, auditable, and easy to extend. :)


Sources


License

This project is released under the MIT License. See LICENSE for full text.