Failed to compute sha1 of a file in C.
main
lomna-dev 1 year ago
parent 419be2bb94
commit d72e042ce2

@ -1,3 +1,23 @@
# sha1 # nsha1
SHA1 in C This was a failed attempt to create SHA1 algorithm in C. The algorithm achieved still seems sensitive to small changes in text files. So maybe it can be used in stuff like VCS and build systems.
## How to use
This is a single header project. Only nsha1.h needs to be included. Usage is shown in **example.c** file. So there are only 2 source files, nsha1.h and example.c
To compile :
```
python3 flow
```
To clean:
```
python3 flow clean
```
The "library" is only adding:
1. NSHA1_Result strcut to store result
2. nsha1file, a function to get nsha1 of a file.
3. leftRotate32, a macro to circular shift 32 bit unsigned integers.

@ -0,0 +1,4 @@
output.flow
;!remove!;
a.out
output.flow.temp

@ -1 +0,0 @@
abc

@ -1,20 +1,10 @@
#include "sha1.h" #include "nsha1.h"
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
int main(){ int main(){
SHA1_Result r = sha1file("dummyFile"); NSHA1_Result r = nsha1file("flow");
char buffer[41]; char buffer[41];
printf("%x %x %x %x %x", r.h0, r.h1, r.h2, r.h3, r.h4);
// final 160 bit hash value is :
// (h0 << 128) | (h1 << 96) | (h2 << 64) | (h3 << 32) | h4
// but since c does not support ints bigger than 64 bit, we will just print the values of all h(i)'s
sprintf(buffer, "%x%x%x%x%x", r.h0, r.h1, r.h2, r.h3, r.h4);
int i = 0;
while(buffer[i] != '\0')
printf("%c", buffer[i++]);
printf("\n");
return 0; return 0;
} }

217
flow

@ -0,0 +1,217 @@
#!/usr/bin/python3
import os # for checking if file exists
import hashlib # for md5sum
import sys # for reading cmd args
import shutil # for removind directories recursively
from subprocess import run # running external programs
build_files_src = {}
build_files_level = {}
build_files_toBuild = {}
# Taken from https://www.asciiart.eu/nature/deserts
done_art = r"""
. _ + . ______ . .
( /|\ . | \ . +
. ||||| _ | | | | || .
. ||||| | | _| | | | |_|| .
/\ ||||| . | | | | | | .
__||||_|||||____| |_|_____________\__________
. |||| ||||| /\ _____ _____ . .
|||| ||||| |||| . . . ________
. \|`-'|||| |||| __________ . .
\__ |||| |||| . . .
__ ||||`-'||| . . __________
. . |||| ___/ ___________ .
. _ ||||| . _ . _________
_ ___|||||__ _ \\--// . _
_ `---' .)=\oo|=(. _ . . .
_ ^ . - . \.|
"""
def check_if_file(filename, build_file_name):
""" Checks it the given file exists, else print error and exit """
if os.path.isfile(filename):
return True
else:
print("In " + build_file_name + " : " + filename + " is not a file")
exit(1)
def getmd5(filename):
""" Takes Path to a file and get it's md5sum """
with open(filename, 'rb') as file_to_check:
data = file_to_check.read()
md5_returned = hashlib.md5(data).hexdigest()
return md5_returned
def get_meta_file(filename):
""" Takes src file name in build file and converts it to entry in .flow folder filename """
fname = ""
for letter in filename:
if letter == "." or letter == "\\" or letter == "/":
pass
else:
fname += letter
return fname
def update_md5(filename):
""" Takes the filename in .flow as var fname and updates it's md5sum value according to contents of var filename """
fname = get_meta_file(filename)
with open(".flow/" + fname, "w") as f:
f.write(getmd5(filename).strip())
def create_md5(filename):
""" Takes the filename in .flow as var fname and updates it's md5sum value according to contents of var filename """
fname = get_meta_file(filename)
with open(".flow/" + fname, "w") as f:
f.write("new file")
def getstoredmd5(filename):
""" get value of file's md5 from .flow folder, else create entry. return the (md5, createdEntry)"""
md5_returned = ""
fname = get_meta_file(filename)
if fname in os.listdir(".flow"):
with open(".flow/" + fname, "r") as f:
md5_returned = f.readline()
else:
print("INFO : md5sum entry not present for " + filename + " creating one.")
create_md5(filename)
return md5_returned
def recieved_file(filename, level, rebuild):
if build_files_toBuild.get(filename, False) == False:
build_files_toBuild[filename] = rebuild
if build_files_level.get(filename, -1) < level:
build_files_level[filename] = level
pass
start, mid, end = "", "", ""
with open(filename, "r") as f:
x = f.read().split(";!run!;")
start = x[0]
y = x[1].split(";!end!;")
mid = y[0]
end = y[1]
# start
src_files = []
for line in start.split():
entry = line.strip()
src_files.append(entry)
build_files_src[filename] = src_files
if rebuild:
build_files_toBuild[filename] = True
else:
for line in start.split():
entry = line.strip()
check_if_file(entry, filename)
new_md5, old_md5 = "", ""
new_md5 = getmd5(entry)
old_md5 = getstoredmd5(entry)
if old_md5 != new_md5:
print(entry + " was modified")
build_files_toBuild[filename] = True
# mid
if build_files_toBuild[filename]:
with open(filename + ".temp", "w") as f:
f.write(mid)
# end
for line in end.split():
entry = line.strip()
check_if_file(entry, filename)
recieved_file(entry, level + 1, build_files_toBuild[filename])
def remove_if_exists(filename):
""" Check if the given filename exists, if yes then print filename and delete """
if os.path.isfile(filename):
print("Deleting " + filename)
os.remove(filename)
def main():
with open("build.flow", "r") as main_build_file:
""" flow clean """
for i in sys.argv:
if i == "clean":
# delete the .flow folder
if os.path.exists(".flow"):
print("Removing .flow directory")
shutil.rmtree(".flow")
# delete the mentioned files
cleaning_started = False
for line in main_build_file:
entry = line.strip()
if cleaning_started:
remove_if_exists(entry)
if entry == ";!remove!;":
cleaning_started = True
print("Cleaning done")
exit(0)
if not os.path.exists(".flow"):
os.makedirs(".flow")
""" creating data for build process """
for line in main_build_file:
entry = line.strip()
if entry == ";!remove!;":
break
elif os.path.isfile(entry):
recieved_file(entry, 0, False)
else:
print("ERROR : " + entry + " is neither a file or a directory")
exit(1)
print(build_files_level)
print(build_files_src)
print(build_files_toBuild)
print()
print("<-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <->")
print()
""" Build by using the data """
for f, x in list(build_files_toBuild.items()):
if x == False:
del build_files_level[f]
del build_files_src[f]
del build_files_toBuild[f]
levels_list = []
for f,x in build_files_level.items():
levels_list.append((f,x))
n = len(levels_list)
for i in range(n):
for j in range(0, n-i-1):
if levels_list[j][1] > levels_list[j+1][1]:
levels_list[j], levels_list[j+1] = levels_list[j+1], levels_list[j]
for item in levels_list:
p = run([ "bash", item[0] + ".temp" ])
if p.returncode != 0:
print(p)
print("Build Failed", file=sys.stderr )
exit(p.returncode)
for item in levels_list:
build_file_name = item[0]
for src_file in build_files_src[build_file_name]:
update_md5(src_file)
print(done_art)
print("Build Completed Successfully")
print()
print("<-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <->")
print()
if __name__ == "__main__":
main()

@ -1,5 +1,5 @@
#ifndef INCLUDED_SHA1_H #ifndef INCLUDED_NSHA1_H
#define INCLUDED_SHA1_H #define INCLUDED_NSHA1_H
#include <stdint.h> #include <stdint.h>
#include <errno.h> #include <errno.h>
@ -7,27 +7,27 @@
#define leftRotate32(N,D) (N<<D)|(N>>(32-D)) #define leftRotate32(N,D) (N<<D)|(N>>(32-D))
typedef struct SHA1_Result{ typedef struct NSHA1_Result{
uint32_t h0; uint32_t h0;
uint32_t h1; uint32_t h1;
uint32_t h2; uint32_t h2;
uint32_t h3; uint32_t h3;
uint32_t h4; uint32_t h4;
} SHA1_Result; } NSHA1_Result;
SHA1_Result sha1file(char *filename){ NSHA1_Result nsha1file(char *filename){
FILE* file; FILE* file;
SHA1_Result r; NSHA1_Result r;
uint32_t number_of_chuncks = 0; uint32_t number_of_chuncks = 0;
uint32_t size_in_bytes = 0; uint32_t size_in_bytes = 0;
uint64_t size_in_bits = 0; uint64_t size_in_bits = 0;
uint32_t h0 = 0x67452301; uint32_t h0 = 0x67452301;
uint32_t h1 = 0xEFCDAB89; uint32_t h1 = 0xefcdab89;
uint32_t h2 = 0x98BADCFE; uint32_t h2 = 0x98badcfe;
uint32_t h3 = 0x10325476; uint32_t h3 = 0x10325476;
uint32_t h4 = 0xC3D2E1F0; uint32_t h4 = 0xc3d2e1f0;
file = fopen(filename,"r"); file = fopen(filename,"r");
if(errno != 0){ if(errno != 0){
@ -44,7 +44,7 @@ SHA1_Result sha1file(char *filename){
bytes_read = fread(buffer, 1, 64, file); bytes_read = fread(buffer, 1, 64, file);
number_of_chuncks++; number_of_chuncks++;
printf("We read %d bytes\n", bytes_read); // printf("We read %d bytes\n", bytes_read);
if(bytes_read != 64){ if(bytes_read != 64){
// * We need to convert to 512 bit * // // * We need to convert to 512 bit * //
@ -67,7 +67,6 @@ SHA1_Result sha1file(char *filename){
lastRound = 1; // This is the last round lastRound = 1; // This is the last round
} }
/** /**
// Printing each byte of the chunk // Printing each byte of the chunk
printf("------------------------------------------\n"); printf("------------------------------------------\n");
@ -88,12 +87,13 @@ SHA1_Result sha1file(char *filename){
w[i] = leftRotate32( w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i - 16] , 1 ); w[i] = leftRotate32( w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i - 16] , 1 );
/** Printing each w for the chunck **/ /**
// Printing each w for the chunck
printf("------------------------------------------\n"); printf("------------------------------------------\n");
for(int i = 0; i < 80; i++) for(int i = 0; i < 80; i++)
printf("%x i=%d\n", w[i], i); printf("%x i=%d\n", w[i], i);
printf("------------------------------------------\n"); printf("------------------------------------------\n");
/** Printing each w **/ **/
uint32_t a = h0; uint32_t a = h0;
uint32_t b = h1; uint32_t b = h1;
@ -107,19 +107,19 @@ SHA1_Result sha1file(char *filename){
// The 80 iterations // The 80 iterations
for(int i = 0; i < 80; i++){ for(int i = 0; i < 80; i++){
if(i >= 0 && i <= 19){ if(i >= 0 && i <= 19){
f = d ^ ( b & ( c ^ d )); f = (b & c) ^ ((~b) & d);
k = 0x5A827999; k = 0x5a827999;
}else if ( i >= 20 && i <= 39){ }else if ( i >= 20 && i <= 39){
f = b ^ c ^ d; f = b ^ c ^ d;
k = 0x6ED9EBA1; k = 0x6ed9eba1;
}else if (i >= 40 && i <= 59){ }else if (i >= 40 && i <= 59){
f = (b & c) ^ (b & d) ^ (c & d); f = (b & c) ^ (b & d) ^ (c & d);
k = 0x8F1BBCDC; k = 0x8f1bbcdc;
}else if (i >= 60 && i <= 79){ }else if (i >= 60 && i <= 79){
f = b ^ c ^ d; f = b ^ c ^ d;
k = 0xCA62C1D6; k = 0xca62c1d6;
} }
uint32_t temp = leftRotate32(a,5) + f + e + k + w[i]; uint32_t temp = leftRotate32(a,5) + f + e + k + w[i];
e = d; e = d;
d = c; d = c;
@ -127,20 +127,17 @@ SHA1_Result sha1file(char *filename){
b = a; b = a;
a = temp; a = temp;
} }
// Add this chunk's hash result
h0 += a;
h1 += b;
h2 += c;
h3 += d;
h4 += e;
// Add this chunk's hash result
h0 = h0 + a;
h1 = h1 + b;
h2 = h2 + c;
h3 = h3 + d;
h4 = h4 + e;
/////////////////////// ****************************************** //////////////////////////////////////////// /////////////////////// ****************************************** ////////////////////////////////////////////
} }
fclose(file); fclose(file);
printf("0x%x 0x%x 0x%x 0x%x 0x%x\n", h0, h1, h2, h3, h4);
r.h0 = h0; r.h0 = h0;
r.h1 = h1; r.h1 = h1;

@ -0,0 +1,5 @@
example.c
nsha1.h
;!run!;
gcc example.c
;!end!;
Loading…
Cancel
Save