Last active
December 16, 2020 00:22
-
-
Save dpogorzelski/fb28b6ac7d92a7c667af to your computer and use it in GitHub Desktop.
sha256
This file contains 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 <stdio.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <netinet/in.h> | |
#include <stdlib.h> | |
#define TYP_INIT 0 | |
#define TYP_SMLE 1 | |
#define TYP_BIGE 2 | |
static uint32_t hash[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, | |
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; | |
static uint32_t w[64] = { 0 }; | |
static const uint32_t k[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, | |
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, | |
0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, | |
0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, | |
0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, | |
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, | |
0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, | |
0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, | |
0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, | |
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, | |
0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, | |
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, | |
0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; | |
uint8_t buffer[64] = { 0 }; | |
static const uint8_t pad = 0x80; | |
void sha256(); | |
uint64_t swap_uint64(uint64_t src); | |
int main(int argc, char** argv) | |
{ | |
size_t ceof; | |
uint64_t count = 0; | |
uint32_t i; | |
while ((ceof = fread(buffer, 1, 64, stdin)) > 0) { | |
count += ceof * 8; | |
if (ceof < 56) { | |
count = swap_uint64(count); | |
memcpy(buffer + ceof, &pad, 1); | |
memcpy(buffer + 56, &count, 8); | |
sha256(); | |
} else if (ceof <= 63) { | |
count = swap_uint64(count); | |
memcpy(buffer + ceof, &pad, 1); | |
sha256(); | |
memset(buffer, 0, 64); | |
memcpy(buffer + 56, &count, 8); | |
sha256(); | |
} else { | |
sha256(); | |
memset(buffer, 0, 64); | |
} | |
} | |
for (i = 0; i < 8; i++) | |
printf("%08x", hash[i]); | |
printf("\n"); | |
return 0; | |
} | |
void sha256() | |
{ | |
static uint32_t ch, maj, s0, s1, S0, S1, t1, t2; | |
static uint32_t a, b, c, d, e, f, g, h; | |
uint8_t i; | |
a = hash[0]; | |
b = hash[1]; | |
c = hash[2]; | |
d = hash[3]; | |
e = hash[4]; | |
f = hash[5]; | |
g = hash[6]; | |
h = hash[7]; | |
for (i = 0; i < 16; i++) { | |
memcpy(w + i, buffer + i * 4, 4); | |
w[i] = htonl(w[i]); | |
} | |
for (i = 16; i <= 63; i++) { | |
s0 = ((w[i - 15] >> 7) | (w[i - 15] << (32 - 7))) | |
^ ((w[i - 15] >> 18) | (w[i - 15] << (32 - 18))) | |
^ (w[i - 15] >> 3); | |
s1 = ((w[i - 2] >> 17) | (w[i - 2] << (32 - 17))) | |
^ ((w[i - 2] >> 19) | (w[i - 2] << (32 - 19))) | |
^ (w[i - 2] >> 10); | |
w[i] = w[i - 16] + s0 + w[i - 7] + s1; | |
} | |
for (i = 0; i <= 63; i++) { | |
ch = (e & f) ^ (~e & g); | |
maj = (a & b) ^ (a & c) ^ (c & b); | |
S0 = ((a >> 2) | (a << (32 - 2))) | |
^ ((a >> 13) | (a << (32 - 13))) | |
^ ((a >> 22) | (a << (32 - 22))); | |
S1 = ((e >> 6) | (e << (32 - 6))) | |
^ ((e >> 11) | (e << (32 - 11))) | |
^ ((e >> 25) | (e << (32 - 25))); | |
t1 = h + S1 + ch + k[i] + w[i]; | |
t2 = S0 + maj; | |
h = g; | |
g = f; | |
f = e; | |
e = d + t1; | |
d = c; | |
c = b; | |
b = a; | |
a = t1 + t2; | |
} | |
hash[0] += a; | |
hash[1] += b; | |
hash[2] += c; | |
hash[3] += d; | |
hash[4] += e; | |
hash[5] += f; | |
hash[6] += g; | |
hash[7] += h; | |
} | |
uint64_t swap_uint64(uint64_t src) | |
{ | |
static int typ = TYP_INIT; | |
unsigned char c; | |
union { | |
unsigned long long ull; | |
unsigned char c[8]; | |
} x; | |
if (typ == TYP_INIT) { | |
x.ull = 0x01; | |
typ = (x.c[7] == 0x01ULL) ? TYP_BIGE : TYP_SMLE; | |
} | |
if (typ == TYP_BIGE) | |
return src; | |
x.ull = src; | |
c = x.c[0]; | |
x.c[0] = x.c[7]; | |
x.c[7] = c; | |
c = x.c[1]; | |
x.c[1] = x.c[6]; | |
x.c[6] = c; | |
c = x.c[2]; | |
x.c[2] = x.c[5]; | |
x.c[5] = c; | |
c = x.c[3]; | |
x.c[3] = x.c[4]; | |
x.c[4] = c; | |
return x.ull; | |
} |
It appears to have to do with binary data. In my initial test I used the generated binary itself.
Here is a Dockerfile for gcc on Debian 10. The same issue occurred on my Mac running Big Sur and clang 11.
https://gist.github.com/jac18281828/eaf5fd59f649178bdafa932a7ed639d1
I see that it works if you remove the optimization '-O2'. You have some unsafe code that fails with safe optimizations turned on.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hey @jac18281828, just did a quick test with random data:
would you be able to provide a sample input that didn't match?
edit:
testing on random binary files also seems to match: