From b7fdfe57e61a1ac793af0566c8438cd64ddbcab4 Mon Sep 17 00:00:00 2001 From: Sveske-Juice Date: Sat, 5 Apr 2025 22:30:39 +0200 Subject: [PATCH] Nettle C Program for generating pbkdf2-sha512 hash --- .clang-format | 3 + .editorconfig | 4 + flake.nix | 7 ++ modules/pbkdf2-sha512.c | 150 ++++++++++++++++++++++++++++++++++++++ modules/pbkdf2-sha512.nix | 20 +++++ 5 files changed, 184 insertions(+) create mode 100644 .clang-format create mode 100644 modules/pbkdf2-sha512.c create mode 100644 modules/pbkdf2-sha512.nix diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..ced5697 --- /dev/null +++ b/.clang-format @@ -0,0 +1,3 @@ +AccessModifierOffset: -4 +IndentWidth: 4 +TabWidth: 4 diff --git a/.editorconfig b/.editorconfig index f9b35bf..aba68cf 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,3 +10,7 @@ charset = utf-8 [*.nix] indent_style = space indent_size = 2 + +[*.c] +indent_style = space +indent_size = 4 diff --git a/flake.nix b/flake.nix index 54e7f4d..6aada58 100644 --- a/flake.nix +++ b/flake.nix @@ -46,5 +46,12 @@ # Run all tests for all systems hydraJobs = forAllSystems tests; checks = forAllSystems tests; + devShell.x86_64-linux = let + pkgs = import nixpkgs {system = "x86_64-linux";}; + in + pkgs.mkShell { + buildInputs = with pkgs; [bear gcc nettle]; + nativeBuildInputs = [pkgs.nettle]; + }; }; } diff --git a/modules/pbkdf2-sha512.c b/modules/pbkdf2-sha512.c new file mode 100644 index 0000000..ea8e13c --- /dev/null +++ b/modules/pbkdf2-sha512.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define DEBUG(...) \ + if (debug) \ + printf(__VA_ARGS__) + +int uppercase = 0; +int debug = 0; +size_t salt_len; + +static void display_hex(unsigned length, uint8_t *data) { + unsigned i; + + for (i = 0; i < length / 2; i++) { + if (uppercase) + printf("%02X", data[i]); + else + printf("%02x", data[i]); + } + + printf("\n"); +} + +void str_to_upper(char *str, size_t len) { + for (size_t i = 0u; i < len; i++) { + str[i] = toupper(str[i]); + } +} + +uint8_t *hex_decode(char *hex) { + DEBUG("salt: %s\n", hex); + size_t size = strlen(hex); + // 1 byte = 2 hex characters so that means the length in bytes is size / 2 + salt_len = size / 2; + char *val = malloc(size); + char *pos = hex; + + for (size_t count = 0; count < size; count++) { + sscanf(pos, "%2hhx", &val[count]); + pos += 2; + } + + return (uint8_t *)val; +} + +int main(int argc, char **argv) { + int opt; + + uint8_t *key = NULL; + unsigned int iterations = 0; + size_t length = 0; + uint8_t *salt = NULL; + int print_metadata = 1; + + while ((opt = getopt(argc, argv, "k:i:l:vnus::")) != -1) { + switch (opt) { + case 'k': + key = (uint8_t *)optarg; + break; + case 'i': + iterations = strtoul(optarg, NULL, 0); + break; + case 'l': + length = strtoul(optarg, NULL, 0); + break; + case 'v': + debug = 1; + break; + case 'n': + print_metadata = 0; + break; + case 'u': + uppercase = 1; + break; + case 's': + salt = hex_decode(optarg); + break; + default: + fprintf(stderr, + "Usage: %s -k val -i val -l val [-sval]\n" + "-k: Key to hash\n" + "-i: Iterations/rotations of pbkdf2-sha512 algorithm\n" + "-l: Length of output hash\n" + "-n: No metadata with hash. Only print hash\n" + "-v: Verbose\n" + "-u: Output hash in uppercase\n" + "-s: The salt to use. If not provided uses random salt (16 " + "length)\n", + argv[0]); + return EXIT_FAILURE; + } + } + + if (key == NULL) { + fprintf(stderr, "No key provided"); + return EXIT_FAILURE; + } + if (iterations == 0) { + fprintf(stderr, "Invalid or no iterations provived"); + return EXIT_FAILURE; + } + if (length == 0) { + fprintf(stderr, "Invalid or no length provived"); + return EXIT_FAILURE; + } + + // generate salt if none were provided + if (salt == NULL) { + DEBUG("Generating random salt..."); + salt_len = 16; + salt = malloc(salt_len); + getrandom(salt, salt_len, GRND_RANDOM); + } else { + DEBUG("Using provided salt..."); + } + + uint8_t *buffer = malloc(length + 1); + + DEBUG("Key to hash: %s\n", key); + DEBUG("Iterations: %d\n", iterations); + DEBUG("Length: %zu\n", length); + DEBUG("Salt: %.*s\n", (int)salt_len, (char *)salt); + + pbkdf2_hmac_sha512(strlen((char *)key), key, iterations, salt_len, salt, + length, buffer); + + if (print_metadata) { + printf("$PBKDF2-SHA512$iterations=%d$", iterations); + // salt hex + for (int i = 0; i < salt_len; i++) { + printf("%02X", salt[i]); + } + printf("$"); + } + + display_hex(length, buffer); + + free(salt); + free(buffer); + return EXIT_SUCCESS; +} diff --git a/modules/pbkdf2-sha512.nix b/modules/pbkdf2-sha512.nix new file mode 100644 index 0000000..b825342 --- /dev/null +++ b/modules/pbkdf2-sha512.nix @@ -0,0 +1,20 @@ +{pkgs ? import {}, ...}: +pkgs.stdenv.mkDerivation rec { + name = "genhash"; + version = "69.0.0"; + + nativeBuildInputs = with pkgs; [ + gcc + nettle + ]; + + phases = ["buildPhase"]; + + buildPhase = '' + mkdir -p $out + gcc $src -o $out/${name} -lnettle + echo $out + ''; + + src = ./pbkdf2-sha512.c; +}