diff --git a/include/hash.h b/include/hash.h new file mode 100644 index 0000000..5a03d1e --- /dev/null +++ b/include/hash.h @@ -0,0 +1,18 @@ +#ifndef HASH_H +#define HASH_H + +#include +#include +#include +#include + +typedef enum { + FileObject, + TreeObject, + LogObject +} ObjectType; + +void object_hash(ObjectType, char*, char*); +void hash_to_hex(const unsigned char*, char*); + +#endif // HASH_H diff --git a/src/hash.c b/src/hash.c new file mode 100644 index 0000000..0ba0c99 --- /dev/null +++ b/src/hash.c @@ -0,0 +1,43 @@ +#include "hash.h" + +static void compute_sha1_openssl(const char* data, size_t len, unsigned char* hash) { + SHA_CTX ctx; + SHA1_Init(&ctx); + SHA1_Update(&ctx, data, len); + SHA1_Final(hash, &ctx); +} + +void hash_to_hex(const unsigned char* hash, char* hex_string) { + for (int i = 0; i < SHA_DIGEST_LENGTH; i++) { + sprintf(hex_string + (i * 2), "%02x", hash[i]); + } + hex_string[40] = '\0'; +} + +void object_hash(ObjectType obj_type, char* content, char* hex_hash) { + size_t content_len = strlen(content); + + char header[64]; + int header_len; + switch (obj_type) { + case FileObject: header_len = snprintf(header, sizeof(header), "file %zu", content_len); break; + case TreeObject: header_len = snprintf(header, sizeof(header), "tree %zu", content_len); break; + case LogObject: header_len = snprintf(header, sizeof(header), "log %zu", content_len); break; + default: header_len = 0; break; + } + header[header_len] = '\0'; + header_len++; + + size_t total_len = header_len + content_len; + + char* full_content = malloc(total_len); + memcpy(full_content, header, header_len); + memcpy(full_content + header_len, content, content_len); + + unsigned char hash[SHA_DIGEST_LENGTH]; + compute_sha1_openssl(full_content, total_len, hash); + + hash_to_hex(hash, hex_hash); + + free(full_content); +}