/c-hasher

Create secure and variable-length checksums using C with a fast and unique hashing algorithm.

Primary LanguageCApache License 2.0Apache-2.0

C Hasher

Description

Create secure and variable-length checksums using C with a fast and unique hashing algorithm.

  • Allocates static memory with stack instead of heap
  • Bitwise entropy derived without XOR, division or multiplication
  • Compiles with forward-compatible C89 and C++
  • Conforms to strict ISO C with -pedantic-errors enabled
  • Efficient without multithreading or processor-specific vectorization
  • Fast hashing speed without relying on compiler optimization
  • Hashes sequential bytes with dependence on each previous byte value
  • Hashes strings consistently in variable-length blocks of memory
  • Input with large files supported
  • Memory-safe with defined behavior
  • Minified and readable code with single-letter variable names
  • Output character length can be 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 or 1024
  • Outputs an array of 0xF digits for fast hash table lookups
  • Separate hashing functions for each digest length variant

Usage

Clone the repository in the current directory with the command git.

git clone https://github.com/frymimori/c-hasher.git

Navigate to the cloned repository's root directory with the command cd.

cd c-hasher

The following example uses code from the file test.c to generate hash digests.

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

int main(int a, char * * b) {
	FILE * c;
	unsigned short d[16];
	unsigned short e = 1024;
	unsigned short f = 16;
	unsigned short g = f;
	unsigned short h = 0;
	unsigned short * i = &g;
	unsigned short * j = &h;
	unsigned char k[1024];
	unsigned char l[16];

	if (a != 0) {
		c = fopen(b[1], "rb");

		if (c != (void *) 0) {
			while (f != 0) {
				f--;
				d[f] = 254;
			}

			f = g;
			g--;

			while (e == 1024) {
				e = fread(k, 1, 1024, c);
				hasherE(d, i, j, e, k);
			}

			if (feof(c) != 0) {
				fclose(c);
				hasherL(d, f, g, l);

				while (f != 0) {
					f--;
					printf("%x", l[f]);
				}
			} else {
				printf("Error hashing file \"%s\".", b[1]);
			}
		} else {
			printf("Error reading file \"%s\".", b[1]);
		}
	} else {
		printf("Error hashing file without required file name argument.");
	}

	return 0;
}

The function hasherA() outputs a 1-character digest.

The function hasherB() outputs a 2-character digest.

The function hasherC() outputs a 4-character digest.

The function hasherD() outputs a 8-character digest.

The function hasherE() outputs a 16-character digest.

The function hasherF() outputs a 32-character digest.

The function hasherG() outputs a 64-character digest.

The function hasherH() outputs a 128-character digest.

The function hasherI() outputs a 256-character digest.

The function hasherJ() outputs a 512-character digest.

The function hasherK() outputs a 1024-character digest.

The first argument variable d is a pointer to an unsigned short array to store the hashed payload bytes.

The default value is an empty array with a default length of 16.

The length is equivalent to the output length defined as as the bytes for the hash digest output before finalization.

The second argument variable i is a pointer to modify the value of the variable g.

The variable g is an unsigned short defined as the variable f.

The third argument variable j is a pointer to modify the value of the variable h.

The variable h is an unsigned short defined as 0.

The fourth argument variable e is the integer result from each fread() iteration defined as 1024.

The length should be modified based on the expected length of file input and efficiency requirements.

The fifth argument variable k is a pointer to an unsigned char array to store the chunked file data result before hashing.

The default value is an empty array for file data chunks with a default length of 1024.

The length should be modified based on efficiency requirements and should match the length of the variable e and other instances where 1024 is referenced as the memory buffer size for each chunked file data result.

The minimum length is the value of the variable h.

The function hasherL() adds entropy finalization and outputs the hash digest as an array of bytes for each hexadecimal digit.

The first argument variable d is a pointer to the previous unsigned short array defined as the hashed payload bytes to finalize.

The second argument variable f is the previous value defined as the output character length.

The third argument variable g is the previous value modified by the variable i in each hashing iteration for entropy.

The fourth argument variable l is a pointer to an unsigned char array to store the hashed bytes after finalization.

