Signet Forge 0.1.0
C++20 Parquet library with AI-native extensions
DEMO
Loading...
Searching...
No Matches
sha512.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright 2026 Johnson Ogundeji
3#pragma once
4
13
14#include <array>
15#include <cstddef>
16#include <cstdint>
17#include <cstring>
18#include <vector>
19
20namespace signet::forge::crypto {
21namespace detail::sha512 {
22
23// ===========================================================================
24// SHA-512 (FIPS 180-4)
25// ===========================================================================
26
28static constexpr uint64_t H0_512[8] = {
29 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
30 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
31 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
32 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
33};
34
36static constexpr uint64_t K512[80] = {
37 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
38 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
39 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
40 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
41 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
42 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
43 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
44 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
45 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
46 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
47 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
48 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
49 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
50 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
51 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
52 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
53 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
54 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
55 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
56 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
57};
58
59inline constexpr uint64_t rotr64(uint64_t x, int n) {
60 return (x >> n) | (x << (64 - n));
61}
62
63inline uint64_t load_be64(const uint8_t* p) {
64 return (uint64_t(p[0]) << 56) | (uint64_t(p[1]) << 48) |
65 (uint64_t(p[2]) << 40) | (uint64_t(p[3]) << 32) |
66 (uint64_t(p[4]) << 24) | (uint64_t(p[5]) << 16) |
67 (uint64_t(p[6]) << 8) | uint64_t(p[7]);
68}
69
70inline void store_be64(uint8_t* p, uint64_t v) {
71 p[0] = uint8_t(v >> 56); p[1] = uint8_t(v >> 48);
72 p[2] = uint8_t(v >> 40); p[3] = uint8_t(v >> 32);
73 p[4] = uint8_t(v >> 24); p[5] = uint8_t(v >> 16);
74 p[6] = uint8_t(v >> 8); p[7] = uint8_t(v);
75}
76
77inline void sha512_compress(uint64_t h[8], const uint8_t block[128]) {
78 uint64_t W[80];
79 for (int i = 0; i < 16; ++i)
80 W[i] = load_be64(block + i * 8);
81 for (int i = 16; i < 80; ++i) {
82 uint64_t s0 = rotr64(W[i-15], 1) ^ rotr64(W[i-15], 8) ^ (W[i-15] >> 7);
83 uint64_t s1 = rotr64(W[i-2], 19) ^ rotr64(W[i-2], 61) ^ (W[i-2] >> 6);
84 W[i] = W[i-16] + s0 + W[i-7] + s1;
85 }
86 uint64_t a=h[0], b=h[1], c=h[2], d=h[3], e=h[4], f=h[5], g=h[6], hh=h[7];
87 for (int i = 0; i < 80; ++i) {
88 uint64_t S1 = rotr64(e, 14) ^ rotr64(e, 18) ^ rotr64(e, 41);
89 uint64_t ch = (e & f) ^ (~e & g);
90 uint64_t t1 = hh + S1 + ch + K512[i] + W[i];
91 uint64_t S0 = rotr64(a, 28) ^ rotr64(a, 34) ^ rotr64(a, 39);
92 uint64_t maj = (a & b) ^ (a & c) ^ (b & c);
93 uint64_t t2 = S0 + maj;
94 hh = g; g = f; f = e; e = d + t1;
95 d = c; c = b; b = a; a = t1 + t2;
96 }
97 h[0]+=a; h[1]+=b; h[2]+=c; h[3]+=d; h[4]+=e; h[5]+=f; h[6]+=g; h[7]+=hh;
98}
99
100inline std::array<uint8_t, 64> sha512(const uint8_t* data, size_t size) {
101 uint64_t h[8];
102 for (int i = 0; i < 8; ++i) h[i] = H0_512[i];
103
104 size_t full_blocks = size / 128;
105 for (size_t i = 0; i < full_blocks; ++i)
106 sha512_compress(h, data + i * 128);
107
108 // Padding
109 uint8_t last[256] = {};
110 size_t rem = size % 128;
111 if (rem > 0)
112 std::memcpy(last, data + full_blocks * 128, rem);
113 last[rem] = 0x80;
114
115 size_t pad_blocks = (rem < 112) ? 1 : 2;
116 // Message length in bits as 128-bit big-endian (high 64 bits always 0 for us)
117 store_be64(last + pad_blocks * 128 - 8, size * 8);
118
119 for (size_t i = 0; i < pad_blocks; ++i)
120 sha512_compress(h, last + i * 128);
121
122 std::array<uint8_t, 64> out;
123 for (int i = 0; i < 8; ++i)
124 store_be64(out.data() + i * 8, h[i]);
125 return out;
126}
127
128inline std::array<uint8_t, 64> sha512_two(
129 const uint8_t* a, size_t a_len,
130 const uint8_t* b, size_t b_len)
131{
132 // SHA-512(a || b) — incremental hashing
133 std::vector<uint8_t> buf(a_len + b_len);
134 std::memcpy(buf.data(), a, a_len);
135 std::memcpy(buf.data() + a_len, b, b_len);
136 return sha512(buf.data(), buf.size());
137}
138
139inline std::array<uint8_t, 64> sha512_three(
140 const uint8_t* a, size_t a_len,
141 const uint8_t* b, size_t b_len,
142 const uint8_t* c, size_t c_len)
143{
144 std::vector<uint8_t> buf(a_len + b_len + c_len);
145 std::memcpy(buf.data(), a, a_len);
146 std::memcpy(buf.data() + a_len, b, b_len);
147 std::memcpy(buf.data() + a_len + b_len, c, c_len);
148 return sha512(buf.data(), buf.size());
149}
150
151} // namespace detail::sha512
152
153// Backward-compatibility alias: ed25519.hpp previously exposed these in detail::ed25519
154namespace detail::ed25519 {
158} // namespace detail::ed25519
159
160} // namespace signet::forge::crypto
std::array< uint8_t, 64 > sha512_three(const uint8_t *a, size_t a_len, const uint8_t *b, size_t b_len, const uint8_t *c, size_t c_len)
Definition sha512.hpp:139
void store_be64(uint8_t *p, uint64_t v)
Definition sha512.hpp:70
uint64_t load_be64(const uint8_t *p)
Definition sha512.hpp:63
void sha512_compress(uint64_t h[8], const uint8_t block[128])
Definition sha512.hpp:77
std::array< uint8_t, 64 > sha512_two(const uint8_t *a, size_t a_len, const uint8_t *b, size_t b_len)
Definition sha512.hpp:128
constexpr uint64_t rotr64(uint64_t x, int n)
Definition sha512.hpp:59
std::array< uint8_t, 64 > sha512(const uint8_t *data, size_t size)
Definition sha512.hpp:100