Created
October 12, 2017 22:40
-
-
Save randomoracle/eb0e6d3f6ad3ad20376644a1ffa69acb to your computer and use it in GitHub Desktop.
Experimental SHA256 implementation for exploring behavior of compression function
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 <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
static const size_t kBlocksizeSHA256 = 64; | |
// Round constants | |
static const unsigned int K[] = { | |
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 | |
}; | |
unsigned int | |
H0 = 0x6a09e667, | |
H1 = 0xbb67ae85, | |
H2 = 0x3c6ef372, | |
H3 = 0xa54ff53a, | |
H4 = 0x510e527f, | |
H5 = 0x9b05688c, | |
H6 = 0x1f83d9ab, | |
H7 = 0x5be0cd19; | |
unsigned int RotateRight(unsigned int V, unsigned int shift) { | |
return (V >> shift) | (V << (32 - shift)); | |
} | |
unsigned int ByteSwap(unsigned int V) { | |
return ((V & 0xFF000000) >> 24 ) | | |
((V & 0x00FF0000) >> 8 ) | | |
((V & 0x0000FF00) << 8 ) | | |
((V & 0x000000FF) << 24); | |
} | |
void SHA256RoundFunction(const unsigned char *message) { | |
unsigned int W[64]; | |
memcpy(W, message, kBlocksizeSHA256); | |
for (int i = 0; i < 16; ++i) | |
W[i] = ByteSwap(W[i]); | |
for (unsigned int i = 16; i < 64; ++i) { | |
unsigned int S0 = RotateRight(W[i - 15], 7) ^ | |
RotateRight(W[i - 15], 18) ^ | |
(W[i - 15] >> 3); | |
unsigned int S1 = RotateRight(W[i - 2], 17) ^ | |
RotateRight(W[i - 2], 19) ^ | |
(W[i - 2] >> 10); | |
W[i] = W[i - 16] + W[i - 7] + S0 + S1; | |
} | |
for (int i = 0; i < 64; ++i) | |
printf("%2d: %08x\n", i, W[i]); | |
unsigned int | |
A = H0, | |
B = H1, | |
C = H2, | |
D = H3, | |
E = H4, | |
F = H5, | |
G = H6, | |
H = H7; | |
printf("Initial: %08x %08x %08x %08x %08x %08x %08x %08x\n", | |
A, B, C, D, E, F, G, H); | |
for (int i = 0; i < 64; ++i) { | |
unsigned int S1 = RotateRight(E, 6) ^ RotateRight(E, 11) ^ RotateRight(E, 25); | |
unsigned int ch = (E & F) ^ ((~E) & G); | |
unsigned int temp1 = H + S1 + ch + K[i] + W[i]; | |
unsigned int S0 = RotateRight(A, 2) ^ RotateRight(A, 13) ^ RotateRight(A, 22); | |
unsigned int majority = (A & B) ^ (A & C) ^ (B & C); | |
unsigned int temp2 = S0 + majority; | |
H = G; | |
G = F; | |
F = E; | |
E = D + temp1; | |
D = C; | |
C = B; | |
B = A; | |
A = temp1 + temp2; | |
printf("R%02d: %08X %08X %08X %08X %08X %08X %08X %08X\n", | |
i, A, B, C, D, E, F, G, H); | |
} | |
A += H0; | |
B += H1; | |
C += H2; | |
D += H3; | |
E += H4; | |
F += H5; | |
G += H6; | |
H += H7; | |
printf("Final: %08x %08x %08x %08x %08x %08x %08x %08x\n", | |
A, B, C, D, E, F, G, H); | |
} | |
void TestRotation() { | |
unsigned int test = 0x12345678; | |
for (int i = 0; i < 32; ++i) | |
printf("%i: %08x\n", i, RotateRight(test, i)); | |
} | |
int main(int argc, char **argv) { | |
union { | |
unsigned char bytes[kBlocksizeSHA256]; | |
unsigned int words[kBlocksizeSHA256 / sizeof(unsigned int)]; | |
} block = {}; | |
if (argc == 2) { | |
const char *filename = argv[1]; | |
FILE *fp = fopen(filename, "rb"); | |
if (fp == NULL) | |
return +1; | |
int available = fread(block.bytes, 1, kBlocksizeSHA256, fp); | |
printf("Read %d bytes.\n", available); | |
fclose(fp); | |
} else { | |
unsigned int word_index = atoi(argv[1]); | |
unsigned int word_value = atoi(argv[2]); | |
block.words[word_index % kBlocksizeSHA256] = word_value; | |
} | |
SHA256RoundFunction(block.bytes); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment