From d72e042ce229dc26bc4c22a41146a72ee52f1375 Mon Sep 17 00:00:00 2001 From: lomna-dev Date: Tue, 25 Apr 2023 14:17:49 +0530 Subject: [PATCH] Failure Failed to compute sha1 of a file in C. --- README.md | 24 ++++- build.flow | 4 + dummyFile | 1 - example.c | 16 +--- flow | 217 ++++++++++++++++++++++++++++++++++++++++++++++ sha1.h => nsha1.h | 53 ++++++----- output.flow | 5 ++ 7 files changed, 276 insertions(+), 44 deletions(-) create mode 100644 build.flow delete mode 100644 dummyFile create mode 100755 flow rename sha1.h => nsha1.h (83%) create mode 100644 output.flow diff --git a/README.md b/README.md index 1c1a788..7502176 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,23 @@ -# sha1 +# nsha1 -SHA1 in C \ No newline at end of file +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. \ No newline at end of file diff --git a/build.flow b/build.flow new file mode 100644 index 0000000..cdbd879 --- /dev/null +++ b/build.flow @@ -0,0 +1,4 @@ +output.flow +;!remove!; +a.out +output.flow.temp \ No newline at end of file diff --git a/dummyFile b/dummyFile deleted file mode 100644 index f2ba8f8..0000000 --- a/dummyFile +++ /dev/null @@ -1 +0,0 @@ -abc \ No newline at end of file diff --git a/example.c b/example.c index 0ced164..b0764f7 100644 --- a/example.c +++ b/example.c @@ -1,20 +1,10 @@ -#include "sha1.h" +#include "nsha1.h" #include #include int main(){ - SHA1_Result r = sha1file("dummyFile"); + NSHA1_Result r = nsha1file("flow"); char buffer[41]; - - // 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"); - + printf("%x %x %x %x %x", r.h0, r.h1, r.h2, r.h3, r.h4); return 0; } diff --git a/flow b/flow new file mode 100755 index 0000000..522e0b9 --- /dev/null +++ b/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() diff --git a/sha1.h b/nsha1.h similarity index 83% rename from sha1.h rename to nsha1.h index 8660022..ab3a0c4 100644 --- a/sha1.h +++ b/nsha1.h @@ -1,5 +1,5 @@ -#ifndef INCLUDED_SHA1_H -#define INCLUDED_SHA1_H +#ifndef INCLUDED_NSHA1_H +#define INCLUDED_NSHA1_H #include #include @@ -7,27 +7,27 @@ #define leftRotate32(N,D) (N<>(32-D)) -typedef struct SHA1_Result{ +typedef struct NSHA1_Result{ uint32_t h0; uint32_t h1; uint32_t h2; uint32_t h3; uint32_t h4; -} SHA1_Result; +} NSHA1_Result; -SHA1_Result sha1file(char *filename){ +NSHA1_Result nsha1file(char *filename){ FILE* file; - SHA1_Result r; + NSHA1_Result r; uint32_t number_of_chuncks = 0; uint32_t size_in_bytes = 0; uint64_t size_in_bits = 0; uint32_t h0 = 0x67452301; - uint32_t h1 = 0xEFCDAB89; - uint32_t h2 = 0x98BADCFE; + uint32_t h1 = 0xefcdab89; + uint32_t h2 = 0x98badcfe; uint32_t h3 = 0x10325476; - uint32_t h4 = 0xC3D2E1F0; + uint32_t h4 = 0xc3d2e1f0; file = fopen(filename,"r"); if(errno != 0){ @@ -44,7 +44,7 @@ SHA1_Result sha1file(char *filename){ bytes_read = fread(buffer, 1, 64, file); number_of_chuncks++; - printf("We read %d bytes\n", bytes_read); + // printf("We read %d bytes\n", bytes_read); if(bytes_read != 64){ // * We need to convert to 512 bit * // @@ -67,7 +67,6 @@ SHA1_Result sha1file(char *filename){ lastRound = 1; // This is the last round } - /** // Printing each byte of the chunk 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 ); - /** Printing each w for the chunck **/ + /** + // Printing each w for the chunck printf("------------------------------------------\n"); for(int i = 0; i < 80; i++) printf("%x i=%d\n", w[i], i); printf("------------------------------------------\n"); - /** Printing each w **/ + **/ uint32_t a = h0; uint32_t b = h1; @@ -107,19 +107,19 @@ SHA1_Result sha1file(char *filename){ // The 80 iterations for(int i = 0; i < 80; i++){ if(i >= 0 && i <= 19){ - f = d ^ ( b & ( c ^ d )); - k = 0x5A827999; + f = (b & c) ^ ((~b) & d); + k = 0x5a827999; }else if ( i >= 20 && i <= 39){ f = b ^ c ^ d; - k = 0x6ED9EBA1; + k = 0x6ed9eba1; }else if (i >= 40 && i <= 59){ f = (b & c) ^ (b & d) ^ (c & d); - k = 0x8F1BBCDC; + k = 0x8f1bbcdc; }else if (i >= 60 && i <= 79){ f = b ^ c ^ d; - k = 0xCA62C1D6; + k = 0xca62c1d6; } - + uint32_t temp = leftRotate32(a,5) + f + e + k + w[i]; e = d; d = c; @@ -127,20 +127,17 @@ SHA1_Result sha1file(char *filename){ b = a; 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); - - printf("0x%x 0x%x 0x%x 0x%x 0x%x\n", h0, h1, h2, h3, h4); r.h0 = h0; r.h1 = h1; diff --git a/output.flow b/output.flow new file mode 100644 index 0000000..9d6be5d --- /dev/null +++ b/output.flow @@ -0,0 +1,5 @@ +example.c +nsha1.h +;!run!; +gcc example.c +;!end!; \ No newline at end of file