【英文】SHA-256算法的C语言实现

SHA-256 Algorithm Implementation in C

Original site: rbtblog.com/posts/SHA256-Algorithm-Implementation-in-C


Author: Robert1037

Source: https://github.com/Robert1037/Crypto-in-C/tree/master/sha-256

Releases: https://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

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) :

featuressha256full.csha256fast.csha256min.c
timerYes (3)Yes (1)No
promptYes (detailed)Yes (brief)No
repetitionYesNoNo
string hashingYesYes (include NULL)No
file hashingYesYesYes
unroll loopYes (1)Yes (18)No

sha256min.c :

/**
 * 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

sha256fast_win10_x64.exe

sha256min_win10_x64.exe

OS

  • Windows 10
  • Windows 11

CPU

  • Intel x64 (x86_64, amd64)
  • AMD x64 (x86_64, amd64)

Build Info

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

sha256fast_deb11_x64

sha256min_deb11_x64

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

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

sha256fast_rasp4b_64

sha256min_rasp4b_64

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

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

sha256fast_rasp4b_32

sha256min_rasp4b_32

OS

  • Raspbian 11 armhf
  • Ubuntu 20.04 (focal) armhf
  • Ubuntu 22.04 (jammy) armhf

Hardware

  • Raspberry Pi 4 Model B

Build Info

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

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)

> mingw32-make full

Build all: (by default)

> mingw32-make

Linux

Prerequisites: gcc, make

Build one of them: (e.g. sha256full)

$ make full

Build all: (by default)

$ make

Usage

Windows

sha256full

  • cmd or powershell
  • double click .exe
> .\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 or powershell
  • double click .exe
> .\sha256fast
filename or string :

sha256min

  • cmd or powershell
  • double click .exe
> .\sha256min <filename>

Linux

sha256full

$ ./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

$ ./sha256fast
filename or string :

sha256min

$ ./sha256min <filename>

Screenshots & Test Results

Windows10 x64

Verification tools:

https://coding.tools/sha256

and

> 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:

$ 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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Su4pJrUz-1674401913576)(null)]

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值