1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 01:02:24 +00:00

Final cleanups on key import/export work. Rationalised the UI (so

that menu options are greyed out helpfully) and added documentation.

[originally from svn r1683]
This commit is contained in:
Simon Tatham 2002-05-15 20:07:11 +00:00
parent ff5241c1ed
commit de3b29f7e5
2 changed files with 205 additions and 83 deletions

View File

@ -1,4 +1,4 @@
\versionid $Id: pubkey.but,v 1.14 2002/05/11 16:45:29 simon Exp $
\versionid $Id: pubkey.but,v 1.15 2002/05/15 20:07:11 simon Exp $
\C{pubkey} Using public keys for SSH authentication
@ -330,6 +330,38 @@ find your key file. Once you select the file, PuTTYgen will ask you
for a passphrase (if necessary) and will then display the key
details in the same way as if it had just generated the key.
PuTTYgen can also load SSH2 private keys in OpenSSH's format and
\cw{ssh.com}'s format. Once you have loaded one of these key types,
you can then save it back out as a PuTTY-format key so that you can
use it with PuTTY. The passphrase will be unchanged by this process.
You may want to change the key comment before you save the key,
since OpenSSH's SSH2 key format contains no space for a comment and
\cw{ssh.com}'s default comment format is long and verbose.
\S{puttygen-export} Exporting your private key in an alternative format
\cfg{winhelp-topic}{puttygen.export}
Most SSH1 clients use a standard format for storing private keys on
disk. PuTTY uses this format as well; so if you have generated an
SSH1 private key using OpenSSH or \cw{ssh.com}'s client, you can use
it with PuTTY, and vice versa.
However, SSH2 private keys have no standard format. OpenSSH and
\cw{ssh.com} have different formats, and PuTTY's is different again.
So a key generated with one client cannot immediately be used with
another.
PuTTYgen has the ability to export private keys in OpenSSH format,
or in \cw{ssh.com} format. To do so, select an option from the
\q{Export} menu at the top of the PuTTYgen window. Exporting a key
works exactly like saving it (see \k{puttygen-savepriv}) - you need
to have typed your passphrase in beforehand, and you will be warned
if you are about to save a key without a passphrase.
Note that the export options are only available if you have
generated an SSH2 key.
\H{pubkey-gettingready} Getting ready for public key authentication
Connect to your SSH server using PuTTY with the SSH protocol. When the

View File

