hash passwords

This commit is contained in:
SimonFJ20 2025-03-05 11:12:20 +01:00
parent 355c907135
commit d537e0a709
7 changed files with 179 additions and 4 deletions

View File

@ -1 +1,2 @@
build/
database.db

View File

@ -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 =

35
slige/runtime/prepare.sql Normal file
View File

@ -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)
);

View File

@ -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);
}

View File

@ -1,5 +1,7 @@
#include "http_server.h"
#include "json.h"
#include "str_util.h"
#include <sqlite3.h>
#include <stdio.h>
#include <string.h>
@ -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);
}

View File

@ -1,5 +1,9 @@
#include "str_util.h"
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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;
}

View File

@ -1,7 +1,9 @@
#pragma once
#include "collection.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
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);