mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-26 01:32:25 +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
|
Hence, the export options are not available if you have generated an
|
||||||
SSH-1 key.
|
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
|
\H{pubkey-gettingready} Getting ready for public key authentication
|
||||||
|
|
||||||
Connect to your SSH server using PuTTY with the SSH protocol. When the
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct InitialParams {
|
||||||
|
int keybutton;
|
||||||
|
int primepolicybutton;
|
||||||
|
bool rsa_strong;
|
||||||
|
FingerprintType fptype;
|
||||||
|
int keybits;
|
||||||
|
int eccurve_index, edcurve_index;
|
||||||
|
};
|
||||||
|
|
||||||
struct MainDlgState {
|
struct MainDlgState {
|
||||||
bool generation_thread_exists;
|
bool generation_thread_exists;
|
||||||
bool key_exists;
|
bool key_exists;
|
||||||
@ -1393,15 +1402,16 @@ static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
|||||||
cp.ypos = ymax;
|
cp.ypos = ymax;
|
||||||
endbox(&cp);
|
endbox(&cp);
|
||||||
}
|
}
|
||||||
ui_set_key_type(hwnd, state, IDC_KEYSSH2RSA);
|
struct InitialParams *params = (struct InitialParams *)lParam;
|
||||||
ui_set_primepolicy(hwnd, state, IDC_PRIMEGEN_PROB);
|
ui_set_key_type(hwnd, state, params->keybutton);
|
||||||
ui_set_rsa_strong(hwnd, state, false);
|
ui_set_primepolicy(hwnd, state, params->primepolicybutton);
|
||||||
ui_set_fptype(hwnd, state, fptype_to_idc(SSH_FPTYPE_DEFAULT));
|
ui_set_rsa_strong(hwnd, state, params->rsa_strong);
|
||||||
SetDlgItemInt(hwnd, IDC_BITS, DEFAULT_KEY_BITS, false);
|
ui_set_fptype(hwnd, state, fptype_to_idc(params->fptype));
|
||||||
|
SetDlgItemInt(hwnd, IDC_BITS, params->keybits, false);
|
||||||
SendDlgItemMessage(hwnd, IDC_ECCURVE, CB_SETCURSEL,
|
SendDlgItemMessage(hwnd, IDC_ECCURVE, CB_SETCURSEL,
|
||||||
DEFAULT_ECCURVE_INDEX, 0);
|
params->eccurve_index, 0);
|
||||||
SendDlgItemMessage(hwnd, IDC_EDCURVE, CB_SETCURSEL,
|
SendDlgItemMessage(hwnd, IDC_EDCURVE, CB_SETCURSEL,
|
||||||
DEFAULT_EDCURVE_INDEX, 0);
|
params->edcurve_index, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initially, hide the progress bar and the key display,
|
* 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;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
int ret;
|
int ret;
|
||||||
|
struct InitialParams params[1];
|
||||||
|
|
||||||
dll_hijacking_protection();
|
dll_hijacking_protection();
|
||||||
|
|
||||||
@ -2024,6 +2035,16 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
|||||||
*/
|
*/
|
||||||
init_help();
|
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);
|
split_into_argv(cmdline, &argc, &argv, NULL);
|
||||||
|
|
||||||
int argbits = -1;
|
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",
|
} else if (match_opt("-restrict-acl", "-restrict_acl",
|
||||||
"-restrictacl")) {
|
"-restrictacl")) {
|
||||||
restrict_process_acl();
|
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 {
|
} else {
|
||||||
opt_error("unrecognised option '%s'\n", amo.argv[amo.index]);
|
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();
|
random_setup_special();
|
||||||
ret = DialogBox(hinst, MAKEINTRESOURCE(201), NULL, MainDlgProc) != IDOK;
|
ret = DialogBoxParam(hinst, MAKEINTRESOURCE(201), NULL, MainDlgProc,
|
||||||
|
(LPARAM)params) != IDOK;
|
||||||
|
|
||||||
cleanup_exit(ret);
|
cleanup_exit(ret);
|
||||||
return ret; /* just in case optimiser complains */
|
return ret; /* just in case optimiser complains */
|
||||||
|
Loading…
Reference in New Issue
Block a user