Last active
February 15, 2024 14:37
-
-
Save resilar/a10e01c6a244d701cf45a57885a6c867 to your computer and use it in GitHub Desktop.
SHA-512 C implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "sha512.h" | |
#define ROR64(x, c) (((x) >> (c)) | ((x) << (64 - (c)))) | |
#define LOAD64_BE(p) \ | |
( ((uint64_t)((p)[7]) << 0) \ | |
| ((uint64_t)((p)[6]) << 8) \ | |
| ((uint64_t)((p)[5]) << 16) \ | |
| ((uint64_t)((p)[4]) << 24) \ | |
| ((uint64_t)((p)[3]) << 32) \ | |
| ((uint64_t)((p)[2]) << 40) \ | |
| ((uint64_t)((p)[1]) << 48) \ | |
| ((uint64_t)((p)[0]) << 56) \ | |
) | |
#define STORE64_BE(p, v) \ | |
(p)[7] = ((v) >> 0) & 0xFF; \ | |
(p)[6] = ((v) >> 8) & 0xFF; \ | |
(p)[5] = ((v) >> 16) & 0xFF; \ | |
(p)[4] = ((v) >> 24) & 0xFF; \ | |
(p)[3] = ((v) >> 32) & 0xFF; \ | |
(p)[2] = ((v) >> 40) & 0xFF; \ | |
(p)[1] = ((v) >> 48) & 0xFF; \ | |
(p)[0] = ((v) >> 56) & 0xFF; | |
void sha512_init(struct sha512 *ctx) | |
{ | |
ctx->state[0] = 0x6a09e667f3bcc908; /* sqrt(2) */ | |
ctx->state[1] = 0xbb67ae8584caa73b; /* sqrt(3) */ | |
ctx->state[2] = 0x3c6ef372fe94f82b; /* sqrt(5) */ | |
ctx->state[3] = 0xa54ff53a5f1d36f1; /* sqrt(7) */ | |
ctx->state[4] = 0x510e527fade682d1; /* sqrt(11) */ | |
ctx->state[5] = 0x9b05688c2b3e6c1f; /* sqrt(13) */ | |
ctx->state[6] = 0x1f83d9abfb41bd6b; /* sqrt(17) */ | |
ctx->state[7] = 0x5be0cd19137e2179; /* sqrt(19) */ | |
ctx->bits[0] = ctx->bits[1] = 0; | |
ctx->n = 0; | |
} | |
static void sha512_block(uint64_t state[8], const uint8_t p[128]) | |
{ | |
uint64_t a, b, c, d, e, f, g, h, s0, s1, S0, S1, t1, t2, w[16]; | |
static const uint64_t K512[80] = { | |
0x428a2f98d728ae22, 0x7137449123ef65cd, | |
0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, | |
0x3956c25bf348b538, 0x59f111f1b605d019, | |
0x923f82a4af194f9b, 0xab1c5ed5da6d8118, | |
0xd807aa98a3030242, 0x12835b0145706fbe, | |
0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, | |
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, | |
0x9bdc06a725c71235, 0xc19bf174cf692694, | |
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, | |
0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, | |
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, | |
0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, | |
0x983e5152ee66dfab, 0xa831c66d2db43210, | |
0xb00327c898fb213f, 0xbf597fc7beef0ee4, | |
0xc6e00bf33da88fc2, 0xd5a79147930aa725, | |
0x06ca6351e003826f, 0x142929670a0e6e70, | |
0x27b70a8546d22ffc, 0x2e1b21385c26c926, | |
0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, | |
0x650a73548baf63de, 0x766a0abb3c77b2a8, | |
0x81c2c92e47edaee6, 0x92722c851482353b, | |
0xa2bfe8a14cf10364, 0xa81a664bbc423001, | |
0xc24b8b70d0f89791, 0xc76c51a30654be30, | |
0xd192e819d6ef5218, 0xd69906245565a910, | |
0xf40e35855771202a, 0x106aa07032bbd1b8, | |
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, | |
0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, | |
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, | |
0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, | |
0x748f82ee5defb2fc, 0x78a5636f43172f60, | |
0x84c87814a1f0ab72, 0x8cc702081a6439ec, | |
0x90befffa23631e28, 0xa4506cebde82bde9, | |
0xbef9a3f7b2c67915, 0xc67178f2e372532b, | |
0xca273eceea26619c, 0xd186b8c721c0c207, | |
0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, | |
0x06f067aa72176fba, 0x0a637dc5a2c898a6, | |
0x113f9804bef90dae, 0x1b710b35131c471b, | |
0x28db77f523047d84, 0x32caab7b40c72493, | |
0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, | |
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, | |
0x5fcb6fab3ad6faec, 0x6c44198c4a475817 | |
}; | |
a = state[0]; b = state[1]; c = state[2]; d = state[3]; | |
e = state[4]; f = state[5]; g = state[6]; h = state[7]; | |
#define ROUND_CORE(i) \ | |
S0 = ROR64(a, 28) ^ ROR64(a, 34) ^ ROR64(a, 39); \ | |
S1 = ROR64(e, 14) ^ ROR64(e, 18) ^ ROR64(e, 41); \ | |
t1 = h + S1 + ((e & f) ^ (~e & g)) + K512[i] + w[i & 0xf]; \ | |
t2 = S0 + ((a & b) ^ (a & c) ^ (b & c)); \ | |
h = g; g = f; f = e; e = d + t1; \ | |
d = c; c = b; b = a; a = t1 + t2; | |
#define ROUND_0_15(i) w[i] = LOAD64_BE(p); p += 8; ROUND_CORE(i) | |
ROUND_0_15( 0) ROUND_0_15( 1) ROUND_0_15( 2) ROUND_0_15( 3) | |
ROUND_0_15( 4) ROUND_0_15( 5) ROUND_0_15( 6) ROUND_0_15( 7) | |
ROUND_0_15( 8) ROUND_0_15( 9) ROUND_0_15(10) ROUND_0_15(11) | |
ROUND_0_15(12) ROUND_0_15(13) ROUND_0_15(14) ROUND_0_15(15) | |
#undef ROUND_0_15 | |
#define ROUND_16_79(i) \ | |
s0 = w[(i + 1) & 0xf]; s1 = w[(i + 14) & 0xf]; \ | |
s0 = ROR64(s0, 1) ^ ROR64(s0, 8) ^ (s0 >> 7); \ | |
s1 = ROR64(s1, 19) ^ ROR64(s1, 61) ^ (s1 >> 6); \ | |
w[i & 0xf] += s0 + s1 + w[(i + 9) & 0xf]; ROUND_CORE(i) | |
ROUND_16_79(16) ROUND_16_79(17) ROUND_16_79(18) ROUND_16_79(19) | |
ROUND_16_79(20) ROUND_16_79(21) ROUND_16_79(22) ROUND_16_79(23) | |
ROUND_16_79(24) ROUND_16_79(25) ROUND_16_79(26) ROUND_16_79(27) | |
ROUND_16_79(28) ROUND_16_79(29) ROUND_16_79(30) ROUND_16_79(31) | |
ROUND_16_79(32) ROUND_16_79(33) ROUND_16_79(34) ROUND_16_79(35) | |
ROUND_16_79(36) ROUND_16_79(37) ROUND_16_79(38) ROUND_16_79(39) | |
ROUND_16_79(40) ROUND_16_79(41) ROUND_16_79(42) ROUND_16_79(43) | |
ROUND_16_79(44) ROUND_16_79(45) ROUND_16_79(46) ROUND_16_79(47) | |
ROUND_16_79(48) ROUND_16_79(49) ROUND_16_79(50) ROUND_16_79(51) | |
ROUND_16_79(52) ROUND_16_79(53) ROUND_16_79(54) ROUND_16_79(55) | |
ROUND_16_79(56) ROUND_16_79(57) ROUND_16_79(58) ROUND_16_79(59) | |
ROUND_16_79(60) ROUND_16_79(61) ROUND_16_79(62) ROUND_16_79(63) | |
ROUND_16_79(64) ROUND_16_79(65) ROUND_16_79(66) ROUND_16_79(67) | |
ROUND_16_79(68) ROUND_16_79(69) ROUND_16_79(70) ROUND_16_79(71) | |
ROUND_16_79(72) ROUND_16_79(73) ROUND_16_79(74) ROUND_16_79(75) | |
ROUND_16_79(76) ROUND_16_79(77) ROUND_16_79(78) ROUND_16_79(79) | |
#undef ROUND_16_79 | |
#undef ROUND_CORE | |
state[0] += a; state[1] += b; state[2] += c; state[3] += d; | |
state[4] += e; state[5] += f; state[6] += g; state[7] += h; | |
} | |
void sha512_update(struct sha512 *ctx, const void *data, size_t n) | |
{ | |
const uint8_t *input = data; | |
if (ctx->n || n < 128) { | |
while (n && ctx->n < 128) { | |
ctx->buffer[ctx->n++] = *input++; | |
n--; | |
} | |
if (ctx->n < 128) | |
return; | |
sha512_block(ctx->state, ctx->buffer); | |
ctx->bits[1] += !(ctx->bits[0] += 1024); | |
ctx->n = 0; | |
} | |
while (n >= 128) { | |
sha512_block(ctx->state, input); | |
ctx->bits[1] += !(ctx->bits[0] += 1024); | |
input += 128; | |
n -= 128; | |
} | |
while (n) { | |
ctx->buffer[ctx->n++] = *input++; | |
n--; | |
} | |
} | |
void sha512_final(struct sha512 *ctx, uint8_t hash[64]) | |
{ | |
int i; | |
uint8_t buf[256]; | |
ctx->bits[0] += ctx->n * 8; | |
for (i = 1, buf[0] = 0x80; (ctx->n + i + 16) % 128; buf[i++] = 0); | |
STORE64_BE(buf + i, ctx->bits[1]); | |
STORE64_BE(buf + i + 8, ctx->bits[0]); | |
sha512_update(ctx, buf, i + 16); | |
STORE64_BE(hash + 0, ctx->state[0]); | |
STORE64_BE(hash + 8, ctx->state[1]); | |
STORE64_BE(hash + 16, ctx->state[2]); | |
STORE64_BE(hash + 24, ctx->state[3]); | |
STORE64_BE(hash + 32, ctx->state[4]); | |
STORE64_BE(hash + 40, ctx->state[5]); | |
STORE64_BE(hash + 48, ctx->state[6]); | |
STORE64_BE(hash + 56, ctx->state[7]); | |
} | |
void sha512(const void *data, size_t n, uint8_t hash[64]) | |
{ | |
struct sha512 ctx; | |
sha512_init(&ctx); | |
sha512_update(&ctx, data, n); | |
sha512_final(&ctx, hash); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SHA512_H | |
#define SHA512_H | |
#include <stddef.h> | |
#include <stdint.h> | |
struct sha512 { | |
uint64_t state[8]; | |
uint8_t buffer[128]; | |
uint64_t bits[2]; | |
int n; | |
}; | |
void sha512_init(struct sha512 *ctx); | |
void sha512_update(struct sha512 *ctx, const void *data, size_t n); | |
void sha512_final(struct sha512 *ctx, uint8_t hash[64]); | |
void sha512(const void *data, size_t n, uint8_t hash[64]); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment