Skip to content

Instantly share code, notes, and snippets.

@karanlyons
Created July 4, 2017 08:35
Show Gist options
  • Save karanlyons/9763564fcd39c463212610b621b09470 to your computer and use it in GitHub Desktop.
Save karanlyons/9763564fcd39c463212610b621b09470 to your computer and use it in GitHub Desktop.
SHA-512 in C“++”
#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <cstring>
using namespace std;
const uint64_t k[] = {
UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc),
UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019), UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118),
UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe), UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2),
UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694),
UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3), UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65),
UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483), UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5),
UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4),
UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725), UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70),
UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926), UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df),
UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b),
UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001), UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30),
UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910), UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8),
UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8),
UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb), UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3),
UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60), UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec),
UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b),
UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207), UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178),
UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6), UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b),
UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c),
UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a), UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817),
};
class Sha512 {
private:
uint64_t h[8] = {
UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b), UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1),
UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f), UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179),
};
uint8_t partial[128] = {0};
size_t partial_length = 0;
uint64_t total_length[2] = {0};
inline uint64_t rotr(uint64_t m, uint64_t n) { return (m >> n) | (m << (64 - n)); }
inline uint64_t swap_uint64(uint64_t n) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
n = ((n << 8) & UINT64_C(0xFF00FF00FF00FF00) ) | ((n >> 8) & UINT64_C(0x00FF00FF00FF00FF));
n = ((n << 16) & UINT64_C(0xFFFF0000FFFF0000) ) | ((n >> 16) & UINT64_C(0x0000FFFF0000FFFF));
return (n << 32) | (n >> 32);
#else
return n;
#endif
}
inline uint64_t s0(uint64_t w) { return rotr(w, 1) ^ rotr(w, 8) ^ (w >> 7); }
inline uint64_t s1(uint64_t w) { return rotr(w, 19) ^ rotr(w, 61) ^ (w >> 6); }
inline uint64_t S0(uint64_t a) { return rotr(a, 28) ^ rotr(a, 34) ^ rotr(a, 39); }
inline uint64_t S1(uint64_t e) { return rotr(e, 14) ^ rotr(e, 18) ^ rotr(e, 41); }
inline uint64_t ch(uint64_t e, uint64_t f, uint64_t g) { return (e & f) ^ (~e & g); }
inline uint64_t maj(uint64_t a, uint64_t b, uint64_t c) { return (a & b) ^ (a & c) ^ (b & c); }
void process_block(const void *block) {
uint64_t s[8], w[80];
uint64_t t1, t2;
uint8_t i;
memcpy(&s, &h, 64);
for (i=0; i<16; i++) {
w[i] = swap_uint64(((uint64_t *)block)[i]);
}
for (i=16; i<80; i++) {
w[i] = w[i-16] + s0(w[i-15]) + w[i-7] + s1(w[i-2]);
}
for (i=0; i<80; i++) {
t1 = s[7] + S1(s[4]) + ch(s[4], s[5], s[6]) + k[i] + w[i];
t2 = S0(s[0]) + maj(s[0], s[1], s[2]);
s[7] = s[6];
s[6] = s[5];
s[5] = s[4];
s[4] = s[3] + t1;
s[3] = s[2];
s[2] = s[1];
s[1] = s[0];
s[0] = t1 + t2;
}
for (i=0; i<8; i++) {
h[i] += s[i];
}
}
public:
void update(const void *buf, size_t len) {
size_t i = 0;
size_t copy_length;
len = (sizeof((&buf)[0]) * len) / 8;
while (i < len) {
copy_length = min(len - i, 128 - partial_length);
memcpy(&partial[partial_length], &((uint8_t *)buf)[i], copy_length);
i += copy_length;
partial_length += copy_length;
if (partial_length == 128) {
process_block(partial);
partial_length = 0;
}
}
total_length[1] += len * 8;
if (total_length[1] < len * 8) { total_length[0]++; }
}
void digest(void *buf) {
partial[partial_length] = 0x80;
if (partial_length > 111) {
memset(&partial[partial_length + 1], 0x0, 128 - partial_length);
memset(partial, 0x0, 128);
partial_length = 0;
}
else {
memset(&partial[partial_length + 1], 0x0, 128 - partial_length);
}
total_length[0] = swap_uint64(total_length[0]);
total_length[1] = swap_uint64(total_length[1]);
memcpy(&partial[112], total_length, 16);
process_block(partial);
for (uint8_t i=0; i<8; i++) {
((uint64_t *)buf)[i] = swap_uint64(h[i]);
}
}
};
int main(int argc, char **argv) {
uint8_t digest[64] = {0};
Sha512 hash;
argc--; argv++;
while (argc--) {
hash.update(*argv, strlen(*argv));
argv++;
}
hash.digest(digest);
for (uint8_t i=0; i < 64; i++) { printf("%02x", digest[i]); } printf("\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment