Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* argen.c - generate strong passwords with argon2id */
- /* The author disclaims copyright to this source code and
- * releases it into the public domain. In place of a legal
- * notice, here is a blessing:
- *
- * May you do good and not evil.
- *
- * May you find forgiveness for yourself and forgive others.
- *
- * May you share freely, never taking more than you give.
- */
- /* Build with gcc argen.c -lcrypto -o argen */
- #define _GNU_SOURCE
- #include <assert.h>
- #include <ctype.h>
- #include <getopt.h>
- #include <openssl/core_names.h>
- #include <openssl/err.h>
- #include <openssl/evp.h>
- #include <openssl/kdf.h>
- #include <openssl/params.h>
- #include <openssl/rand.h>
- #include <openssl/thread.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- /* the parameter memcost specifies the size in KiB so
- * this is about 64MB
- */
- #define CONFIG_ARGON2_MEMCOST (64 * 1024)
- #define CONFIG_ARGON2_LANES 4
- #define CONFIG_ARGON2_THREADS 2
- #define CONFIG_ARGON2_ITER 128
- #define CONFIG_ARGON2_VERSION 0x13
- #define CONFIG_PASS_LEN 24
- #define osslerror(s) \
- fprintf(stderr, "%s: %s\n", s, ERR_reason_error_string(ERR_get_error()))
- static int argon2id_derive(uint8_t *out, size_t outlen, uint8_t *salt,
- size_t saltlen, char *pass) {
- int ret = 1;
- EVP_KDF *kdf = NULL;
- EVP_KDF_CTX *kctx = NULL;
- uint32_t lanes = CONFIG_ARGON2_LANES;
- uint32_t threads = CONFIG_ARGON2_THREADS;
- uint32_t memcost = CONFIG_ARGON2_MEMCOST;
- uint32_t iter = CONFIG_ARGON2_ITER;
- uint32_t version = CONFIG_ARGON2_VERSION;
- if (OSSL_set_max_threads(NULL, threads) != 1) {
- osslerror("OSSL_set_max_threads");
- goto fail;
- }
- OSSL_PARAM params[] = {
- OSSL_PARAM_uint32(OSSL_KDF_PARAM_THREADS, &threads),
- OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_LANES, &lanes),
- OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_MEMCOST, &memcost),
- OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_VERSION, &version),
- OSSL_PARAM_uint32(OSSL_KDF_PARAM_ITER, &iter),
- OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, salt, saltlen),
- OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, pass, strlen(pass)),
- OSSL_PARAM_END};
- if ((kdf = EVP_KDF_fetch(NULL, "ARGON2ID", NULL)) == NULL) {
- osslerror("EVP_KDF_fetch");
- goto fail;
- }
- if ((kctx = EVP_KDF_CTX_new(kdf)) == NULL) {
- osslerror("EVP_KDF_CTX_new");
- goto fail;
- }
- if (EVP_KDF_derive(kctx, out, outlen, params) != 1) {
- osslerror("EVP_KDF_derive");
- goto fail;
- }
- ret = 0;
- fail:
- EVP_KDF_free(kdf);
- EVP_KDF_CTX_free(kctx);
- OSSL_set_max_threads(NULL, 0);
- return ret;
- }
- void print_usage(const char *prog_name) {
- printf("Generate strong passwords with argon2id\n");
- printf("Usage: %s [-s SALT | -x HEX] [-l LENGTH] text\n", prog_name);
- printf("Options:\n");
- printf(" -h Display this help message\n");
- printf(" -l LENGTH Password length (default %d)\n",
- CONFIG_PASS_LEN);
- printf(" -s SALT Salt\n");
- printf(" -x HEX Salt in hex\n");
- }
- static void graph(uint8_t *buf, size_t size, size_t pass_len) {
- size_t len = 0;
- for (size_t i = 0; i < size && len < pass_len; i++) {
- if (isgraph(buf[i])) {
- putchar(buf[i]);
- len++;
- }
- }
- }
- int main(int argc, char *argv[]) {
- int opt;
- uint8_t salt[1024];
- size_t salt_len = 0;
- size_t pass_len = CONFIG_PASS_LEN;
- int ret = 0;
- uint8_t buf[4096] = {0};
- static struct option long_options[] = {{0, 0, 0, 0}};
- const char *short_options = "hs:l:x:";
- /* Parse options loop */
- while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) !=
- -1) {
- switch (opt) {
- case 'h':
- print_usage(argv[0]);
- return EXIT_SUCCESS;
- case 's':
- if (salt_len) {
- fprintf(stderr, "warning: multiple salt arguments\n");
- break;
- }
- salt_len = snprintf((char *)salt, sizeof(salt), "%s", optarg);
- break;
- case 'x':
- if (salt_len) {
- fprintf(stderr, "warning: multiple salt arguments\n");
- break;
- }
- if (!OPENSSL_hexstr2buf_ex(salt, sizeof(salt), &salt_len, optarg, 0)) {
- osslerror("salt");
- return 1;
- }
- break;
- case 'l':
- pass_len = atoi(optarg);
- break;
- case '?':
- fprintf(stderr, "try '%s -h' for more information.\n", argv[0]);
- return 1;
- case ':':
- fprintf(stderr, "option -%c requires an argument.\n", optopt);
- return 1;
- default:
- abort();
- }
- }
- if (!salt_len) {
- fprintf(stderr, "salt required\n");
- return 1;
- }
- for (int i = optind; i < argc; i++) {
- if (argon2id_derive(buf, sizeof(buf), (uint8_t *)salt, salt_len, argv[i])) {
- fprintf(stderr, "argon2id_derive failed\n");
- ret = 1;
- goto exit;
- }
- graph(buf, sizeof(buf), pass_len);
- putchar('\n');
- }
- exit:
- return ret;
- }
Advertisement
Add Comment
Please, Sign In to add comment