-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9bd53f5
Showing
9 changed files
with
2,078 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# Custom | ||
/.vscode | ||
2_round_preimage.cpp | ||
|
||
# Prerequisites | ||
*.d | ||
|
||
# Object files | ||
*.o | ||
*.ko | ||
*.obj | ||
*.elf | ||
|
||
# Linker output | ||
*.ilk | ||
*.map | ||
*.exp | ||
|
||
# Precompiled Headers | ||
*.gch | ||
*.pch | ||
|
||
# Libraries | ||
*.lib | ||
*.a | ||
*.la | ||
*.lo | ||
|
||
# Shared objects (inc. Windows DLLs) | ||
*.dll | ||
*.so | ||
*.so.* | ||
*.dylib | ||
|
||
# Executables | ||
*.exe | ||
*.out | ||
*.app | ||
*.i*86 | ||
*.x86_64 | ||
*.hex | ||
|
||
# Debug files | ||
*.dSYM/ | ||
*.su | ||
*.idb | ||
*.pdb | ||
|
||
# Kernel Module Compile Results | ||
*.mod* | ||
*.cmd | ||
.tmp_versions/ | ||
modules.order | ||
Module.symvers | ||
Mkfile.old | ||
dkms.conf |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
|
||
# Implementation of BLAKE Hash Function in C | ||
### ECS412(BS Project) - April 2022 | ||
|
||
This project studies the working principles and methods of the [MD5](https://github.com/ajaycc17/md5-hash-function) and BLAKE hash functions. MD5 hash | ||
function is not cryptographically secure now, it has already been broken and is used only for local integrity | ||
checks and other simple tasks, but it is a great example to understand the concept of hash functions; it | ||
introduces message compression using a naive method and then with the help of some non-linear functions | ||
on the message, the hash for the message is generated. The BLAKE hash function is similar to the MD5 hash | ||
function for a few initial steps. MD5 produces a 128-bit hash value with the compression of the message by | ||
adding some extra bits and applying some non-linear functions. But in BLAKE, a core function uses 16 | ||
different states to process the content of the message and generates a 256-bit hash value. The working | ||
method of both the hash functions is explained, and the hash functions are implemented in the C | ||
programming language for simple string values. | ||
|
||
|
||
## Author | ||
|
||
- [@ajaycc17](https://www.github.com/ajaycc17)(Ajay Choudhury) | ||
|
||
|
||
|
||
## Under Guidance of: | ||
Dr. Shashank Singh [(IISER Bhopal)](https://sites.google.com/view/shashank). |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,308 @@ | ||
// BLAKE-256 reduced to 1.5 rounds | ||
#include "../blake_header.h" | ||
|
||
// initialization of states | ||
void initialize(state256 *S) | ||
{ | ||
S->h[0] = 0x6a09e667; | ||
S->h[1] = 0xbb67ae85; | ||
S->h[2] = 0x3c6ef372; | ||
S->h[3] = 0xa54ff53a; | ||
S->h[4] = 0x510e527f; | ||
S->h[5] = 0x9b05688c; | ||
S->h[6] = 0x1f83d9ab; | ||
S->h[7] = 0x5be0cd19; | ||
S->t[0] = S->t[1] = S->buflen = S->nullt = 0; | ||
S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0; | ||
} | ||
|
||
// round function | ||
void round_function(state256 *S, const uint8_t *block) | ||
{ | ||
// states and message block - 32-bit each | ||
uint32_t v[16], m[16], i; | ||
|
||
// convert take 8-bit blocks into 32-bit and big-endian format | ||
for (i = 0; i < 16; ++i) | ||
m[i] = U8TO32_BIG(block + i * 4); | ||
|
||
// initial states | ||
for (i = 0; i < 8; ++i) | ||
v[i] = S->h[i]; | ||
|
||
// rest states | ||
v[8] = S->s[0] ^ constant[0]; | ||
v[9] = S->s[1] ^ constant[1]; | ||
v[10] = S->s[2] ^ constant[2]; | ||
v[11] = S->s[3] ^ constant[3]; | ||
v[12] = constant[4]; | ||
v[13] = constant[5]; | ||
v[14] = constant[6]; | ||
v[15] = constant[7]; | ||
|
||
// XOR with t is not required when the block has padding-bits | ||
if (!S->nullt) | ||
{ | ||
v[12] ^= S->t[0]; | ||
v[13] ^= S->t[0]; | ||
v[14] ^= S->t[1]; | ||
v[15] ^= S->t[1]; | ||
} | ||
|
||
// variables to store values of states after each half round | ||
uint32_t v0[16], v0_5[16], v1[16], v1_5[16]; | ||
|
||
// initial states - before 0.5 round | ||
for (int i = 0; i < 16; i++) | ||
v0[i] = v[i]; | ||
|
||
// run the half core function for 3 times | ||
// 0.5 round | ||
G_mod(v, m, 0, 0, 4, 8, 12, 0); | ||
G_mod(v, m, 0, 1, 5, 9, 13, 2); | ||
G_mod(v, m, 0, 2, 6, 10, 14, 4); | ||
G_mod(v, m, 0, 3, 7, 11, 15, 6); | ||
// states after 0.5 round | ||
for (int i = 0; i < 16; i++) | ||
v0_5[i] = v[i]; | ||
|
||
// 1 round | ||
G_mod(v, m, 0, 0, 5, 10, 15, 8); | ||
G_mod(v, m, 0, 1, 6, 11, 12, 10); | ||
G_mod(v, m, 0, 2, 7, 8, 13, 12); | ||
G_mod(v, m, 0, 3, 4, 9, 14, 14); | ||
// states after 1 round | ||
for (int i = 0; i < 16; i++) | ||
v1[i] = v[i]; | ||
|
||
// 1.5 round | ||
G_mod(v, m, 1, 0, 4, 8, 12, 0); | ||
G_mod(v, m, 1, 1, 5, 9, 13, 2); | ||
G_mod(v, m, 1, 2, 6, 10, 14, 4); | ||
G_mod(v, m, 1, 3, 7, 11, 15, 6); | ||
// states after 1.5 round | ||
for (int i = 0; i < 16; i++) | ||
v1_5[i] = v[i]; | ||
|
||
// generating the hash with all updated states | ||
for (i = 0; i < 16; ++i) | ||
S->h[i % 8] ^= v[i]; | ||
|
||
for (i = 0; i < 8; ++i) | ||
S->h[i] ^= S->s[i % 4]; | ||
|
||
// print all the states and message | ||
printf("\n"); | ||
for (int i = 0; i < 16; i++) | ||
{ | ||
printf("v0[%d] = %08x \t v0_5[%d] = %08x \t v1[%d] = %08x \t v1_5[%d] = %08x \t m[%d] = %08x\n", | ||
i, v0[i], i, v0_5[i], i, v1[i], i, v1_5[i], i, m[i]); | ||
} | ||
printf("\n"); | ||
} | ||
|
||
// update the length of the block left and to fill | ||
void pad_and_round(state256 *S, const uint8_t *in, uint64_t inlen) | ||
{ | ||
// space left | ||
int left = S->buflen; | ||
|
||
// space left | ||
int fill = 64 - left; | ||
|
||
// data left is not null and data to be left is greater than available space | ||
if (left && (inlen >= fill)) | ||
{ | ||
memcpy((void *)(S->buf + left), (void *)in, fill); | ||
S->t[0] += 512; | ||
|
||
if (S->t[0] == 0) | ||
S->t[1]++; | ||
|
||
round_function(S, S->buf); | ||
in += fill; | ||
inlen -= fill; | ||
|
||
left = 0; | ||
} | ||
|
||
// if meesage is greater than length of 64 | ||
while (inlen >= 64) | ||
{ | ||
S->t[0] += 512; | ||
|
||
if (S->t[0] == 0) | ||
S->t[1]++; | ||
|
||
round_function(S, in); | ||
in += 64; | ||
inlen -= 64; | ||
} | ||
|
||
// if the message when block is empty | ||
if (inlen > 0) | ||
{ | ||
memcpy((void *)(S->buf + left), (void *)in, (size_t)inlen); | ||
S->buflen = left + (int)inlen; | ||
} | ||
else | ||
S->buflen = 0; | ||
} | ||
|
||
// finalize blake 256 | ||
void final_block(state256 *S, uint8_t *out) | ||
{ | ||
uint8_t msglen[8], zo = 0x01, oo = 0x81; | ||
uint32_t lo = S->t[0] + (S->buflen << 3), hi = S->t[1]; | ||
|
||
// space fill is less than greater than 2^32 bits | ||
if (lo < (S->buflen << 3)) | ||
hi++; | ||
|
||
// get the length of message in 64-bit form | ||
U32TO8_BIG(msglen + 0, hi); | ||
U32TO8_BIG(msglen + 4, lo); | ||
|
||
// only one byte for padding is fill | ||
if (S->buflen == 55) | ||
{ | ||
S->t[0] -= 8; | ||
pad_and_round(S, &oo, 1); | ||
} | ||
else | ||
{ | ||
// atleast 2 bytes are available for padding | ||
if (S->buflen < 55) | ||
{ | ||
// if buflen is 0 | ||
if (!S->buflen) | ||
S->nullt = 1; | ||
|
||
S->t[0] -= 440 - (S->buflen << 3); | ||
pad_and_round(S, padding, 55 - S->buflen); | ||
} | ||
else | ||
{ | ||
S->t[0] -= 512 - (S->buflen << 3); | ||
pad_and_round(S, padding, 64 - S->buflen); | ||
S->t[0] -= 440; | ||
pad_and_round(S, padding + 1, 55); | ||
S->nullt = 1; | ||
} | ||
|
||
// add one after padding 0 bits | ||
pad_and_round(S, &zo, 1); | ||
S->t[0] -= 8; | ||
} | ||
S->t[0] -= 64; | ||
pad_and_round(S, msglen, 8); | ||
|
||
// converting the 32-bit blocks into 8-bit hash output in big-endian | ||
U32TO8_BIG(out + 0, S->h[0]); | ||
U32TO8_BIG(out + 4, S->h[1]); | ||
U32TO8_BIG(out + 8, S->h[2]); | ||
U32TO8_BIG(out + 12, S->h[3]); | ||
U32TO8_BIG(out + 16, S->h[4]); | ||
U32TO8_BIG(out + 20, S->h[5]); | ||
U32TO8_BIG(out + 24, S->h[6]); | ||
U32TO8_BIG(out + 28, S->h[7]); | ||
} | ||
|
||
void blake32(uint8_t *out, const uint8_t *in, uint64_t inlen) | ||
{ | ||
state256 S; | ||
initialize(&S); | ||
pad_and_round(&S, in, inlen); | ||
final_block(&S, out); | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
if (argc < 2) | ||
{ | ||
// take the message | ||
char *in = "ajay1137"; | ||
|
||
// length of message | ||
size_t msg_len = strlen(in); | ||
|
||
// output array - this will contain the final hash | ||
uint8_t out[32]; | ||
|
||
// invoke the hashing function | ||
blake32(out, in, msg_len); | ||
|
||
// print the hash in hexadecimal form | ||
printf("BLAKE256 HASH for \"%s\" is: ", in); | ||
for (int i = 0; i < 32; ++i) | ||
{ | ||
printf("%02x", out[i]); | ||
} | ||
} | ||
else | ||
{ | ||
FILE *fp; | ||
int i, j, bytesread; | ||
uint8_t in[toRead], out[32]; | ||
state256 S; | ||
|
||
// read until all the files are processed | ||
for (i = 1; i < argc; ++i) | ||
{ | ||
fp = fopen(*(argv + i), "r"); | ||
if (fp == NULL) | ||
{ | ||
printf("Warning: No file named %s\n", *(argv + i)); | ||
// take the message | ||
char *in = *(argv + i); | ||
|
||
// length of message | ||
size_t msg_len = strlen(in); | ||
|
||
// output array - this will contain the final hash | ||
uint8_t out[32]; | ||
|
||
// invoke the hashing function | ||
blake32(out, in, msg_len); | ||
|
||
// print the hash in hexadecimal form | ||
printf("BLAKE256 HASH for \"%s\" is: ", in); | ||
for (int i = 0; i < 32; ++i) | ||
{ | ||
printf("%02x", out[i]); | ||
} | ||
return 1; | ||
} | ||
|
||
// initialize a state with constants | ||
initialize(&S); | ||
|
||
// read the file given as input | ||
while (1) | ||
{ | ||
// read in 64-bit blocks | ||
bytesread = fread(in, 1, toRead, fp); | ||
|
||
// if somethings is read update it else break | ||
if (bytesread) | ||
pad_and_round(&S, in, bytesread); | ||
else | ||
break; | ||
} | ||
|
||
// generate the hash digest | ||
final_block(&S, out); | ||
|
||
// print the hash digest | ||
printf("BLAKE-256 HASH for \"%s\" is: ", *(argv + i)); | ||
for (j = 0; j < 32; ++j) | ||
{ | ||
printf("%02x", out[j]); | ||
} | ||
|
||
// close the file pointer | ||
fclose(fp); | ||
} | ||
} | ||
return 0; | ||
} |
Oops, something went wrong.