SHA-256 Algorithm Implementation in C
- SHA-256 Algorithm Implementation in C
Author: Robert1037
Source: github.com/Robert1037/Crypto-in-C/tree/master/sha-256
Releases: github.com/Robert1037/Crypto-in-C/releases/tag/sha-256_v2.1_little-endian
Introduction
What is the SHA-256 algorithm? Here is the official explanation in Secure Hash Standard (SHS) :
This Standard specifies secure hash algorithms, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224 and SHA-512/256. All of the algorithms are iterative, one-way hash functions that can process a message to produce a condensed representation called a message digest. These algorithms enable the determination of a message’s integrity: any change to the message will, with a very high probability, result in a different message digest. This property is useful in the generation and verification of digital signatures and message authentication codes, and in the generation of random numbers or bits.
Each algorithm can be described in two stages: preprocessing and hash computation. Preprocessing involves padding a message, parsing the padded message into m-bit blocks, and setting initialization values to be used in the hash computation. The hash computation generates a message schedule from the padded message and uses that schedule, along with functions, constants, and word operations to iteratively generate a series of hash values. The final hash value generated by the hash computation is used to determine the message digest.
SHA-256 may be used to hash a message, M, having a length of l bits, where 0 <= l < 2^64. The algorithm uses 1) a message schedule of sixty-four 32-bit words, 2) eight working variables of 32 bits each, and 3) a hash value of eight 32-bit words. The final result of SHA-256 is a 256-bit message digest.
Algorithm
Read the following chapters and sections in Secure Hash Standard (SHS) :
2
3
4.1.2
4.2.2
5.1.1
5.2.1
5.3.3
6.2
or read: RFC 6234: US Secure Hash Algorithms
Implementation & Features
sha256full.c is the original version of sha256fast.c and sha256min.c. But sha256full.c
and sha256fast.c
are optimized, so their codes may be a little confusing. Thus I recommend reading sha256min.c
first.
Here are the features (differences) :
features | sha256full.c | sha256fast.c | sha256min.c |
---|---|---|---|
timer | Yes (3) | Yes (1) | No |
prompt | Yes (detailed) | Yes (brief) | No |
repetition | Yes | No | No |
string hashing | Yes | Yes (include NULL) | No |
file hashing | Yes | Yes | Yes |
unroll loop | Yes (1) | Yes (18) | No |
sha256min.c :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/**
* MIT License
* Copyright (c) 2023 Robert1037
* sha256min.c v2.1 little-endian
* Last modified: 2023-01-21
**/
#include <stdio.h>
#include <stdlib.h>
#define M_LEN 64 //each M block is 512 bits == 64 bytes
#define Rn(X, n) ((X << (32 - n)) | (X >> n))
#define Sn(X, n) (X >> n)
#define Ch(X, Y, Z) ((X & Y) ^ (~X & Z))
#define Maj(X, Y, Z) ((X & Y) ^ (X & Z) ^ (Y & Z))
#define Sigma_E0(X) (Rn(X, 2) ^ Rn(X, 13) ^ Rn(X, 22)) //Σ0(X) = R2(X) ⊕ R13(X) ⊕ R22(X)
#define Sigma_E1(X) (Rn(X, 6) ^ Rn(X, 11) ^ Rn(X, 25)) //Σ1(X) = R6(X) ⊕ R11(X) ⊕ R25(X)
#define Sigma_o0(X) (Rn(X, 7) ^ Rn(X, 18) ^ Sn(X, 3)) //σ0(X) = R7(X) ⊕ R18(X) ⊕ S3(X)
#define Sigma_o1(X) (Rn(X, 17) ^ Rn(X, 19) ^ Sn(X, 10)) //σ1(X) = R17(X) ⊕ R19(X) ⊕ S10(X)
int main(int argc, char **argv)
{
FILE *fp = fopen(argv[1], "rb");
if (!fp)
return 0;
unsigned int K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
register unsigned int *Kp, *W, *M, a, b, c, d, e, f, g, h, T1,
H0 = 0x6a09e667, H1 = 0xbb67ae85, H2 = 0x3c6ef372, H3 = 0xa54ff53a,
H4 = 0x510e527f, H5 = 0x9b05688c, H6 = 0x1f83d9ab, H7 = 0x5be0cd19;
register char *chp, *ch, tmp;
fseek(fp, 0, SEEK_END);
a = ftell(fp);
b = a & 63; // a % 64;
b = a + ((b < 56) ? (M_LEN - b) : (M_LEN | (M_LEN - b)));
if (!(ch = (char*)calloc(b + 256, 1))) // 256 == 64 * sizeof(int), it's for W.
return 0;
rewind(fp);
if (fread(ch, 1, a, fp) != a)
return 0;
fclose(fp);
ch[a] = 0x80;
chp = ch + b - 12;
do {
tmp = chp[0]; chp[0] = chp[3]; chp[3] = tmp;
tmp = chp[1]; chp[1] = chp[2]; chp[2] = tmp;
chp -= 4;
} while (ch <= chp);
M = (unsigned int*)ch;
b >>= 2;
W = M + b;
W[-2] = a >> 29;
W[-1] = a << 3;
do { // 1 -> N blocks of M
a = H0; b = H1; c = H2; d = H3;
e = H4; f = H5; g = H6; h = H7;
Kp = W + 16;
do { // j : 0 -> 15
*W = *M;
W++; M++;
} while (Kp != W);
Kp += 48;
do { // j : 16 -> 63
*W = Sigma_o1(W[-2]) + W[-7] + Sigma_o0(W[-15]) + W[-16];
W++;
} while (Kp != W);
Kp = K; W -= 64;
do {
T1 = h + Sigma_E1(e) + Ch(e, f, g) + *W + *Kp; //T1 ← h + Σ1(e) + Ch(e, f, g) + Wj + Kj
h = g; g = f; f = e; e = d + T1;
d = c; c = b; b = a; a = T1 + Sigma_E0(b) + Maj(b, c, d); //T2 ← Σ0(a) + Maj(a, b, c)
W++; Kp++;
} while (Kp <= &K[63]);
H0 += a; H1 += b; H2 += c; H3 += d;
H4 += e; H5 += f; H6 += g; H7 += h;
W -= 64;
} while (M != W);
printf("%.8x%.8x%.8x%.8x%.8x%.8x%.8x%.8x\n", H0, H1, H2, H3, H4, H5, H6, H7);
return 0;
}
Download
Windows
64-bit
win10_x64
sha256full_win10_x64.exe github sourceforge
sha256fast_win10_x64.exe github sourceforge
sha256min_win10_x64.exe github sourceforge
OS
- Windows 10
- Windows 11
CPU
- Intel x64 (x86_64, amd64)
- AMD x64 (x86_64, amd64)
Build Info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Microsoft Windows 10
x64-based PC
GNU Make 4.2.1
Built for x86_64-w64-mingw32
gcc version 12.2.0 (x86_64-posix-seh-rev2, Built by MinGW-W64 project)
Using built-in specs.
COLLECT_GCC=D:\mingw64\bin\gcc.exe
COLLECT_LTO_WRAPPER=D:/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/12.2.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../../../src/gcc-12.2.0/configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysroot=/c/mingw-builds/ucrt64-seh-posix/x86_64-1220-posix-seh-ucrt-rt_v10-rev2/mingw64 --enable-hot
-shared --disable-multilib --enable-languages=c,c++,fortran,lto --enable-libstdcxx-time=yes --enable-threads=posix --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --enable-libstdcxx-filesystem-ts=yes --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=nocona --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static --with-mpfr=/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static --with-mpc=/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static --with-isl=/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static --with-pkgversion='x86_64-posix-seh-rev2, Built by MinGW-W64 project' --with-bugurl=https://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -fno-ident -I/c/mingw-builds/ucrt64-seh-posix/x86_64-1220-posix-seh-ucrt-rt_v10-rev2/mingw64/opt/include -I/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-zlib-static/include -I/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -fno-ident -I/c/mingw-builds/ucrt64-seh-posix/x86_64-1220-posix-seh-ucrt-rt_v10-rev2/mingw64/opt/include -I/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-zlib-static/include -I/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS=' -I/c/mingw-builds/ucrt64-seh-posix/x86_64-1220-posix-seh-ucrt-rt_v10-rev2/mingw64/opt/include -I/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-zlib-static/include -I/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static/include' LDFLAGS='-pipe -fno-ident -L/c/mingw-builds/ucrt64-seh-posix/x86_64-1220-posix-seh-ucrt-rt_v10-rev2/mingw64/opt/lib -L/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-zlib-static/lib -L/c/mingw-builds/ucrt64-seh-posix/prerequisites/x86_64-w64-mingw32-static/lib ' LD_FOR_TARGET=/c/mingw-builds/ucrt64-seh-posix/x86_64-1220-posix-seh-ucrt-rt_v10-rev2/mingw64/bin/ld.exe --with-boot-ldflags=' -Wl,--disable-dynamicbase -static-libstdc++ -static-libgcc'
Thread model: posix
Supported LTO compression algorithms: zlib
Linux
64-bit
deb11_x64
sha256full_deb11_x64 github sourceforge
sha256fast_deb11_x64 github sourceforge
sha256min_deb11_x64 github sourceforge
OS
- Debian 11 (bullseye) amd64
- Debian 12 (bookworm) amd64
- Ubuntu 20.04 (focal) amd64
- Ubuntu 22.04 (jammy) amd64
CPU
- Intel x64 (x86_64, amd64)
- AMD x64 (x86_64, amd64)
Build Info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Debian GNU/Linux 11 (bullseye)
Linux version 5.10.0-18-cloud-amd64
GNU Make 4.3
Built for x86_64-pc-linux-gnu
gcc version 10.2.1 20210110 (Debian 10.2.1-6)
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-Km9U7s/gcc-10-10.2.1/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
Thread model: posix
Supported LTO compression algorithms: zlib zstd
rasp4b_64
sha256full_rasp4b_64 github sourceforge
sha256fast_rasp4b_64 github sourceforge
sha256min_rasp4b_64 github sourceforge
OS
- Raspbian 11 (i.e. Debian 11) aarch64
- Ubuntu 20.04 (focal) aarch64
- Ubuntu 22.04 (jammy) aarch64
Hardware
- Raspberry Pi 4 Model B
Build Info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Debian GNU/Linux 11 (bullseye)
Linux version 5.15.61-v8+
GNU Make 4.3
Built for aarch64-unknown-linux-gnu
gcc version 10.2.1 20210110 (Debian 10.2.1-6)
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/aarch64-linux-gnu/10/lto-wrapper
Target: aarch64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 10.2.1-6' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=aarch64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libquadmath --disable-libquadmath-support --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --enable-fix-cortex-a53-843419 --disable-werror --enable-checking=release --build=aarch64-linux-gnu --host=aarch64-linux-gnu --target=aarch64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
Thread model: posix
Supported LTO compression algorithms: zlib zstd
32-bit
rasp4b_32
sha256full_rasp4b_32 github sourceforge
sha256fast_rasp4b_32 github sourceforge
sha256min_rasp4b_32 github sourceforge
OS
- Raspbian 11 armhf
- Ubuntu 20.04 (focal) armhf
- Ubuntu 22.04 (jammy) armhf
Hardware
- Raspberry Pi 4 Model B
Build Info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Raspbian GNU/Linux 11 (bullseye)
Linux version 5.15.61-v7l+
GNU Make 4.3
Built for arm-unknown-linux-gnueabihf
gcc version 10.2.1 20210110 (Raspbian 10.2.1-6+rpi1)
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/10/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Raspbian 10.2.1-6+rpi1' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=arm-linux-gnueabihf- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --disable-libquadmath-support --enable-plugin --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-sjlj-exceptions --with-arch=armv6 --with-fpu=vfp --with-float=hard --disable-werror --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
Supported LTO compression algorithms: zlib zstd
Clone & Build
Download source_of_sha-256_v2.1_little-endian.zip or source_of_sha-256_v2.1_little-endian.tar.gz
or
1
git clone https://github.com/Robert1037/Crypto-in-C.git
Windows
Download the latest version of mingw: https://github.com/niXman/mingw-builds-binaries/releases4
Build one of them: (e.g. sha256full)
1
> mingw32-make full
Build all: (by default)
1
> mingw32-make
Linux
Prerequisites: gcc, make
Build one of them: (e.g. sha256full)
1
$ make full
Build all: (by default)
1
$ make
Usage
Windows
sha256full
cmd
orpowershell
- double click
.exe
1
2
3
4
5
6
7
8
> .\sha256full
*************** sha-256 ***************
Please input a file name.
If the file dose not exist,
the inputted string will be computed.
(string length < 960, file size < 2 GB)
(ENTER without input to quit)
:
sha256fast
cmd
orpowershell
- double click
.exe
1
2
> .\sha256fast
filename or string :
sha256min
cmd
orpowershell
- double click
.exe
1
> .\sha256min <filename>
Linux
sha256full
1
2
3
4
5
6
7
8
$ ./sha256full
*************** sha-256 ***************
Please input a file name.
If the file dose not exist,
the inputted string will be computed.
(string length < 960, file size < 2 GB)
(ENTER without input to quit)
:
sha256fast
1
2
$ ./sha256fast
filename or string :
sha256min
1
$ ./sha256min <filename>
Screenshots & Test Results
Windows10 x64
Verification tools:
https://coding.tools/sha256
and
1
> certutil -hashfile <filename> sha256
sha256full.exe
hello
null.txt
NIST.FIPS.180-4.pdf
..\..\test.mp4
..\..\movie.mp4
(Press ENTER
key directly)
sha256fast.exe
(Press ENTER
key directly)
hello
null.txt
NIST.FIPS.180-4.pdf
..\..\movie.mp4
sha256min.exe
(Press ENTER
key directly)
null.txt
NIST.FIPS.180-4.pdf
..\..\movie.mp4
Ubuntu20.04 x64
Verification tool:
1
$ sha256sum <filename>
sha256full
hello
NIST.FIPS.180-4.pdf
sha256fast
(Press ENTER
key directly)
hello
NIST.FIPS.180-4.pdf
sha256min
null.txt
NIST.FIPS.180-4.pdf
Verification:
References
[1] Wade Trappe, Lawrence C. Washington. Introduction to Cryptography with Coding Theory (3rd edition) [M]. Hoboken: Pearson Education, 2020: 499-521.
[2] FIPS PUB 180-4. Secure Hash Standard (SHS) [S]. http://dx.doi.org/10.6028/NIST.FIPS.180-4
[3] Datacruiser. 一文读懂SHA256算法原理及其实现. https://zhuanlan.zhihu.com/p/94619052
[4] 小Q谈移动安全. 【密码学】一文读懂SHA-2. https://zhuanlan.zhihu.com/p/404879837
Further Reading
[1] Henri Gilbert, Helena Handschuh. Security Analysis of SHA-256 and Sisters. https://link.springer.com/content/pdf/10.1007/978-3-540-24654-1_13.pdf
[2] in3rsha. sha256-animation. https://github.com/in3rsha/sha256-animation
[3] https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA256.pdf