From 273c4f09fdb4db5544422428caa9484c4810d0d2 Mon Sep 17 00:00:00 2001 From: Christopher Wellons Date: Fri, 3 Mar 2017 18:24:34 -0500 Subject: [PATCH] Add --derive option for secret keys. --- docs.h | 1 + enchive.c | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/docs.h b/docs.h index 0b2afcc..fc0a705 100644 --- a/docs.h +++ b/docs.h @@ -21,6 +21,7 @@ static const char docs_keygen[] = "\n" " --force, -f overwrite any existing keys (default: no clobber)\n" " --plain, -u don't encrypt the secret key\n" +" --derive, -d derive secret key from a passphrase\n" "\n" "The global --pubkey and --seckey options select the filenames.\n"; diff --git a/enchive.c b/enchive.c index 33a5e49..16e7468 100644 --- a/enchive.c +++ b/enchive.c @@ -127,16 +127,17 @@ get_passphrase(char *buf, size_t len, char *prompt) } #endif -#define KEY_DERIVE_ITERATIONS 0x400000ul +#define KEY_DERIVE_ITERATIONS 0x00400000ul +#define SECKEY_DERIVE_ITERATIONS 0x01000000ul static void -key_derive(char *key, u8 *buf) +key_derive(char *key, u8 *buf, unsigned long iterations) { unsigned long i; SHA256_CTX ctx[1]; sha256_init(ctx); sha256_final(ctx, buf); - for (i = 0; i < KEY_DERIVE_ITERATIONS; i++) { + for (i = 0; i < iterations; i++) { sha256_init(ctx); sha256_update(ctx, (void *)key, strlen(key)); sha256_update(ctx, buf, sizeof(buf)); @@ -330,12 +331,12 @@ write_seckey(char *file, u8 *seckey, int encrypt) get_passphrase(pass[1], sizeof(pass[0]), "passphrase (repeat): "); if (strcmp(pass[0], pass[1]) != 0) - fatal("passphrase don't match"); + fatal("passphrases don't match"); if (!pass[0][0]) { encrypt = 0; } else { - key_derive(pass[0], key); + key_derive(pass[0], key, KEY_DERIVE_ITERATIONS); sha256_init(sha); sha256_update(sha, key, 32); @@ -395,7 +396,7 @@ load_seckey(char *file, u8 *seckey) if (memcmp(buf, empty, sizeof(empty)) != 0) { char pass[256]; get_passphrase(pass, sizeof(pass), "passphrase: "); - key_derive(pass, key); + key_derive(pass, key, KEY_DERIVE_ITERATIONS); sha256_init(sha); sha256_update(sha, key, 32); @@ -445,8 +446,9 @@ static void command_keygen(struct optparse *options) { static const struct optparse_long keygen[] = { - {"force", 'f', OPTPARSE_NONE}, - {"plain", 'u', OPTPARSE_NONE}, + {"derive", 'd', OPTPARSE_NONE}, + {"force", 'f', OPTPARSE_NONE}, + {"plain", 'u', OPTPARSE_NONE}, {0} }; @@ -456,10 +458,14 @@ command_keygen(struct optparse *options) u8 secret[32]; int clobber = 0; int encrypt = 1; + int derive = 0; int option; while ((option = optparse_long(options, keygen, 0)) != -1) { switch (option) { + case 'd': + derive = 1; + break; case 'f': clobber = 1; break; @@ -480,7 +486,20 @@ command_keygen(struct optparse *options) if (!clobber && fopen(secfile, "r")) fatal("operation would clobber %s", secfile); - generate_secret(secret); + /* Generate secret key. */ + if (derive) { + char pass[2][256]; + get_passphrase(pass[0], sizeof(pass[0]), + "secret key passphrase: "); + get_passphrase(pass[1], sizeof(pass[0]), + "secret key passphrase (repeat): "); + if (strcmp(pass[0], pass[1]) != 0) + fatal("passphrases don't match"); + key_derive(pass[0], secret, SECKEY_DERIVE_ITERATIONS); + } else { + generate_secret(secret); + } + compute_public(public, secret); write_pubkey(pubfile, public); write_seckey(secfile, secret, encrypt);