Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_sha256.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
27
28#include <stdio.h>
29#include <string.h>
30
31#include "nilorea/n_sha256.h"
32
35static const uint32_t _sha256_k[64] = {
36 0x428a2f98u, 0x71374491u, 0xb5c0fbcfu, 0xe9b5dba5u, 0x3956c25bu, 0x59f111f1u, 0x923f82a4u, 0xab1c5ed5u,
37 0xd807aa98u, 0x12835b01u, 0x243185beu, 0x550c7dc3u, 0x72be5d74u, 0x80deb1feu, 0x9bdc06a7u, 0xc19bf174u,
38 0xe49b69c1u, 0xefbe4786u, 0x0fc19dc6u, 0x240ca1ccu, 0x2de92c6fu, 0x4a7484aau, 0x5cb0a9dcu, 0x76f988dau,
39 0x983e5152u, 0xa831c66du, 0xb00327c8u, 0xbf597fc7u, 0xc6e00bf3u, 0xd5a79147u, 0x06ca6351u, 0x14292967u,
40 0x27b70a85u, 0x2e1b2138u, 0x4d2c6dfcu, 0x53380d13u, 0x650a7354u, 0x766a0abbu, 0x81c2c92eu, 0x92722c85u,
41 0xa2bfe8a1u, 0xa81a664bu, 0xc24b8b70u, 0xc76c51a3u, 0xd192e819u, 0xd6990624u, 0xf40e3585u, 0x106aa070u,
42 0x19a4c116u, 0x1e376c08u, 0x2748774cu, 0x34b0bcb5u, 0x391c0cb3u, 0x4ed8aa4au, 0x5b9cca4fu, 0x682e6ff3u,
43 0x748f82eeu, 0x78a5636fu, 0x84c87814u, 0x8cc70208u, 0x90befffau, 0xa4506cebu, 0xbef9a3f7u, 0xc67178f2u};
44
46#define N_SHA256_ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
47
49static void _sha256_block(uint32_t state[8], const unsigned char block[64]) {
50 uint32_t w[64];
51 uint32_t a = state[0], b = state[1], c = state[2], d = state[3];
52 uint32_t e = state[4], f = state[5], g = state[6], h = state[7];
53 int i = 0;
54
55 for (i = 0; i < 16; i++)
56 w[i] = ((uint32_t)block[i * 4] << 24) | ((uint32_t)block[i * 4 + 1] << 16) | ((uint32_t)block[i * 4 + 2] << 8) |
57 (uint32_t)block[i * 4 + 3];
58 for (i = 16; i < 64; i++) {
59 uint32_t s0 = N_SHA256_ROTR(w[i - 15], 7) ^ N_SHA256_ROTR(w[i - 15], 18) ^ (w[i - 15] >> 3);
60 uint32_t s1 = N_SHA256_ROTR(w[i - 2], 17) ^ N_SHA256_ROTR(w[i - 2], 19) ^ (w[i - 2] >> 10);
61
62 w[i] = w[i - 16] + s0 + w[i - 7] + s1;
63 }
64 for (i = 0; i < 64; i++) {
65 uint32_t s1 = N_SHA256_ROTR(e, 6) ^ N_SHA256_ROTR(e, 11) ^ N_SHA256_ROTR(e, 25);
66 uint32_t ch = (e & f) ^ (~e & g);
67 uint32_t t1 = h + s1 + ch + _sha256_k[i] + w[i];
68 uint32_t s0 = N_SHA256_ROTR(a, 2) ^ N_SHA256_ROTR(a, 13) ^ N_SHA256_ROTR(a, 22);
69 uint32_t maj = (a & b) ^ (a & c) ^ (b & c);
70 uint32_t t2 = s0 + maj;
71
72 h = g;
73 g = f;
74 f = e;
75 e = d + t1;
76 d = c;
77 c = b;
78 b = a;
79 a = t1 + t2;
80 }
81 state[0] += a;
82 state[1] += b;
83 state[2] += c;
84 state[3] += d;
85 state[4] += e;
86 state[5] += f;
87 state[6] += g;
88 state[7] += h;
89}
90
92 /* the first 32 bits of the fractional parts of the square roots of the
93 * first eight primes */
94 static const uint32_t initial[8] = {0x6a09e667u, 0xbb67ae85u, 0x3c6ef372u, 0xa54ff53au,
95 0x510e527fu, 0x9b05688cu, 0x1f83d9abu, 0x5be0cd19u};
96
97 if (!ctx) return;
98 memcpy(ctx->state, initial, sizeof(initial));
99 ctx->length = 0;
100 ctx->used = 0;
101}
102
103void n_sha256_update(N_SHA256* ctx, const void* data, size_t len) {
104 const unsigned char* p = (const unsigned char*)data;
105
106 if (!ctx || !p || !len) return;
107 ctx->length += (uint64_t)len;
108 /* Top up a partial block first, then whole blocks straight from the
109 * caller's bytes, then keep what is left. */
110 if (ctx->used) {
111 size_t take = 64 - ctx->used < len ? 64 - ctx->used : len;
112
113 memcpy(ctx->block + ctx->used, p, take);
114 ctx->used += take;
115 p += take;
116 len -= take;
117 if (ctx->used < 64) return;
118 _sha256_block(ctx->state, ctx->block);
119 ctx->used = 0;
120 }
121 while (len >= 64) {
122 _sha256_block(ctx->state, p);
123 p += 64;
124 len -= 64;
125 }
126 if (len) {
127 memcpy(ctx->block, p, len);
128 ctx->used = len;
129 }
130}
131
132void n_sha256_final(N_SHA256* ctx, unsigned char out[N_SHA256_LEN]) {
133 uint64_t bits = 0;
134 int i = 0;
135
136 if (!ctx || !out) return;
137 bits = ctx->length * 8u;
138 /* a one bit, zeros to 56 bytes into a block, the length in bits */
139 ctx->block[ctx->used++] = 0x80;
140 if (ctx->used > 56) {
141 memset(ctx->block + ctx->used, 0, 64 - ctx->used);
142 _sha256_block(ctx->state, ctx->block);
143 ctx->used = 0;
144 }
145 memset(ctx->block + ctx->used, 0, 56 - ctx->used);
146 for (i = 0; i < 8; i++)
147 ctx->block[56 + i] = (unsigned char)(bits >> (56 - 8 * i));
148 _sha256_block(ctx->state, ctx->block);
149 for (i = 0; i < 8; i++) {
150 out[i * 4] = (unsigned char)(ctx->state[i] >> 24);
151 out[i * 4 + 1] = (unsigned char)(ctx->state[i] >> 16);
152 out[i * 4 + 2] = (unsigned char)(ctx->state[i] >> 8);
153 out[i * 4 + 3] = (unsigned char)ctx->state[i];
154 }
155 ctx->used = 0;
156}
157
158void n_sha256(const void* data, size_t len, unsigned char out[N_SHA256_LEN]) {
159 N_SHA256 ctx;
160
161 n_sha256_init(&ctx);
162 n_sha256_update(&ctx, data, len);
163 n_sha256_final(&ctx, out);
164}
165
166int n_sha256_file(const char* path, unsigned char out[N_SHA256_LEN]) {
167 unsigned char buffer[65536];
168 N_SHA256 ctx;
169 FILE* f = NULL;
170 int failed = 0;
171
172 if (!path || !out) return -1;
173 f = fopen(path, "rb");
174 if (!f) return -1;
175 n_sha256_init(&ctx);
176 /* A read shorter than asked is the end of the file or an error, and is
177 * the last one: reading again after either does nothing at the end and
178 * reads from an indeterminate position after an error (C11 7.21.8.1).
179 * ferror() below says which it was. */
180 for (;;) {
181 size_t got = fread(buffer, 1, sizeof(buffer), f);
182
183 if (got > 0)
184 n_sha256_update(&ctx, buffer, got);
185 if (got < sizeof(buffer))
186 break;
187 }
188 failed = ferror(f);
189 fclose(f);
190 if (failed) return -1;
191 n_sha256_final(&ctx, out);
192 return 0;
193}
194
195void n_sha256_hex(const unsigned char digest[N_SHA256_LEN], char out[N_SHA256_HEX_LEN]) {
196 static const char digits[] = "0123456789abcdef";
197 int i = 0;
198
199 if (!digest || !out) return;
200 for (i = 0; i < N_SHA256_LEN; i++) {
201 out[i * 2] = digits[digest[i] >> 4];
202 out[i * 2 + 1] = digits[digest[i] & 15];
203 }
204 out[N_SHA256_HEX_LEN - 1] = '\0';
205}
unsigned char block[64]
the block being filled
Definition n_sha256.h:63
uint32_t state[8]
the eight working words
Definition n_sha256.h:59
size_t used
how much of it is filled
Definition n_sha256.h:65
uint64_t length
bytes hashed so far
Definition n_sha256.h:61
void n_sha256_final(N_SHA256 *ctx, unsigned char out[32])
finish: the digest, the state left spent
Definition n_sha256.c:132
void n_sha256_init(N_SHA256 *ctx)
start a hash
Definition n_sha256.c:91
int n_sha256_file(const char *path, unsigned char out[32])
hash a file, read in pieces
Definition n_sha256.c:166
void n_sha256(const void *data, size_t len, unsigned char out[32])
hash one buffer
Definition n_sha256.c:158
#define N_SHA256_HEX_LEN
size of its lowercase hex form, terminator included
Definition n_sha256.h:54
void n_sha256_update(N_SHA256 *ctx, const void *data, size_t len)
feed bytes
Definition n_sha256.c:103
#define N_SHA256_LEN
size in bytes of a SHA-256 digest
Definition n_sha256.h:52
void n_sha256_hex(const unsigned char digest[32], char out[65])
a digest as lowercase hex
Definition n_sha256.c:195
a SHA-256 in progress: plain data, copyable to fork a hash
Definition n_sha256.h:57
#define N_SHA256_ROTR(x, n)
rotate right
Definition n_sha256.c:46
static void _sha256_block(uint32_t state[8], const unsigned char block[64])
helper: hash one 64 byte block into the state
Definition n_sha256.c:49
static const uint32_t _sha256_k[64]
the round constants: the first 32 bits of the fractional parts of the cube roots of the first 64 prim...
Definition n_sha256.c:35
SHA-256 in portable C, fed a piece at a time.