declarative-jellyfin/modules/pbkdf2-sha512.c
Sveske-Juice b7fdfe57e6
All checks were successful
Run tests / run_tests (push) Successful in 1m15s
Nettle C Program for generating pbkdf2-sha512 hash
2025-04-05 22:30:39 +02:00

151 lines
3.8 KiB
C

#include <ctype.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/random.h>
#include <nettle/pbkdf2.h>
#include <string.h>
#include <unistd.h>
#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;
}