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; | |
} |
hey @jac18281828, just did a quick test with random data:
~ ❯ echo "asdfdsf" | ./a.out
c3474612eaed297c0a8b7bcc09e89f0f7beb05dd9ead5b3ff03940fb7c43f900
~ ❯ echo "asdfdsf" | openssl dgst -sha256
c3474612eaed297c0a8b7bcc09e89f0f7beb05dd9ead5b3ff03940fb7c43f900
would you be able to provide a sample input that didn't match?
edit:
testing on random binary files also seems to match:
~ ❯ cat Downloads/terraform | ./a.out
922b234c6c013183cf350ecd7fc3d840f3c9b28d6ec60c9c636fe2159bfa3638
~ ❯ cat Downloads/terraform | openssl dgst -sha256
922b234c6c013183cf350ecd7fc3d840f3c9b28d6ec60c9c636fe2159bfa3638
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
Although it compiles on gcc, the output does not match openssl dgst -sha256