From d537e0a709bd9754cf3e92980e16ea17c385e217 Mon Sep 17 00:00:00 2001 From: SimonFJ20 Date: Wed, 5 Mar 2025 11:12:20 +0100 Subject: [PATCH] hash passwords --- slige/runtime/.gitignore | 1 + slige/runtime/Makefile | 3 +- slige/runtime/prepare.sql | 35 ++++++++++++++++ slige/runtime/src/http_server.c | 3 +- slige/runtime/src/main.c | 50 +++++++++++++++++++++- slige/runtime/src/str_util.c | 73 +++++++++++++++++++++++++++++++++ slige/runtime/src/str_util.h | 18 ++++++++ 7 files changed, 179 insertions(+), 4 deletions(-) create mode 100644 slige/runtime/prepare.sql diff --git a/slige/runtime/.gitignore b/slige/runtime/.gitignore index 567609b..5e19c1d 100644 --- a/slige/runtime/.gitignore +++ b/slige/runtime/.gitignore @@ -1 +1,2 @@ build/ +database.db diff --git a/slige/runtime/Makefile b/slige/runtime/Makefile index 37f9892..43961f8 100644 --- a/slige/runtime/Makefile +++ b/slige/runtime/Makefile @@ -14,7 +14,8 @@ C_FLAGS = \ -Wall -Wextra -Wpedantic -Wconversion \ -pedantic -pedantic-errors \ -L_FLAGS = -lm -pthread +L_FLAGS = -lm -pthread $(shell pkg-config sqlite3 openssl --libs) +C_FLAGS = $(shell pkg-config sqlite3 openssl --cflags) F_FLAGS = OPTIMIZATION = diff --git a/slige/runtime/prepare.sql b/slige/runtime/prepare.sql new file mode 100644 index 0000000..f8e9899 --- /dev/null +++ b/slige/runtime/prepare.sql @@ -0,0 +1,35 @@ + +CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY, + email TEXT NOT NULL, + password_hash TEXT NOT NULL, + balanceInDkkCent INTEGER NOT NULL +); + +CREATE TABLE IF NOT EXISTS products ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + priceInDkkCent INTEGER NOT NULL +); + +CREATE TABLE IF NOT EXISTS product_prices ( + id INTEGER PRIMARY KEY, + product INTEGER NOT NULL, + priceInDkkCent INTEGER NOT NULL, + FOREIGN KEY(product) REFERENCES products(id) +); + +CREATE TABLE IF NOT EXISTS carts ( + id INTEGER PRIMARY KEY, + user INTEGER NOT NULL, + FOREIGN KEY(user) REFERENCES users(id) +); + +CREATE TABLE IF NOT EXISTS cart_items ( + id INTEGER PRIMARY KEY, + cart INTEGER NOT NULL, + amount INTEGER NOT NULL, + FOREIGN KEY(cart) REFERENCES carts(id) +); + + diff --git a/slige/runtime/src/http_server.c b/slige/runtime/src/http_server.c index e357d0d..daeda16 100644 --- a/slige/runtime/src/http_server.c +++ b/slige/runtime/src/http_server.c @@ -322,7 +322,8 @@ static inline void worker_handle_request(Worker* worker, Client* client) l1_return: header_vec_destroy(&handler_ctx.res_headers); req_destroy(&req); - free(body); + if (body) + free(body); l0_return: close(client->file); } diff --git a/slige/runtime/src/main.c b/slige/runtime/src/main.c index 30a26f7..03d342c 100644 --- a/slige/runtime/src/main.c +++ b/slige/runtime/src/main.c @@ -1,5 +1,7 @@ #include "http_server.h" #include "json.h" +#include "str_util.h" +#include #include #include @@ -47,18 +49,61 @@ void route_post_set_number(HttpCtx* ctx) JsonValue* body = json_parser_parse(&parser); json_parser_destroy(&parser); + if (!json_object_has(body, "value")) { + RESPOND_JSON( + ctx, 200, "{\"ok\": false, \"msg\": \"no 'value' key\"}\r\n"); + goto l0_return; + } + int64_t value = json_int(json_object_get(body, "value")); cx->number = (int)value; - json_value_free(body); - RESPOND_JSON(ctx, 200, "{\"ok\": true}\r\n"); + +l0_return: + json_value_free(body); } HttpServer* server; int main(void) { + + char password[] = "Merc1234"; + + const char* other_password = "Merc1234"; + + { + StrHash password_hash = str_hash(password); + char* password_hash_str = str_hash_to_string(password_hash); + printf("'%s'\n", password_hash_str); + + bool other_is_equal = str_hash_is_equal(password_hash, other_password); + printf("is_equal = %s\n", other_is_equal ? "true" : "false"); + + free(password_hash_str); + } + + { + StrHash password_hash = str_hash(password); + char* password_hash_str = str_hash_to_string(password_hash); + printf("'%s'\n", password_hash_str); + + bool other_is_equal = str_hash_is_equal(password_hash, other_password); + printf("is_equal = %s\n", other_is_equal ? "true" : "false"); + + free(password_hash_str); + } + + return 0; + + sqlite3* db; + int res = sqlite3_open("database.db", &db); + if (res != SQLITE_OK) { + fprintf(stderr, "error: could not open sqlite 'database.db'\n"); + return -1; + } + Cx cx = { .number = 1 }; server = http_server_new((HttpServerOpts) { @@ -77,4 +122,5 @@ int main(void) http_server_listen(server); http_server_free(server); + sqlite3_close(db); } diff --git a/slige/runtime/src/str_util.c b/slige/runtime/src/str_util.c index b8c82bc..0f9e243 100644 --- a/slige/runtime/src/str_util.c +++ b/slige/runtime/src/str_util.c @@ -1,5 +1,9 @@ #include "str_util.h" +#include +#include #include +#include +#include #include StrSplitter str_split(const char* text, size_t text_len, const char* split) @@ -44,3 +48,72 @@ char* string_copy(const String* string) copy[string->size] = '\0'; return copy; } +static inline StrHash str_hash_with_salt(const char* str, const uint8_t* salt) +{ + if (strlen(str) >= MAX_HASH_INPUT_LEN - 1) { + fprintf(stderr, "error: tried to hash too long input\n"); + exit(1); + } + + StrHash hash; + memcpy(hash.salt, salt, STR_HASH_SALT_SIZE); + + uint8_t input[MAX_HASH_INPUT_LEN + STR_HASH_SALT_SIZE] = { 0 }; + memcpy(input, hash.salt, STR_HASH_SALT_SIZE); + memcpy(&input[STR_HASH_SALT_SIZE], str, strlen(str)); + + SHA256(input, strlen((char*)input), hash.hash); + return hash; +} + +StrHash str_hash(const char* str) +{ + uint8_t salt[STR_HASH_SALT_SIZE]; + RAND_bytes(salt, STR_HASH_SALT_SIZE); + return str_hash_with_salt(str, salt); +} + +bool str_hash_is_equal(StrHash hash, const char* str) +{ + StrHash other = str_hash_with_salt(str, hash.salt); + return memcmp(hash.hash, other.hash, STR_HASH_HASH_SIZE) == 0; +} + +char* str_hash_to_string(StrHash hash) +{ + char* result = calloc(STR_HASH_STR_LEN + 1, sizeof(char)); + for (size_t i = 0; i < STR_HASH_SALT_SIZE; ++i) { + char bytestr[3] = { 0 }; + snprintf(bytestr, 3, "%02x", hash.salt[i]); + result[i * 2] = bytestr[0]; + result[i * 2 + 1] = bytestr[1]; + } + for (size_t i = 0; i < STR_HASH_HASH_SIZE; ++i) { + char bytestr[3] = { 0 }; + snprintf(bytestr, 3, "%02x", hash.salt[i]); + result[(STR_HASH_SALT_SIZE + i) * 2] = bytestr[0]; + result[(STR_HASH_SALT_SIZE + i) * 2 + 1] = bytestr[1]; + } + return result; +} + +StrHash str_hash_from_string(const char* str) +{ + uint8_t result[64] = { 0 }; + size_t result_i = 0; + for (size_t i = 0; i < strlen(str) && result_i < 64; i += 2) { + char bytestr[3] = { 0 }; + strncpy(bytestr, &str[i], 2); + uint64_t byte = strtoul(bytestr, NULL, 16); + result[result_i] = (uint8_t)byte; + result_i += 1; + } + + StrHash hash; + // memcpy((uint8_t*)&hash, result, sizeof(result)); + for (size_t i = 0; i < 32; ++i) { + hash.salt[i] = result[i]; + hash.hash[i] = result[32 + i]; + } + return hash; +} diff --git a/slige/runtime/src/str_util.h b/slige/runtime/src/str_util.h index 5b523f1..60aa9b2 100644 --- a/slige/runtime/src/str_util.h +++ b/slige/runtime/src/str_util.h @@ -1,7 +1,9 @@ #pragma once #include "collection.h" +#include #include +#include typedef struct { const char* ptr; @@ -25,3 +27,19 @@ void string_push_str(String* string, const char* str); char* string_copy(const String* string); DEFINE_VEC(char*, RawStrVec, rawstr_vec, 8) + +#define MAX_HASH_INPUT_LEN 256 + +#define STR_HASH_SALT_SIZE 32 +#define STR_HASH_HASH_SIZE 32 +#define STR_HASH_STR_LEN 128 + +typedef struct { + uint8_t salt[STR_HASH_SALT_SIZE]; + uint8_t hash[STR_HASH_HASH_SIZE]; +} StrHash; + +StrHash str_hash(const char* str); +bool str_hash_is_equal(StrHash hash, const char* str); +char* str_hash_to_string(StrHash hash); +StrHash str_hash_from_string(const char* str);