mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Support public keys using the "ssh-ed25519" method.
This introduces a third system of elliptic curve representation and arithmetic, namely Edwards form.
This commit is contained in:
parent
541abf9258
commit
76a4b576e5
21
cmdgen.c
21
cmdgen.c
@ -269,7 +269,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
char *infile = NULL;
|
||||
Filename *infilename = NULL, *outfilename = NULL;
|
||||
enum { NOKEYGEN, RSA1, RSA2, DSA, ECDSA } keytype = NOKEYGEN;
|
||||
enum { NOKEYGEN, RSA1, RSA2, DSA, ECDSA, ED25519 } keytype = NOKEYGEN;
|
||||
char *outfile = NULL, *outfiletmp = NULL;
|
||||
enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH_PEM,
|
||||
OPENSSH_NEW, SSHCOM } outtype = PRIVATE;
|
||||
@ -444,6 +444,8 @@ int main(int argc, char **argv)
|
||||
keytype = DSA, sshver = 2;
|
||||
else if (!strcmp(p, "ecdsa"))
|
||||
keytype = ECDSA, sshver = 2;
|
||||
else if (!strcmp(p, "ed25519"))
|
||||
keytype = ED25519, sshver = 2;
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"puttygen: unknown key type `%s'\n", p);
|
||||
@ -516,6 +518,9 @@ int main(int argc, char **argv)
|
||||
case ECDSA:
|
||||
bits = 384;
|
||||
break;
|
||||
case ED25519:
|
||||
bits = 256;
|
||||
break;
|
||||
default:
|
||||
bits = 2048;
|
||||
break;
|
||||
@ -527,6 +532,11 @@ int main(int argc, char **argv)
|
||||
errs = TRUE;
|
||||
}
|
||||
|
||||
if (keytype == ED25519 && (bits != 256)) {
|
||||
fprintf(stderr, "puttygen: invalid bits for ED25519, choose 256\n");
|
||||
errs = TRUE;
|
||||
}
|
||||
|
||||
if (errs)
|
||||
return 1;
|
||||
|
||||
@ -702,6 +712,8 @@ int main(int argc, char **argv)
|
||||
strftime(default_comment, 30, "dsa-key-%Y%m%d", &tm);
|
||||
else if (keytype == ECDSA)
|
||||
strftime(default_comment, 30, "ecdsa-key-%Y%m%d", &tm);
|
||||
else if (keytype == ED25519)
|
||||
strftime(default_comment, 30, "ed25519-key-%Y%m%d", &tm);
|
||||
else
|
||||
strftime(default_comment, 30, "rsa-key-%Y%m%d", &tm);
|
||||
|
||||
@ -736,6 +748,13 @@ int main(int argc, char **argv)
|
||||
ssh2key->alg = &ssh_ecdsa_nistp521;
|
||||
}
|
||||
ssh1key = NULL;
|
||||
} else if (keytype == ED25519) {
|
||||
struct ec_key *ec = snew(struct ec_key);
|
||||
ec_edgenerate(ec, bits, progressfn, &prog);
|
||||
ssh2key = snew(struct ssh2_userkey);
|
||||
ssh2key->data = ec;
|
||||
ssh2key->alg = &ssh_ecdsa_ed25519;
|
||||
ssh1key = NULL;
|
||||
} else {
|
||||
struct RSAKey *rsakey = snew(struct RSAKey);
|
||||
rsa_generate(rsakey, bits, progressfn, &prog);
|
||||
|
1
ssh.c
1
ssh.c
@ -406,6 +406,7 @@ static void ssh_channel_destroy(struct ssh_channel *c);
|
||||
#define OUR_V2_PACKETLIMIT 0x9000UL
|
||||
|
||||
const static struct ssh_signkey *hostkey_algs[] = {
|
||||
&ssh_ecdsa_ed25519,
|
||||
&ssh_ecdsa_nistp256, &ssh_ecdsa_nistp384, &ssh_ecdsa_nistp521,
|
||||
&ssh_rsa, &ssh_dss
|
||||
};
|
||||
|
13
ssh.h
13
ssh.h
@ -124,13 +124,21 @@ struct ec_mcurve
|
||||
struct ec_point G;
|
||||
};
|
||||
|
||||
/* Edwards form curve */
|
||||
struct ec_ecurve
|
||||
{
|
||||
Bignum l, d;
|
||||
struct ec_point B;
|
||||
};
|
||||
|
||||
struct ec_curve {
|
||||
enum { EC_WEIERSTRASS, EC_MONTGOMERY } type;
|
||||
enum { EC_WEIERSTRASS, EC_MONTGOMERY, EC_EDWARDS } type;
|
||||
unsigned int fieldBits;
|
||||
Bignum p;
|
||||
union {
|
||||
struct ec_wcurve w;
|
||||
struct ec_mcurve m;
|
||||
struct ec_ecurve e;
|
||||
};
|
||||
};
|
||||
|
||||
@ -421,6 +429,7 @@ extern const struct ssh_kexes ssh_rsa_kex;
|
||||
extern const struct ssh_kexes ssh_ecdh_kex;
|
||||
extern const struct ssh_signkey ssh_dss;
|
||||
extern const struct ssh_signkey ssh_rsa;
|
||||
extern const struct ssh_signkey ssh_ecdsa_ed25519;
|
||||
extern const struct ssh_signkey ssh_ecdsa_nistp256;
|
||||
extern const struct ssh_signkey ssh_ecdsa_nistp384;
|
||||
extern const struct ssh_signkey ssh_ecdsa_nistp521;
|
||||
@ -721,6 +730,8 @@ int dsa_generate(struct dss_key *key, int bits, progfn_t pfn,
|
||||
void *pfnparam);
|
||||
int ec_generate(struct ec_key *key, int bits, progfn_t pfn,
|
||||
void *pfnparam);
|
||||
int ec_edgenerate(struct ec_key *key, int bits, progfn_t pfn,
|
||||
void *pfnparam);
|
||||
Bignum primegen(int bits, int modulus, int residue, Bignum factor,
|
||||
int phase, progfn_t pfn, void *pfnparam, unsigned firstbits);
|
||||
void invent_firstbits(unsigned *one, unsigned *two);
|
||||
|
38
sshecdsag.c
38
sshecdsag.c
@ -39,3 +39,41 @@ int ec_generate(struct ec_key *key, int bits, progfn_t pfn,
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ec_edgenerate(struct ec_key *key, int bits, progfn_t pfn,
|
||||
void *pfnparam)
|
||||
{
|
||||
struct ec_point *publicKey;
|
||||
|
||||
if (bits == 256) {
|
||||
key->publicKey.curve = ec_ed25519();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
/* EdDSA secret keys are just 32 bytes of hash preimage; the
|
||||
* 64-byte SHA-512 hash of that key will be used when signing,
|
||||
* but the form of the key stored on disk is the preimage
|
||||
* only. */
|
||||
Bignum privMax = bn_power_2(bits);
|
||||
if (!privMax) return 0;
|
||||
key->privateKey = bignum_random_in_range(Zero, privMax);
|
||||
freebn(privMax);
|
||||
if (!key->privateKey) return 0;
|
||||
}
|
||||
|
||||
publicKey = ec_public(key->privateKey, key->publicKey.curve);
|
||||
if (!publicKey) {
|
||||
freebn(key->privateKey);
|
||||
key->privateKey = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
key->publicKey.x = publicKey->x;
|
||||
key->publicKey.y = publicKey->y;
|
||||
key->publicKey.z = NULL;
|
||||
sfree(publicKey);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -569,6 +569,8 @@ const struct ssh_signkey *find_pubkey_alg_len(int namelen, const char *name)
|
||||
return &ssh_ecdsa_nistp384;
|
||||
else if (match_ssh_id(namelen, name, "ecdsa-sha2-nistp521"))
|
||||
return &ssh_ecdsa_nistp521;
|
||||
else if (match_ssh_id(namelen, name, "ssh-ed25519"))
|
||||
return &ssh_ecdsa_ed25519;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ static int CALLBACK AboutProc(HWND hwnd, UINT msg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef enum {RSA, DSA, ECDSA} keytype;
|
||||
typedef enum {RSA, DSA, ECDSA, ED25519} keytype;
|
||||
|
||||
/*
|
||||
* Thread to generate a key.
|
||||
@ -344,6 +344,8 @@ static DWORD WINAPI generate_rsa_key_thread(void *param)
|
||||
dsa_generate(params->dsskey, params->keysize, progress_update, &prog);
|
||||
else if (params->keytype == ECDSA)
|
||||
ec_generate(params->eckey, params->keysize, progress_update, &prog);
|
||||
else if (params->keytype == ED25519)
|
||||
ec_edgenerate(params->eckey, params->keysize, progress_update, &prog);
|
||||
else
|
||||
rsa_generate(params->key, params->keysize, progress_update, &prog);
|
||||
|
||||
@ -530,7 +532,7 @@ enum {
|
||||
IDC_SAVESTATIC, IDC_SAVE, IDC_SAVEPUB,
|
||||
IDC_BOX_PARAMS,
|
||||
IDC_TYPESTATIC, IDC_KEYSSH1, IDC_KEYSSH2RSA, IDC_KEYSSH2DSA,
|
||||
IDC_KEYSSH2ECDSA,
|
||||
IDC_KEYSSH2ECDSA, IDC_KEYSSH2ED25519,
|
||||
IDC_BITSSTATIC, IDC_BITS,
|
||||
IDC_ABOUT,
|
||||
IDC_GIVEHELP,
|
||||
@ -570,6 +572,7 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2ECDSA), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2ED25519), 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);
|
||||
@ -580,6 +583,8 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2DSA, MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2ECDSA,
|
||||
MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2ED25519,
|
||||
MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->cvtmenu, IDC_IMPORT, MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH_PEM,
|
||||
MF_GRAYED|MF_BYCOMMAND);
|
||||
@ -600,6 +605,7 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 0);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 0);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2ECDSA), 0);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2ED25519), 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);
|
||||
@ -610,6 +616,8 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2DSA, MF_GRAYED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2ECDSA,
|
||||
MF_GRAYED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2ED25519,
|
||||
MF_GRAYED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->cvtmenu, IDC_IMPORT, MF_GRAYED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH_PEM,
|
||||
MF_GRAYED|MF_BYCOMMAND);
|
||||
@ -630,6 +638,7 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2ECDSA), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2ED25519), 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);
|
||||
@ -640,6 +649,8 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2DSA,MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2ECDSA,
|
||||
MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2ED25519,
|
||||
MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->cvtmenu, IDC_IMPORT, MF_ENABLED|MF_BYCOMMAND);
|
||||
/*
|
||||
* Enable export menu items if and only if the key type
|
||||
@ -884,6 +895,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2RSA, "SSH-2 &RSA key");
|
||||
AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2DSA, "SSH-2 &DSA key");
|
||||
AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2ECDSA, "SSH-2 &ECDSA key");
|
||||
AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2ED25519, "SSH-2 ED&25519 key");
|
||||
AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&Key");
|
||||
state->keymenu = menu1;
|
||||
|
||||
@ -965,7 +977,8 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
"SSH-&1 (RSA)", IDC_KEYSSH1,
|
||||
"SSH-2 &RSA", IDC_KEYSSH2RSA,
|
||||
"SSH-2 &DSA", IDC_KEYSSH2DSA,
|
||||
"SSH-2 &ECDSA", IDC_KEYSSH2ECDSA, NULL);
|
||||
"SSH-2 &ECDSA", IDC_KEYSSH2ECDSA,
|
||||
"SSH-2 ED&25519", IDC_KEYSSH2ED25519, NULL);
|
||||
staticedit(&cp, "Number of &bits in a generated key:",
|
||||
IDC_BITSSTATIC, IDC_BITS, 20);
|
||||
endbox(&cp);
|
||||
@ -1044,6 +1057,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
case IDC_KEYSSH2RSA:
|
||||
case IDC_KEYSSH2DSA:
|
||||
case IDC_KEYSSH2ECDSA:
|
||||
case IDC_KEYSSH2ED25519:
|
||||
{
|
||||
state = (struct MainDlgState *)
|
||||
GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
@ -1113,6 +1127,8 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
state->keytype = DSA;
|
||||
} else if (IsDlgButtonChecked(hwnd, IDC_KEYSSH2ECDSA)) {
|
||||
state->keytype = ECDSA;
|
||||
} else if (IsDlgButtonChecked(hwnd, IDC_KEYSSH2ED25519)) {
|
||||
state->keytype = ED25519;
|
||||
}
|
||||
if (state->keysize < 256) {
|
||||
int ret = MessageBox(hwnd,
|
||||
@ -1140,6 +1156,18 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
state->keysize = 256;
|
||||
SetDlgItemInt(hwnd, IDC_BITS, 256, FALSE);
|
||||
}
|
||||
if (state->keytype == ED25519 && state->keysize != 256) {
|
||||
int ret = MessageBox(hwnd,
|
||||
"Only 256 bit Edwards elliptic"
|
||||
" curves are supported.\n"
|
||||
"Key length reset to 256. Continue?",
|
||||
"PuTTYgen Warning",
|
||||
MB_ICONWARNING | MB_OKCANCEL);
|
||||
if (ret != IDOK)
|
||||
break;
|
||||
state->keysize = 256;
|
||||
SetDlgItemInt(hwnd, IDC_BITS, 256, FALSE);
|
||||
}
|
||||
ui_set_state(hwnd, state, 1);
|
||||
SetDlgItemText(hwnd, IDC_GENERATING, entropy_msg);
|
||||
state->key_exists = FALSE;
|
||||
@ -1347,6 +1375,9 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
state->ssh2key.alg = &ssh_ecdsa_nistp384;
|
||||
else
|
||||
state->ssh2key.alg = &ssh_ecdsa_nistp521;
|
||||
} else if (state->keytype == ED25519) {
|
||||
state->ssh2key.data = &state->eckey;
|
||||
state->ssh2key.alg = &ssh_ecdsa_ed25519;
|
||||
} else {
|
||||
state->ssh2key.data = &state->key;
|
||||
state->ssh2key.alg = &ssh_rsa;
|
||||
@ -1369,6 +1400,8 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
strftime(*state->commentptr, 30, "dsa-key-%Y%m%d", &tm);
|
||||
else if (state->keytype == ECDSA)
|
||||
strftime(*state->commentptr, 30, "ecdsa-key-%Y%m%d", &tm);
|
||||
else if (state->keytype == ED25519)
|
||||
strftime(*state->commentptr, 30, "ed25519-key-%Y%m%d", &tm);
|
||||
else
|
||||
strftime(*state->commentptr, 30, "rsa-key-%Y%m%d", &tm);
|
||||
}
|
||||
@ -1460,6 +1493,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
case IDC_KEYSSH2RSA:
|
||||
case IDC_KEYSSH2DSA:
|
||||
case IDC_KEYSSH2ECDSA:
|
||||
case IDC_KEYSSH2ED25519:
|
||||
topic = WINHELP_CTX_puttygen_keytype; break;
|
||||
case IDC_BITSSTATIC:
|
||||
case IDC_BITS:
|
||||
|
Loading…
Reference in New Issue
Block a user