C Fundamentals
Algorithms · data structures · cryptography · systems — pure C11, zero deps
Loading...
Searching...
No Matches
sha256.c
Go to the documentation of this file.
1/**
2 * @file sha256.c
3 * @brief SHA-256 implementation per FIPS 180-4.
4 *
5 * Single-shot interface only — given the bytes, returns the digest.
6 * The 32-bit constants K[0..63] are the first 32 bits of the fractional
7 * parts of the cube roots of the first 64 primes; H0[0..7] are the same
8 * for the square roots of the first 8 primes.
9 */
10
11#include "sha256.h"
12#include <string.h>
13
14static const uint32_t K[64] = {
15 0x428a2f98u, 0x71374491u, 0xb5c0fbcfu, 0xe9b5dba5u, 0x3956c25bu, 0x59f111f1u,
16 0x923f82a4u, 0xab1c5ed5u, 0xd807aa98u, 0x12835b01u, 0x243185beu, 0x550c7dc3u,
17 0x72be5d74u, 0x80deb1feu, 0x9bdc06a7u, 0xc19bf174u, 0xe49b69c1u, 0xefbe4786u,
18 0x0fc19dc6u, 0x240ca1ccu, 0x2de92c6fu, 0x4a7484aau, 0x5cb0a9dcu, 0x76f988dau,
19 0x983e5152u, 0xa831c66du, 0xb00327c8u, 0xbf597fc7u, 0xc6e00bf3u, 0xd5a79147u,
20 0x06ca6351u, 0x14292967u, 0x27b70a85u, 0x2e1b2138u, 0x4d2c6dfcu, 0x53380d13u,
21 0x650a7354u, 0x766a0abbu, 0x81c2c92eu, 0x92722c85u, 0xa2bfe8a1u, 0xa81a664bu,
22 0xc24b8b70u, 0xc76c51a3u, 0xd192e819u, 0xd6990624u, 0xf40e3585u, 0x106aa070u,
23 0x19a4c116u, 0x1e376c08u, 0x2748774cu, 0x34b0bcb5u, 0x391c0cb3u, 0x4ed8aa4au,
24 0x5b9cca4fu, 0x682e6ff3u, 0x748f82eeu, 0x78a5636fu, 0x84c87814u, 0x8cc70208u,
25 0x90befffau, 0xa4506cebu, 0xbef9a3f7u, 0xc67178f2u
26};
27
28static uint32_t rotr(uint32_t x, unsigned n) { return (x >> n) | (x << (32 - n)); }
29
30static void process_block(uint32_t H[8], const uint8_t block[64]) {
31 uint32_t W[64];
32
33 /* Big-endian 32-bit load for each 4-byte chunk. */
34 for (int i = 0; i < 16; i++) {
35 W[i] = ((uint32_t)block[i * 4 + 0] << 24)
36 | ((uint32_t)block[i * 4 + 1] << 16)
37 | ((uint32_t)block[i * 4 + 2] << 8)
38 | (uint32_t)block[i * 4 + 3];
39 }
40 for (int i = 16; i < 64; i++) {
41 uint32_t s0 = rotr(W[i - 15], 7) ^ rotr(W[i - 15], 18) ^ (W[i - 15] >> 3);
42 uint32_t s1 = rotr(W[i - 2], 17) ^ rotr(W[i - 2], 19) ^ (W[i - 2] >> 10);
43 W[i] = W[i - 16] + s0 + W[i - 7] + s1;
44 }
45
46 uint32_t a = H[0], b = H[1], c = H[2], d = H[3];
47 uint32_t e = H[4], f = H[5], g = H[6], h = H[7];
48
49 for (int i = 0; i < 64; i++) {
50 uint32_t S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
51 uint32_t ch = (e & f) ^ ((~e) & g);
52 uint32_t t1 = h + S1 + ch + K[i] + W[i];
53 uint32_t S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
54 uint32_t mj = (a & b) ^ (a & c) ^ (b & c);
55 uint32_t t2 = S0 + mj;
56 h = g; g = f; f = e;
57 e = d + t1;
58 d = c; c = b; b = a;
59 a = t1 + t2;
60 }
61
62 H[0] += a; H[1] += b; H[2] += c; H[3] += d;
63 H[4] += e; H[5] += f; H[6] += g; H[7] += h;
64}
65
66void sha256(const uint8_t *data, size_t len, uint8_t digest[SHA256_DIGEST_BYTES]) {
67 uint32_t H[8] = {
68 0x6a09e667u, 0xbb67ae85u, 0x3c6ef372u, 0xa54ff53au,
69 0x510e527fu, 0x9b05688cu, 0x1f83d9abu, 0x5be0cd19u
70 };
71
72 uint64_t bit_len = (uint64_t)len * 8;
73
74 /* Process all complete 64-byte blocks. */
75 size_t off = 0;
76 while (len - off >= 64) {
77 process_block(H, data + off);
78 off += 64;
79 }
80
81 /* Last block(s): copy remainder, append 0x80, then zero-pad to 56,
82 then 8-byte big-endian message length. May spill into a second block. */
83 uint8_t pad[128] = {0};
84 size_t rem = len - off;
85 memcpy(pad, data + off, rem);
86 pad[rem] = 0x80;
87
88 size_t pad_len;
89 if (rem < 56) {
90 pad_len = 64;
91 } else {
92 pad_len = 128;
93 }
94
95 /* Big-endian length in the last 8 bytes. */
96 for (int i = 0; i < 8; i++) {
97 pad[pad_len - 1 - i] = (uint8_t)(bit_len >> (i * 8));
98 }
99
100 process_block(H, pad);
101 if (pad_len == 128) process_block(H, pad + 64);
102
103 /* Big-endian 32-bit store. */
104 for (int i = 0; i < 8; i++) {
105 digest[i * 4 + 0] = (uint8_t)(H[i] >> 24);
106 digest[i * 4 + 1] = (uint8_t)(H[i] >> 16);
107 digest[i * 4 + 2] = (uint8_t)(H[i] >> 8);
108 digest[i * 4 + 3] = (uint8_t)(H[i] );
109 }
110}
111
112void sha256_to_hex(const uint8_t digest[SHA256_DIGEST_BYTES],
113 char hex_out[SHA256_HEX_BYTES]) {
114 static const char *hex = "0123456789abcdef";
115 for (int i = 0; i < SHA256_DIGEST_BYTES; i++) {
116 hex_out[i * 2 + 0] = hex[(digest[i] >> 4) & 0xF];
117 hex_out[i * 2 + 1] = hex[ digest[i] & 0xF];
118 }
119 hex_out[SHA256_DIGEST_BYTES * 2] = '\0';
120}
static const uint32_t K[64]
Definition sha256.c:14
static void process_block(uint32_t H[8], const uint8_t block[64])
Definition sha256.c:30
void sha256(const uint8_t *data, size_t len, uint8_t digest[SHA256_DIGEST_BYTES])
Definition sha256.c:66
void sha256_to_hex(const uint8_t digest[SHA256_DIGEST_BYTES], char hex_out[SHA256_HEX_BYTES])
Definition sha256.c:112
static uint32_t rotr(uint32_t x, unsigned n)
Definition sha256.c:28
Pure-C SHA-256 implementation, written from the FIPS 180-4 spec.
#define SHA256_HEX_BYTES
Definition sha256.h:17
#define SHA256_DIGEST_BYTES
Definition sha256.h:16