@ -332,6 +332,7 @@ struct MainDlgState {
unsigned *entropy;
struct RSAKey key;
struct dss_key dsskey;
HMENU filemenu, keymenu, exportmenu;
};
static void hidemany(HWND hwnd, const int *ids, int hideit)
@ -475,45 +476,138 @@ static int save_ssh2_pubkey(char *filename, struct ssh2_userkey *key)
return 1;
}
enum {
controlidstart = 100,
IDC_QUIT,
IDC_TITLE,
IDC_BOX_KEY,
IDC_NOKEY,
IDC_GENERATING,
IDC_PROGRESS,
IDC_PKSTATIC, IDC_KEYDISPLAY,
IDC_FPSTATIC, IDC_FINGERPRINT,
IDC_COMMENTSTATIC, IDC_COMMENTEDIT,
IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT,
IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT,
IDC_BOX_ACTIONS,
IDC_GENSTATIC, IDC_GENERATE,
IDC_LOADSTATIC, IDC_LOAD,
IDC_SAVESTATIC, IDC_SAVE, IDC_SAVEPUB,
IDC_BOX_PARAMS,
IDC_TYPESTATIC, IDC_KEYSSH1, IDC_KEYSSH2RSA, IDC_KEYSSH2DSA,
IDC_BITSSTATIC, IDC_BITS,
IDC_ABOUT,
IDC_GIVEHELP,
IDC_IMPORT, IDC_EXPORT_OPENSSH, IDC_EXPORT_SSHCOM
};
static const int nokey_ids[] = { IDC_NOKEY, 0 };
static const int generating_ids[] = { IDC_GENERATING, IDC_PROGRESS, 0 };
static const int gotkey_ids[] = {
IDC_PKSTATIC, IDC_KEYDISPLAY,
IDC_FPSTATIC, IDC_FINGERPRINT,
IDC_COMMENTSTATIC, IDC_COMMENTEDIT,
IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT,
IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT, 0
};
/*
* Small UI helper function to switch the state of the main dialog
* by enabling and disabling controls and menu items.
*/
void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
{
int type;
switch (status) {
case 0: /* no key */
hidemany(hwnd, nokey_ids, FALSE);
hidemany(hwnd, generating_ids, TRUE);
hidemany(hwnd, gotkey_ids, TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 1);
EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 1);
EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 0);
EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 0);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 1);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 1);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 1);
EnableWindow(GetDlgItem(hwnd, IDC_BITS), 1);
EnableMenuItem(state->filemenu, IDC_LOAD, MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->filemenu, IDC_SAVE, MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->filemenu, IDC_SAVEPUB, MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->keymenu, IDC_GENERATE, MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->keymenu, IDC_KEYSSH1, MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->keymenu, IDC_KEYSSH2RSA, MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->keymenu, IDC_KEYSSH2DSA, MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->exportmenu, IDC_EXPORT_OPENSSH,
MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->exportmenu, IDC_EXPORT_SSHCOM,
MF_GRAYED|MF_BYCOMMAND);
break;
case 1: /* generating key */
hidemany(hwnd, nokey_ids, TRUE);
hidemany(hwnd, generating_ids, FALSE);
hidemany(hwnd, gotkey_ids, TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 0);
EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 0);
EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 0);
EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 0);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 0);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 0);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 0);
EnableWindow(GetDlgItem(hwnd, IDC_BITS), 0);
EnableMenuItem(state->filemenu, IDC_LOAD, MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->filemenu, IDC_SAVE, MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->filemenu, IDC_SAVEPUB, MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->keymenu, IDC_GENERATE, MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->keymenu, IDC_KEYSSH1, MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->keymenu, IDC_KEYSSH2RSA, MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->keymenu, IDC_KEYSSH2DSA, MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->exportmenu, IDC_EXPORT_OPENSSH,
MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->exportmenu, IDC_EXPORT_SSHCOM,
MF_GRAYED|MF_BYCOMMAND);
break;
case 2:
hidemany(hwnd, nokey_ids, TRUE);
hidemany(hwnd, generating_ids, TRUE);
hidemany(hwnd, gotkey_ids, FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 1);
EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 1);
EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 1);
EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 1);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 1);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 1);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 1);
EnableWindow(GetDlgItem(hwnd, IDC_BITS), 1);
EnableMenuItem(state->filemenu, IDC_LOAD, MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->filemenu, IDC_SAVE, MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->filemenu, IDC_SAVEPUB, MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->keymenu, IDC_GENERATE, MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->keymenu, IDC_KEYSSH1, MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->keymenu, IDC_KEYSSH2RSA,MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->keymenu, IDC_KEYSSH2DSA,MF_ENABLED|MF_BYCOMMAND);
/*
* Enable export menu items if and only if the key type
* supports this kind of export.
*/
type = state->ssh2 ? SSH_KEYTYPE_SSH2 : SSH_KEYTYPE_SSH1;
#define do_export_menuitem(x,y) \
EnableMenuItem(state->exportmenu, x, MF_BYCOMMAND | \
(import_target_type(y)==type?MF_ENABLED:MF_GRAYED))
do_export_menuitem(IDC_EXPORT_OPENSSH, SSH_KEYTYPE_OPENSSH);
do_export_menuitem(IDC_EXPORT_SSHCOM, SSH_KEYTYPE_SSHCOM);
#undef do_export_menuitem
break;
}
}
/*
* Dialog-box function for the main PuTTYgen dialog box.
*/
static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
enum {
controlidstart = 100,
IDC_TITLE,
IDC_BOX_KEY,
IDC_NOKEY,
IDC_GENERATING,
IDC_PROGRESS,
IDC_PKSTATIC, IDC_KEYDISPLAY,
IDC_FPSTATIC, IDC_FINGERPRINT,
IDC_COMMENTSTATIC, IDC_COMMENTEDIT,
IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT,
IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT,
IDC_BOX_ACTIONS,
IDC_GENSTATIC, IDC_GENERATE,
IDC_LOADSTATIC, IDC_LOAD,
IDC_SAVESTATIC, IDC_SAVE, IDC_SAVEPUB,
IDC_BOX_PARAMS,
IDC_TYPESTATIC, IDC_KEYSSH1, IDC_KEYSSH2RSA, IDC_KEYSSH2DSA,
IDC_BITSSTATIC, IDC_BITS,
IDC_ABOUT,
IDC_GIVEHELP,
IDC_IMPORT, IDC_EXPORT_OPENSSH, IDC_EXPORT_SSHCOM
};
static const int nokey_ids[] = { IDC_NOKEY, 0 };
static const int generating_ids[] =
{ IDC_GENERATING, IDC_PROGRESS, 0 };
static const int gotkey_ids[] = {
IDC_PKSTATIC, IDC_KEYDISPLAY,
IDC_FPSTATIC, IDC_FINGERPRINT,
IDC_COMMENTSTATIC, IDC_COMMENTEDIT,
IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT,
IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT, 0
};
static const char generating_msg[] =
"Please wait while a key is generated...";
static const char entropy_msg[] =
@ -533,33 +627,48 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
}
requested_help = FALSE;
state = smalloc(sizeof(*state));
state->generation_thread_exists = FALSE;
state->collecting_entropy = FALSE;
state->entropy = NULL;
state->key_exists = FALSE;
SetWindowLong(hwnd, GWL_USERDATA, (LONG) state);
{
HMENU menu, menu1;
menu = CreateMenu();
menu1 = CreateMenu();
AppendMenu(menu1, MF_ENABLED, IDC_GENERATE, "&Generate key pair");
AppendMenu(menu1, MF_ENABLED, IDC_LOAD, "&Load private key");
AppendMenu(menu1, MF_ENABLED, IDC_SAVEPUB, "Save p&ublic key");
AppendMenu(menu1, MF_ENABLED, IDC_SAVE, "&Save private key");
AppendMenu(menu1, MF_SEPARATOR, 0, 0);
AppendMenu(menu1, MF_ENABLED, IDC_QUIT, "E&xit");
AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&File");
state->filemenu = menu1;
menu1 = CreateMenu();
AppendMenu(menu1, MF_ENABLED, IDC_GENERATE, "&Generate key pair");
AppendMenu(menu1, MF_SEPARATOR, 0, 0);
AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH1, "SSH&1 key (RSA)");
AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2RSA, "SSH2 &RSA key");
AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2DSA, "SSH2 &DSA key");
AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&Key");
state->keymenu = menu1;
menu1 = CreateMenu();
AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_OPENSSH,
"Export &OpenSSH key");
AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_SSHCOM,
"Export &ssh.com key");
AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1,
"&Export");
state->exportmenu = menu1;
menu1 = CreateMenu();
AppendMenu(menu1, MF_ENABLED, IDC_ABOUT, "&About");
if (help_path)
AppendMenu(menu1, MF_ENABLED, IDC_GIVEHELP, "&Help");
AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&Help");
SetMenu(hwnd, menu);
@ -580,12 +689,6 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
rd.right - rd.left, rd.bottom - rd.top, TRUE);
}
state = smalloc(sizeof(*state));
state->generation_thread_exists = FALSE;
state->collecting_entropy = FALSE;
state->entropy = NULL;
state->key_exists = FALSE;
SetWindowLong(hwnd, GWL_USERDATA, (LONG) state);
{
struct ctlpos cp, cp2;
@ -632,6 +735,8 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
endbox(&cp);
}
CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2DSA, IDC_KEYSSH1);
CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1, IDC_KEYSSH2DSA,
IDC_KEYSSH1, MF_BYCOMMAND);
SetDlgItemInt(hwnd, IDC_BITS, DEFAULT_KEYSIZE, FALSE);
/*
@ -640,11 +745,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
* buttons, because with no key we obviously can't save
* anything.
*/
hidemany(hwnd, nokey_ids, FALSE);
hidemany(hwnd, generating_ids, TRUE);
hidemany(hwnd, gotkey_ids, TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 0);
EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 0);
ui_set_state(hwnd, state, 0);
return 1;
case WM_MOUSEMOVE:
@ -694,6 +795,22 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_KEYSSH1:
case IDC_KEYSSH2RSA:
case IDC_KEYSSH2DSA:
{
state = (struct MainDlgState *)
GetWindowLong(hwnd, GWL_USERDATA);
if (!IsDlgButtonChecked(hwnd, LOWORD(wParam)))
CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2DSA,
LOWORD(wParam));
CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1, IDC_KEYSSH2DSA,
LOWORD(wParam), MF_BYCOMMAND);
}
break;
case IDC_QUIT:
PostMessage(hwnd, WM_CLOSE, 0, 0);
break;
case IDC_COMMENTEDIT:
if (HIWORD(wParam) == EN_CHANGE) {
state = (struct MainDlgState *)
@ -754,19 +871,9 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
state->keysize = 256;
SetDlgItemInt(hwnd, IDC_BITS, 256, FALSE);
}
hidemany(hwnd, nokey_ids, TRUE);
hidemany(hwnd, generating_ids, FALSE);
hidemany(hwnd, gotkey_ids, TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 0);
EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 0);
EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 0);
EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 0);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 0);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 0);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 0);
EnableWindow(GetDlgItem(hwnd, IDC_BITS), 0);
state->key_exists = FALSE;
ui_set_state(hwnd, state, 1);
SetDlgItemText(hwnd, IDC_GENERATING, entropy_msg);
state->key_exists = FALSE;
state->collecting_entropy = TRUE;
/*
@ -1001,14 +1108,6 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
MessageBox(NULL, "Couldn't load private key.",
"PuTTYgen Error", MB_OK | MB_ICONERROR);
} else if (ret == 1) {
EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 1);
EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 1);
EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 1);
EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 1);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 1);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 1);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 1);
EnableWindow(GetDlgItem(hwnd, IDC_BITS), 1);
/*
* Now update the key controls with all the
* key data.
@ -1073,9 +1172,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
* Finally, hide the progress bar and show
* the key data.
*/
hidemany(hwnd, nokey_ids, TRUE);
hidemany(hwnd, generating_ids, TRUE);
hidemany(hwnd, gotkey_ids, FALSE);
ui_set_state(hwnd, state, 2);
state->key_exists = TRUE;
}
}
@ -1090,14 +1187,6 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0,
MAKELPARAM(0, PROGRESSRANGE));
SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, PROGRESSRANGE, 0);
EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 1);
EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 1);
EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 1);
EnableWindow(GetDlgItem(hwnd, IDC_SAVEPUB), 1);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 1);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 1);
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 1);
EnableWindow(GetDlgItem(hwnd, IDC_BITS), 1);
if (state->ssh2) {
if (state->is_dsa) {
state->ssh2key.data = &state->dsskey;
@ -1176,9 +1265,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
/*
* Finally, hide the progress bar and show the key data.
*/
hidemany(hwnd, nokey_ids, TRUE);
hidemany(hwnd, generating_ids, TRUE);
hidemany(hwnd, gotkey_ids, FALSE);
ui_set_state(hwnd, state, 2);
break;
case WM_HELP:
if (help_path) {
@ -1220,6 +1307,9 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
case IDC_BITSSTATIC:
case IDC_BITS:
cmd = "JI(`',`puttygen.bits')"; break;
case IDC_EXPORT_OPENSSH:
case IDC_EXPORT_SSHCOM:
cmd = "JI(`',`puttygen.export')"; break;
}
if (cmd) {
WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd);