Created
June 12, 2018 11:10
-
-
Save philronan/49458736a2f08ecdff7b60eb6fc6f565 to your computer and use it in GitHub Desktop.
A proof of work function based on SHA256 hashes; finds a string with a given prefix whose hash value ends in the required number of zero bits
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
/* compile with: cc -Wall -O3 sha256_proof_of_work.c -o sha256_proof_of_work -lcrypto */ | |
#include <openssl/sha.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#define PREFIX_BYTES 16 | |
#define MAX_HASH_ATTEMPTS 10000000000L | |
uint8_t *sha256_proof_of_work(const uint8_t prefix[PREFIX_BYTES], int strength); | |
int main(int argc, char **argv) { | |
uint8_t p[PREFIX_BYTES]; | |
uint8_t *result; | |
FILE *f; | |
int i, nbits = 10; | |
if (argc == 2) nbits = atoi(argv[1]); | |
if (nbits < 1) nbits = 1; | |
if (nbits > 24) nbits = 24; | |
printf("Searching for a hash with %d trailing zero bits\n", nbits); | |
f = fopen("/dev/urandom", "r"); | |
fread(p, PREFIX_BYTES, 1, f); | |
fclose(f); | |
printf("Prefix: "); | |
for (i=0; i<PREFIX_BYTES; i++) { | |
printf("%02x", p[i]); | |
} | |
putchar('\n'); | |
result = sha256_proof_of_work(p, nbits); | |
if (!result) { | |
puts("No hash found"); | |
return 1; | |
} | |
printf("Output: "); | |
for (i = 0; i < SHA256_DIGEST_LENGTH; i++) | |
printf("%02x", *result++); | |
putchar('\n'); | |
return 0; | |
} | |
uint8_t *sha256_proof_of_work(const uint8_t prefix[PREFIX_BYTES], int strength) { | |
static uint8_t hash_in[SHA256_DIGEST_LENGTH]; | |
uint8_t hash_out[SHA256_DIGEST_LENGTH]; | |
int i, j, iszero; | |
long nhashes; | |
int zbytes = strength >> 3; | |
int zbits = ~(~0 << (strength & 0x07)); | |
for (i=0; i<PREFIX_BYTES; i++) hash_in[i] = prefix[i]; | |
for ( ; i<SHA256_DIGEST_LENGTH; i++) hash_in[i] = 0; | |
for (nhashes=0; nhashes<MAX_HASH_ATTEMPTS; nhashes++) { | |
SHA256(hash_in, SHA256_DIGEST_LENGTH, hash_out); | |
iszero = 1; | |
for (i=SHA256_DIGEST_LENGTH-1; i>=SHA256_DIGEST_LENGTH-zbytes; i--) { | |
if (hash_out[i]) { | |
iszero = 0; | |
break; | |
} | |
} | |
if (iszero && (hash_out[i] & zbits) == 0) { | |
return hash_in; | |
} | |
j = SHA256_DIGEST_LENGTH-1; | |
while (!(++hash_in[j])) j--; | |
} | |
return NULL; /* No hash found after MAX_HASH_ATTEMPTS; request another prefix? */ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment