Guest User

argen.c

a guest
Jun 5th, 2026
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.99 KB | Source Code | 0 0
  1. /* argen.c - generate strong passwords with argon2id */
  2.  
  3. /* The author disclaims copyright to this source code and
  4.  * releases it into the public domain. In place of a legal
  5.  * notice, here is a blessing:
  6.  *
  7.  *  May you do good and not evil.
  8.  *
  9.  *  May you find forgiveness for yourself and forgive others.
  10.  *
  11.  *  May you share freely, never taking more than you give.
  12.  */
  13.  
  14. /* Build with gcc argen.c -lcrypto -o argen */
  15.  
  16. #define _GNU_SOURCE
  17. #include <assert.h>
  18. #include <ctype.h>
  19. #include <getopt.h>
  20. #include <openssl/core_names.h>
  21. #include <openssl/err.h>
  22. #include <openssl/evp.h>
  23. #include <openssl/kdf.h>
  24. #include <openssl/params.h>
  25. #include <openssl/rand.h>
  26. #include <openssl/thread.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30.  
  31. /* the parameter memcost specifies the size in KiB so
  32.  * this is about 64MB
  33.  */
  34. #define CONFIG_ARGON2_MEMCOST (64 * 1024)
  35. #define CONFIG_ARGON2_LANES 4
  36. #define CONFIG_ARGON2_THREADS 2
  37. #define CONFIG_ARGON2_ITER 128
  38. #define CONFIG_ARGON2_VERSION 0x13
  39. #define CONFIG_PASS_LEN 24
  40.  
  41. #define osslerror(s)                                                           \
  42.   fprintf(stderr, "%s: %s\n", s, ERR_reason_error_string(ERR_get_error()))
  43. static int argon2id_derive(uint8_t *out, size_t outlen, uint8_t *salt,
  44.                            size_t saltlen, char *pass) {
  45.   int ret = 1;
  46.  
  47.   EVP_KDF *kdf = NULL;
  48.   EVP_KDF_CTX *kctx = NULL;
  49.  
  50.   uint32_t lanes = CONFIG_ARGON2_LANES;
  51.   uint32_t threads = CONFIG_ARGON2_THREADS;
  52.   uint32_t memcost = CONFIG_ARGON2_MEMCOST;
  53.   uint32_t iter = CONFIG_ARGON2_ITER;
  54.   uint32_t version = CONFIG_ARGON2_VERSION;
  55.  
  56.   if (OSSL_set_max_threads(NULL, threads) != 1) {
  57.     osslerror("OSSL_set_max_threads");
  58.     goto fail;
  59.   }
  60.  
  61.   OSSL_PARAM params[] = {
  62.       OSSL_PARAM_uint32(OSSL_KDF_PARAM_THREADS, &threads),
  63.       OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_LANES, &lanes),
  64.       OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_MEMCOST, &memcost),
  65.       OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_VERSION, &version),
  66.       OSSL_PARAM_uint32(OSSL_KDF_PARAM_ITER, &iter),
  67.       OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, salt, saltlen),
  68.       OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, pass, strlen(pass)),
  69.       OSSL_PARAM_END};
  70.  
  71.   if ((kdf = EVP_KDF_fetch(NULL, "ARGON2ID", NULL)) == NULL) {
  72.     osslerror("EVP_KDF_fetch");
  73.     goto fail;
  74.   }
  75.   if ((kctx = EVP_KDF_CTX_new(kdf)) == NULL) {
  76.     osslerror("EVP_KDF_CTX_new");
  77.     goto fail;
  78.   }
  79.   if (EVP_KDF_derive(kctx, out, outlen, params) != 1) {
  80.     osslerror("EVP_KDF_derive");
  81.     goto fail;
  82.   }
  83.   ret = 0;
  84.  
  85. fail:
  86.   EVP_KDF_free(kdf);
  87.   EVP_KDF_CTX_free(kctx);
  88.   OSSL_set_max_threads(NULL, 0);
  89.   return ret;
  90. }
  91.  
  92. void print_usage(const char *prog_name) {
  93.   printf("Generate strong passwords with argon2id\n");
  94.   printf("Usage: %s [-s SALT | -x HEX] [-l LENGTH] text\n", prog_name);
  95.   printf("Options:\n");
  96.   printf("  -h                      Display this help message\n");
  97.   printf("  -l LENGTH               Password length (default %d)\n",
  98.          CONFIG_PASS_LEN);
  99.   printf("  -s SALT                 Salt\n");
  100.   printf("  -x HEX                  Salt in hex\n");
  101. }
  102.  
  103. static void graph(uint8_t *buf, size_t size, size_t pass_len) {
  104.   size_t len = 0;
  105.   for (size_t i = 0; i < size && len < pass_len; i++) {
  106.     if (isgraph(buf[i])) {
  107.       putchar(buf[i]);
  108.       len++;
  109.     }
  110.   }
  111. }
  112.  
  113. int main(int argc, char *argv[]) {
  114.   int opt;
  115.   uint8_t salt[1024];
  116.   size_t salt_len = 0;
  117.   size_t pass_len = CONFIG_PASS_LEN;
  118.   int ret = 0;
  119.   uint8_t buf[4096] = {0};
  120.  
  121.   static struct option long_options[] = {{0, 0, 0, 0}};
  122.  
  123.   const char *short_options = "hs:l:x:";
  124.  
  125.   /* Parse options loop */
  126.   while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) !=
  127.          -1) {
  128.     switch (opt) {
  129.     case 'h':
  130.       print_usage(argv[0]);
  131.       return EXIT_SUCCESS;
  132.     case 's':
  133.       if (salt_len) {
  134.         fprintf(stderr, "warning: multiple salt arguments\n");
  135.         break;
  136.       }
  137.       salt_len = snprintf((char *)salt, sizeof(salt), "%s", optarg);
  138.       break;
  139.     case 'x':
  140.       if (salt_len) {
  141.         fprintf(stderr, "warning: multiple salt arguments\n");
  142.         break;
  143.       }
  144.       if (!OPENSSL_hexstr2buf_ex(salt, sizeof(salt), &salt_len, optarg, 0)) {
  145.         osslerror("salt");
  146.         return 1;
  147.       }
  148.       break;
  149.     case 'l':
  150.       pass_len = atoi(optarg);
  151.       break;
  152.     case '?':
  153.       fprintf(stderr, "try '%s -h' for more information.\n", argv[0]);
  154.       return 1;
  155.     case ':':
  156.       fprintf(stderr, "option -%c requires an argument.\n", optopt);
  157.       return 1;
  158.     default:
  159.       abort();
  160.     }
  161.   }
  162.   if (!salt_len) {
  163.     fprintf(stderr, "salt required\n");
  164.     return 1;
  165.   }
  166.  
  167.   for (int i = optind; i < argc; i++) {
  168.     if (argon2id_derive(buf, sizeof(buf), (uint8_t *)salt, salt_len, argv[i])) {
  169.       fprintf(stderr, "argon2id_derive failed\n");
  170.       ret = 1;
  171.       goto exit;
  172.     }
  173.     graph(buf, sizeof(buf), pass_len);
  174.     putchar('\n');
  175.   }
  176.  
  177. exit:
  178.   return ret;
  179. }
  180.  
Advertisement
Add Comment
Please, Sign In to add comment