The default value is an empty array with a default length of 16.

The length should match the length of the variable d and the value of the variable f.

gcc -o c-hasher -pedantic-errors -std=c89 hasher.c test.c

The output from the command ./c-hasher is a hexadecimal hash digest string.

echo 123456789 > file

./c-hasher file
# f72e2e66353a7efa

The first command line argument value file is the file name to hash.

These are the outputs for each character length variant.

# hasherA()
./c-hasher file
# e

# hasherB()
./c-hasher file
# b8

# hasherC()
./c-hasher file
# acf8

# hasherD()
./c-hasher file
# 5dc02d43

# hasherE()
./c-hasher file
# f72e2e66353a7efa

# hasherF()
./c-hasher file
# cfc68e84a832f9722bd17b25c3675340

# hasherG()
./c-hasher file
# 2855a606e7a549feb53edac6b955cdd3aba83e7e5c8a0ad3c2c395dfb1d0b552

# hasherH()
./c-hasher file
# cf0a72772c17f13c815122048dbe909da49ff5df1a67f13c891b9438e606deed2863f55d337d326f239841ac3ca68d9c3b743a6316c3064c5fbb436e0586fae7

# hasherI()
./c-hasher file
# f36397a595fce01181d50f4a960e1cb0e2e733a373c0c519c763d20485fc6c344bc4681d6a6f3746f38618998db6deedacddc9386a677595ea2507802c177511bc641629a13968562fb3520ec6e262079a9fc83b6406725fbe52bb64b34a195537e59b0a318fb452424a533da5c9a625bbf8608ca9fbc8f97911b614c40bdbb1

# hasherJ()
./c-hasher file
# e240c056b221e85fd036189985780b23b53edacef729aa08acddc9bc4fe398571e023be9019bdee566484553f7292623b53eda4258be1cb066c4ec7e7b06d6af54135e2f9e4ce019c7e7bf4a9ec88746fbccaeab3d32759da49ffd9147a549f67763dac6b1931c344b408be1c34c6cb8287c2ac635fc64721e02bfce73c80369c4382f53dd8675c60b4ee37e5cd789b2e8fe30b7551908b6c5e413f2318776345f85ca2a46107becbc6fc0a0e642575f3ac6f584e7716dbbae08aed82449dc24052de94a2a6d6cba267cf77afb709f5ccf665796af4e7dd29a103e4529a18f3d18a611ddb4b5b9361ae27a5b9217cc81c4bcbe4d90a5169eae0d03fa8fca185a

# hasherK()
./c-hasher file
# cf0a32c3219bd6a71e0233a373c049fe31512a4250fce0110df0078862292e69cfa9e43862a549721e86105b3dbe9011053694b485f4aa006e0afd152c931c3c0d7ca6e1c34ce85792eff55bb1177ddbfb400780245d0369c76b1815a0704134cf2583abb9d92e61053694b401931cb06e8e56652c939011815960df1aeb52ca54135e27583275110d7c2ac63dbe1cb8a41b1815a0f42ee5e26b9c763db65a8c05b2332f960e14729aa96891c34c64febdf083abb19bdeedacd50f4a9682f134cfa12aceff677595664083a3734c64feb5369cf2dc177d5fd874ecfa9ec887cad0361891cb06d6a79aa12ac6b9d1e0194b408b65a0fc6cb8a413d280a070cd5fc6aba8d16ebb85591419f74144725726ae89598081584d098986bcd287d9f3d77053335768389affce1492fe0f1f02111c5fd71ad1b86cb7c6d69dab92623078fe1f184edd549ea6f3799750e3e559c22e0065b703cb10c68f514505e313efad4f970e76c9031010eaed50143f14d4b26c8e290466c6e7e01d0e2cea58268dce1a18cdc7411267e856715cb3f71fde6387187c134de36b4943cf6373b6a4e11fa74a01bbe02e157d25507f0651b8ed6ea314137baff54d093b4e30b7dcd70267e068fba28ca187cca072c0f8b75d5914710282dc3755642f69ff370607246d3fd8b541f4a1b0d53f0f23ee19eaa8fc84574ad71217f06c62d8ec513d4b518079