mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-25 01:02:24 +00:00
Windows PuTTYgen: support cmdgen's key-type and PPK options.
This imports the following options from command-line PuTTYgen, which all correspond to controls in Windows PuTTYgen's GUI, and let you set the GUI controls to initial values of your choice: -t <key type> -b <bits> -E <fingerprint type> --primes <prime gen policy> --strong-rsa --ppk-param <KDF parameters or PPK version etc> The idea is that if someone generates a lot of keys and has standard non-default preferences, they can make a shortcut that passes those preferences on the command line.
This commit is contained in:
parent
dc183e1649
commit
11aa9ab8f3
@ -478,6 +478,82 @@ you have generated an SSH-1 private key using OpenSSH or
|
||||
Hence, the export options are not available if you have generated an
|
||||
SSH-1 key.
|
||||
|
||||
\S{puttygen-cli} PuTTYgen command-line configuration
|
||||
|
||||
PuTTYgen supports a set of command-line options to configure many of
|
||||
the same settings you can select in the GUI. This allows you to start
|
||||
it up with your own preferences ready-selected, which might be useful
|
||||
if you generate a lot of keys. (For example, you could make a Windows
|
||||
shortcut that runs PuTTYgen with some command line options, or a batch
|
||||
file or Powershell script that you could distribute to a whole
|
||||
organisation containing your local standards.)
|
||||
|
||||
The options supported on the command line are:
|
||||
|
||||
\dt \cw{\-t} \e{keytype}
|
||||
|
||||
\dd Type of key to generate. You can select \c{rsa}, \c{dsa},
|
||||
\c{ecdsa}, \c{eddsa} or \c{rsa1}. See \k{puttygen-keytype}.
|
||||
|
||||
\dt \cw{\-b} \e{bits}
|
||||
|
||||
\dd Size of the key to generate, in bits. See \k{puttygen-strength}.
|
||||
|
||||
\dt \cw{\-\-primes} \e{method}
|
||||
|
||||
\dd Method for generating prime numbers. You can select \c{probable},
|
||||
\c{proven}, and \c{proven-even}. See \k{puttygen-primes}.
|
||||
|
||||
\dt \cw{\-\-strong-rsa}
|
||||
|
||||
\dd When generating an RSA key, make sure the prime factors of the key
|
||||
modulus are \q{strong primes}. A strong prime is a prime number chosen
|
||||
to have a particular structure that makes certain factoring algorithms
|
||||
more difficult to apply, so some security standards recommend their
|
||||
use. However, the most modern factoring algorithms are unaffected, so
|
||||
this option is probably not worth turning on \e{unless} you have a
|
||||
local standard that recommends it.
|
||||
|
||||
\dt \cw{\-\-ppk-param} \e{key}\cw{=}\e{value}\cw{,}...
|
||||
|
||||
\dd Allows setting all the same details of the PPK save file format
|
||||
described in \k{puttygen-save-params}.
|
||||
|
||||
\lcont{
|
||||
|
||||
Aspects to change are specified as a series of \e{key}\cw{=}\e{value} pairs
|
||||
separated by commas. The \e{key}s are:
|
||||
|
||||
\dt \cw{version}
|
||||
|
||||
\dd The PPK format version: either \cw{3} or \cw{2}.
|
||||
|
||||
\dt \cw{kdf}
|
||||
|
||||
\dd The variant of Argon2 to use: \cw{argon2id}, \cw{argon2i}, and
|
||||
\cw{argon2d}.
|
||||
|
||||
\dt \cw{memory}
|
||||
|
||||
\dd The amount of memory needed to decrypt the key, in Kbyte.
|
||||
|
||||
\dt \cw{time}
|
||||
|
||||
\dd Specifies how much time is required to attempt decrypting the key,
|
||||
in milliseconds.
|
||||
|
||||
\dt \cw{passes}
|
||||
|
||||
\dd Alternative to \cw{time}: specifies the number of hash passes
|
||||
required to attempt decrypting the key.
|
||||
|
||||
\dt \cw{parallelism}
|
||||
|
||||
\dd Number of parallelisable threads that can be used to decrypt the
|
||||
key.
|
||||
|
||||
}
|
||||
|
||||
\H{pubkey-gettingready} Getting ready for public key authentication
|
||||
|
||||
Connect to your SSH server using PuTTY with the SSH protocol. When the
|
||||
|
@ -629,6 +629,15 @@ static DWORD WINAPI generate_key_thread(void *param)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct InitialParams {
|
||||
int keybutton;
|
||||
int primepolicybutton;
|
||||
bool rsa_strong;
|
||||
FingerprintType fptype;
|
||||
int keybits;
|
||||
int eccurve_index, edcurve_index;
|
||||
};
|
||||
|
||||
struct MainDlgState {
|
||||
bool generation_thread_exists;
|
||||
bool key_exists;
|
||||
@ -1393,15 +1402,16 @@ static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
cp.ypos = ymax;
|
||||
endbox(&cp);
|
||||
}
|
||||
ui_set_key_type(hwnd, state, IDC_KEYSSH2RSA);
|
||||
ui_set_primepolicy(hwnd, state, IDC_PRIMEGEN_PROB);
|
||||
ui_set_rsa_strong(hwnd, state, false);
|
||||
ui_set_fptype(hwnd, state, fptype_to_idc(SSH_FPTYPE_DEFAULT));
|
||||
SetDlgItemInt(hwnd, IDC_BITS, DEFAULT_KEY_BITS, false);
|
||||
struct InitialParams *params = (struct InitialParams *)lParam;
|
||||
ui_set_key_type(hwnd, state, params->keybutton);
|
||||
ui_set_primepolicy(hwnd, state, params->primepolicybutton);
|
||||
ui_set_rsa_strong(hwnd, state, params->rsa_strong);
|
||||
ui_set_fptype(hwnd, state, fptype_to_idc(params->fptype));
|
||||
SetDlgItemInt(hwnd, IDC_BITS, params->keybits, false);
|
||||
SendDlgItemMessage(hwnd, IDC_ECCURVE, CB_SETCURSEL,
|
||||
DEFAULT_ECCURVE_INDEX, 0);
|
||||
params->eccurve_index, 0);
|
||||
SendDlgItemMessage(hwnd, IDC_EDCURVE, CB_SETCURSEL,
|
||||
DEFAULT_EDCURVE_INDEX, 0);
|
||||
params->edcurve_index, 0);
|
||||
|
||||
/*
|
||||
* Initially, hide the progress bar and the key display,
|
||||
@ -2013,6 +2023,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
||||
int argc;
|
||||
char **argv;
|
||||
int ret;
|
||||
struct InitialParams params[1];
|
||||
|
||||
dll_hijacking_protection();
|
||||
|
||||
@ -2024,6 +2035,16 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
||||
*/
|
||||
init_help();
|
||||
|
||||
params->keybutton = IDC_KEYSSH2RSA;
|
||||
params->primepolicybutton = IDC_PRIMEGEN_PROB;
|
||||
params->rsa_strong = false;
|
||||
params->fptype = SSH_FPTYPE_DEFAULT;
|
||||
params->keybits = DEFAULT_KEY_BITS;
|
||||
params->eccurve_index = DEFAULT_ECCURVE_INDEX;
|
||||
params->edcurve_index = DEFAULT_EDCURVE_INDEX;
|
||||
|
||||
save_params = ppk_save_default_parameters;
|
||||
|
||||
split_into_argv(cmdline, &argc, &argv, NULL);
|
||||
|
||||
int argbits = -1;
|
||||
@ -2052,15 +2073,151 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
||||
} else if (match_opt("-restrict-acl", "-restrict_acl",
|
||||
"-restrictacl")) {
|
||||
restrict_process_acl();
|
||||
} else if (match_optval("-t")) {
|
||||
if (!strcmp(val, "rsa") || !strcmp(val, "rsa2")) {
|
||||
params->keybutton = IDC_KEYSSH2RSA;
|
||||
} else if (!strcmp(val, "rsa1")) {
|
||||
params->keybutton = IDC_KEYSSH1;
|
||||
} else if (!strcmp(val, "dsa") || !strcmp(val, "dss")) {
|
||||
params->keybutton = IDC_KEYSSH2DSA;
|
||||
} else if (!strcmp(val, "ecdsa")) {
|
||||
params->keybutton = IDC_KEYSSH2ECDSA;
|
||||
} else if (!strcmp(val, "eddsa")) {
|
||||
params->keybutton = IDC_KEYSSH2EDDSA;
|
||||
} else if (!strcmp(val, "ed25519")) {
|
||||
params->keybutton = IDC_KEYSSH2EDDSA;
|
||||
argbits = 255;
|
||||
} else if (!strcmp(val, "ed448")) {
|
||||
params->keybutton = IDC_KEYSSH2EDDSA;
|
||||
argbits = 448;
|
||||
} else {
|
||||
opt_error("unknown key type '%s'\n", val);
|
||||
}
|
||||
} else if (match_optval("-b")) {
|
||||
argbits = atoi(val);
|
||||
} else if (match_optval("-E")) {
|
||||
if (!strcmp(val, "md5"))
|
||||
params->fptype = SSH_FPTYPE_MD5;
|
||||
else if (!strcmp(val, "sha256"))
|
||||
params->fptype = SSH_FPTYPE_SHA256;
|
||||
else
|
||||
opt_error("unknown fingerprint type '%s'\n", val);
|
||||
} else if (match_optval("-primes")) {
|
||||
if (!strcmp(val, "probable") ||
|
||||
!strcmp(val, "probabilistic")) {
|
||||
params->primepolicybutton = IDC_PRIMEGEN_PROB;
|
||||
} else if (!strcmp(val, "provable") ||
|
||||
!strcmp(val, "proven") ||
|
||||
!strcmp(val, "simple") ||
|
||||
!strcmp(val, "maurer-simple")) {
|
||||
params->primepolicybutton = IDC_PRIMEGEN_MAURER_SIMPLE;
|
||||
} else if (!strcmp(val, "provable-even") ||
|
||||
!strcmp(val, "proven-even") ||
|
||||
!strcmp(val, "even") ||
|
||||
!strcmp(val, "complex") ||
|
||||
!strcmp(val, "maurer-complex")) {
|
||||
params->primepolicybutton = IDC_PRIMEGEN_MAURER_COMPLEX;
|
||||
} else {
|
||||
opt_error("unrecognised prime-generation mode '%s'\n", val);
|
||||
}
|
||||
} else if (match_opt("-strong-rsa")) {
|
||||
params->rsa_strong = true;
|
||||
} else if (match_optval("-ppk-param", "-ppk-params")) {
|
||||
char *nextval;
|
||||
for (; val; val = nextval) {
|
||||
nextval = strchr(val, ',');
|
||||
if (nextval)
|
||||
*nextval++ = '\0';
|
||||
|
||||
char *optvalue = strchr(val, '=');
|
||||
if (!optvalue)
|
||||
opt_error("PPK parameter '%s' expected a value\n", val);
|
||||
*optvalue++ = '\0';
|
||||
|
||||
/* Non-numeric options */
|
||||
if (!strcmp(val, "kdf")) {
|
||||
if (!strcmp(optvalue, "Argon2id") ||
|
||||
!strcmp(optvalue, "argon2id")) {
|
||||
save_params.argon2_flavour = Argon2id;
|
||||
} else if (!strcmp(optvalue, "Argon2i") ||
|
||||
!strcmp(optvalue, "argon2i")) {
|
||||
save_params.argon2_flavour = Argon2i;
|
||||
} else if (!strcmp(optvalue, "Argon2d") ||
|
||||
!strcmp(optvalue, "argon2d")) {
|
||||
save_params.argon2_flavour = Argon2d;
|
||||
} else {
|
||||
opt_error("unrecognised kdf '%s'\n", optvalue);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
char *end;
|
||||
unsigned long n = strtoul(optvalue, &end, 0);
|
||||
if (!*optvalue || *end)
|
||||
opt_error("value '%s' for PPK parameter '%s': expected a "
|
||||
"number\n", optvalue, val);
|
||||
|
||||
if (!strcmp(val, "version")) {
|
||||
save_params.fmt_version = n;
|
||||
} else if (!strcmp(val, "memory") ||
|
||||
!strcmp(val, "mem")) {
|
||||
save_params.argon2_mem = n;
|
||||
} else if (!strcmp(val, "time")) {
|
||||
save_params.argon2_passes_auto = true;
|
||||
save_params.argon2_milliseconds = n;
|
||||
} else if (!strcmp(val, "passes")) {
|
||||
save_params.argon2_passes_auto = false;
|
||||
save_params.argon2_passes = n;
|
||||
} else if (!strcmp(val, "parallelism") ||
|
||||
!strcmp(val, "parallel")) {
|
||||
save_params.argon2_parallelism = n;
|
||||
} else {
|
||||
opt_error("unrecognised PPK parameter '%s'\n", val);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
opt_error("unrecognised option '%s'\n", amo.argv[amo.index]);
|
||||
}
|
||||
}
|
||||
|
||||
save_params = ppk_save_default_parameters;
|
||||
/* Translate argbits into eccurve_index and edcurve_index */
|
||||
if (argbits > 0) {
|
||||
switch (params->keybutton) {
|
||||
case IDC_KEYSSH2RSA:
|
||||
case IDC_KEYSSH1:
|
||||
case IDC_KEYSSH2DSA:
|
||||
params->keybits = argbits;
|
||||
break;
|
||||
case IDC_KEYSSH2ECDSA: {
|
||||
bool found = false;
|
||||
for (int j = 0; j < n_ec_nist_curve_lengths; j++)
|
||||
if (argbits == ec_nist_curve_lengths[j]) {
|
||||
params->eccurve_index = j;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
opt_error("unsupported ECDSA bit length %d", argbits);
|
||||
break;
|
||||
}
|
||||
case IDC_KEYSSH2EDDSA: {
|
||||
bool found = false;
|
||||
for (int j = 0; j < n_ec_ed_curve_lengths; j++)
|
||||
if (argbits == ec_ed_curve_lengths[j]) {
|
||||
params->edcurve_index = j;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
opt_error("unsupported EDDSA bit length %d", argbits);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
random_setup_special();
|
||||
ret = DialogBox(hinst, MAKEINTRESOURCE(201), NULL, MainDlgProc) != IDOK;
|
||||
ret = DialogBoxParam(hinst, MAKEINTRESOURCE(201), NULL, MainDlgProc,
|
||||
(LPARAM)params) != IDOK;
|
||||
|
||||
cleanup_exit(ret);
|
||||
return ret; /* just in case optimiser complains */
|
||||
|
Loading…
Reference in New Issue
Block a user