" -O specify output type:\n"
" private output PuTTY private key format\n"
" private-openssh export OpenSSH private key\n"
+ " private-openssh-pem export OpenSSH private key "
+ "(force old PEM format)\n"
+ " private-openssh-new export OpenSSH private key "
+ "(force new format)\n"
" private-sshcom export ssh.com private key\n"
" public standard / ssh.com public key\n"
" public-openssh OpenSSH public key\n"
Filename *infilename = NULL, *outfilename = NULL;
enum { NOKEYGEN, RSA1, RSA2, DSA, ECDSA } keytype = NOKEYGEN;
char *outfile = NULL, *outfiletmp = NULL;
- enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH, SSHCOM } outtype = PRIVATE;
+ enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH_PEM,
+ OPENSSH_NEW, SSHCOM } outtype = PRIVATE;
int bits = 2048;
char *comment = NULL, *origcomment = NULL;
int change_passphrase = FALSE;
outtype = PRIVATE;
else if (!strcmp(p, "fingerprint"))
outtype = FP;
- else if (!strcmp(p, "private-openssh"))
- outtype = OPENSSH, sshver = 2;
+ else if (!strcmp(p, "private-openssh") ||
+ !strcmp(p, "private-openssh-pem"))
+ outtype = OPENSSH_PEM, sshver = 2;
+ else if (!strcmp(p, "private-openssh-new"))
+ outtype = OPENSSH_NEW, sshver = 2;
else if (!strcmp(p, "private-sshcom"))
outtype = SSHCOM, sshver = 2;
else {
* We must save the private part when generating a new key.
*/
if (keytype != NOKEYGEN &&
- (outtype != PRIVATE && outtype != OPENSSH && outtype != SSHCOM)) {
+ (outtype != PRIVATE && outtype != OPENSSH_PEM &&
+ outtype != OPENSSH_NEW && outtype != SSHCOM)) {
fprintf(stderr, "puttygen: this would generate a new key but "
"discard the private part\n");
return 1;
break;
case SSH_KEYTYPE_SSH2:
- case SSH_KEYTYPE_OPENSSH:
+ case SSH_KEYTYPE_OPENSSH_PEM:
+ case SSH_KEYTYPE_OPENSSH_NEW:
case SSH_KEYTYPE_SSHCOM:
if (sshver == 1) {
fprintf(stderr, "puttygen: conversion from SSH-2 to SSH-1 keys"
*/
if ((intype == SSH_KEYTYPE_SSH1 && outtype == PRIVATE) ||
(intype == SSH_KEYTYPE_SSH2 && outtype == PRIVATE) ||
- (intype == SSH_KEYTYPE_OPENSSH && outtype == OPENSSH) ||
+ (intype == SSH_KEYTYPE_OPENSSH_PEM && outtype == OPENSSH_PEM) ||
+ (intype == SSH_KEYTYPE_OPENSSH_NEW && outtype == OPENSSH_NEW) ||
(intype == SSH_KEYTYPE_SSHCOM && outtype == SSHCOM)) {
if (!outfile) {
outfile = infile;
* Bomb out rather than automatically choosing to write
* a private key file to stdout.
*/
- if (outtype==PRIVATE || outtype==OPENSSH || outtype==SSHCOM) {
+ if (outtype == PRIVATE || outtype == OPENSSH_PEM ||
+ outtype == OPENSSH_NEW || outtype == SSHCOM) {
fprintf(stderr, "puttygen: need to specify an output file\n");
return 1;
}
* out a private key format, or (b) the entire input key file
* is encrypted.
*/
- if (outtype == PRIVATE || outtype == OPENSSH || outtype == SSHCOM ||
- intype == SSH_KEYTYPE_OPENSSH || intype == SSH_KEYTYPE_SSHCOM)
+ if (outtype == PRIVATE || outtype == OPENSSH_PEM ||
+ outtype == OPENSSH_NEW || outtype == SSHCOM ||
+ intype == SSH_KEYTYPE_OPENSSH_PEM ||
+ intype == SSH_KEYTYPE_OPENSSH_NEW ||
+ intype == SSH_KEYTYPE_SSHCOM)
load_encrypted = TRUE;
else
load_encrypted = FALSE;
}
break;
- case SSH_KEYTYPE_OPENSSH:
+ case SSH_KEYTYPE_OPENSSH_PEM:
+ case SSH_KEYTYPE_OPENSSH_NEW:
case SSH_KEYTYPE_SSHCOM:
ssh2key = import_ssh2(infilename, intype, passphrase, &error);
if (ssh2key) {
}
break;
- case OPENSSH:
+ case OPENSSH_PEM:
+ case OPENSSH_NEW:
case SSHCOM:
assert(sshver == 2);
assert(ssh2key);
random_ref(); /* both foreign key types require randomness,
* for IV or padding */
switch (outtype) {
- case OPENSSH:
- real_outtype = SSH_KEYTYPE_OPENSSH;
+ case OPENSSH_PEM:
+ real_outtype = SSH_KEYTYPE_OPENSSH_PEM;
+ break;
+ case OPENSSH_NEW:
+ real_outtype = SSH_KEYTYPE_OPENSSH_NEW;
break;
case SSHCOM:
real_outtype = SSH_KEYTYPE_SSHCOM;
break;
+ default:
+ assert(0 && "control flow goof");
}
ret = export_ssh2(outfilename, real_outtype, ssh2key, passphrase);
if (!ret) {
int openssh_encrypted(const Filename *filename);
struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase,
const char **errmsg_p);
-int openssh_write(const Filename *filename, struct ssh2_userkey *key,
- char *passphrase);
+int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key,
+ char *passphrase);
+int openssh_new_write(const Filename *filename, struct ssh2_userkey *key,
+ char *passphrase);
int sshcom_encrypted(const Filename *filename, char **comment);
struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase,
*/
int import_possible(int type)
{
- if (type == SSH_KEYTYPE_OPENSSH)
+ if (type == SSH_KEYTYPE_OPENSSH_PEM)
+ return 1;
+ if (type == SSH_KEYTYPE_OPENSSH_NEW)
return 1;
if (type == SSH_KEYTYPE_SSHCOM)
return 1;
*/
int import_encrypted(const Filename *filename, int type, char **comment)
{
- if (type == SSH_KEYTYPE_OPENSSH) {
+ if (type == SSH_KEYTYPE_OPENSSH_PEM || type == SSH_KEYTYPE_OPENSSH_NEW) {
/* OpenSSH doesn't do key comments */
*comment = dupstr(filename_to_str(filename));
return openssh_encrypted(filename);
struct ssh2_userkey *import_ssh2(const Filename *filename, int type,
char *passphrase, const char **errmsg_p)
{
- if (type == SSH_KEYTYPE_OPENSSH)
+ if (type == SSH_KEYTYPE_OPENSSH_PEM || type == SSH_KEYTYPE_OPENSSH_NEW)
return openssh_read(filename, passphrase, errmsg_p);
if (type == SSH_KEYTYPE_SSHCOM)
return sshcom_read(filename, passphrase, errmsg_p);
int export_ssh2(const Filename *filename, int type,
struct ssh2_userkey *key, char *passphrase)
{
- if (type == SSH_KEYTYPE_OPENSSH)
- return openssh_write(filename, key, passphrase);
+ if (type == SSH_KEYTYPE_OPENSSH_PEM)
+ return openssh_pem_write(filename, key, passphrase);
+ if (type == SSH_KEYTYPE_OPENSSH_NEW)
+ return openssh_new_write(filename, key, passphrase);
if (type == SSH_KEYTYPE_SSHCOM)
return sshcom_write(filename, key, passphrase);
return 0;
/* ----------------------------------------------------------------------
* Code to read and write OpenSSH private keys.
+ *
+ * These come in two more or less entirely different formats, except
+ * that the base64 wrapper is similar enough to handle with the same
+ * code. Accordingly, there's just one function to load OpenSSH keys
+ * in both formats, but separate functions to write the two formats.
*/
typedef enum {
return retval;
}
-int openssh_write(const Filename *filename, struct ssh2_userkey *key,
- char *passphrase)
+int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key,
+ char *passphrase)
{
unsigned char *pubblob, *privblob, *spareblob;
int publen, privlen, sparelen = 0;
return ret;
}
+int openssh_new_write(const Filename *filename, struct ssh2_userkey *key,
+ char *passphrase)
+{
+ return FALSE;
+}
+
/* ----------------------------------------------------------------------
* Code to read ssh.com private keys.
*/
SSH_KEYTYPE_UNOPENABLE,
SSH_KEYTYPE_UNKNOWN,
SSH_KEYTYPE_SSH1, SSH_KEYTYPE_SSH2,
- SSH_KEYTYPE_OPENSSH, SSH_KEYTYPE_SSHCOM
+ SSH_KEYTYPE_OPENSSH_PEM,
+ SSH_KEYTYPE_OPENSSH_NEW,
+ SSH_KEYTYPE_SSHCOM
};
int key_type(const Filename *filename);
char *key_type_to_str(int type);
char buf[32];
const char putty2_sig[] = "PuTTY-User-Key-File-";
const char sshcom_sig[] = "---- BEGIN SSH2 ENCRYPTED PRIVAT";
+ const char openssh_new_sig[] = "-----BEGIN OPENSSH PRIVATE KEY";
const char openssh_sig[] = "-----BEGIN ";
int i;
return SSH_KEYTYPE_SSH1;
if (!memcmp(buf, putty2_sig, sizeof(putty2_sig)-1))
return SSH_KEYTYPE_SSH2;
+ if (!memcmp(buf, openssh_new_sig, sizeof(openssh_new_sig)-1))
+ return SSH_KEYTYPE_OPENSSH_NEW;
if (!memcmp(buf, openssh_sig, sizeof(openssh_sig)-1))
- return SSH_KEYTYPE_OPENSSH;
+ return SSH_KEYTYPE_OPENSSH_PEM;
if (!memcmp(buf, sshcom_sig, sizeof(sshcom_sig)-1))
return SSH_KEYTYPE_SSHCOM;
return SSH_KEYTYPE_UNKNOWN; /* unrecognised or EOF */
case SSH_KEYTYPE_UNKNOWN: return "not a private key"; break;
case SSH_KEYTYPE_SSH1: return "SSH-1 private key"; break;
case SSH_KEYTYPE_SSH2: return "PuTTY SSH-2 private key"; break;
- case SSH_KEYTYPE_OPENSSH: return "OpenSSH SSH-2 private key"; break;
+ case SSH_KEYTYPE_OPENSSH_PEM: return "OpenSSH SSH-2 private key (old PEM format)"; break;
+ case SSH_KEYTYPE_OPENSSH_NEW: return "OpenSSH SSH-2 private key (new format)"; break;
case SSH_KEYTYPE_SSHCOM: return "ssh.com SSH-2 private key"; break;
default: return "INTERNAL ERROR"; break;
}
IDC_BITSSTATIC, IDC_BITS,
IDC_ABOUT,
IDC_GIVEHELP,
- IDC_IMPORT, IDC_EXPORT_OPENSSH, IDC_EXPORT_SSHCOM
+ IDC_IMPORT,
+ IDC_EXPORT_OPENSSH_PEM, IDC_EXPORT_OPENSSH_NEW,
+ IDC_EXPORT_SSHCOM
};
static const int nokey_ids[] = { IDC_NOKEY, 0 };
EnableMenuItem(state->keymenu, IDC_KEYSSH2ECDSA,
MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->cvtmenu, IDC_IMPORT, MF_ENABLED|MF_BYCOMMAND);
- EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH,
+ EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH_PEM,
+ MF_GRAYED|MF_BYCOMMAND);
+ EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH_NEW,
MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->cvtmenu, IDC_EXPORT_SSHCOM,
MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->keymenu, IDC_KEYSSH2ECDSA,
MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->cvtmenu, IDC_IMPORT, MF_GRAYED|MF_BYCOMMAND);
- EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH,
+ EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH_PEM,
+ MF_GRAYED|MF_BYCOMMAND);
+ EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH_NEW,
MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->cvtmenu, IDC_EXPORT_SSHCOM,
MF_GRAYED|MF_BYCOMMAND);
#define do_export_menuitem(x,y) \
EnableMenuItem(state->cvtmenu, 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_OPENSSH_PEM, SSH_KEYTYPE_OPENSSH_PEM);
+ do_export_menuitem(IDC_EXPORT_OPENSSH_NEW, SSH_KEYTYPE_OPENSSH_NEW);
do_export_menuitem(IDC_EXPORT_SSHCOM, SSH_KEYTYPE_SSHCOM);
#undef do_export_menuitem
break;
menu1 = CreateMenu();
AppendMenu(menu1, MF_ENABLED, IDC_IMPORT, "&Import key");
AppendMenu(menu1, MF_SEPARATOR, 0, 0);
- AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_OPENSSH,
- "Export &OpenSSH key");
+ AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_OPENSSH_PEM,
+ "Export &OpenSSH key (old PEM format)");
+ AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_OPENSSH_NEW,
+ "Export &OpenSSH key (new format)");
AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_SSHCOM,
"Export &ssh.com key");
AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1,
}
break;
case IDC_SAVE:
- case IDC_EXPORT_OPENSSH:
+ case IDC_EXPORT_OPENSSH_PEM:
+ case IDC_EXPORT_OPENSSH_NEW:
case IDC_EXPORT_SSHCOM:
if (HIWORD(wParam) != BN_CLICKED)
break;
else
realtype = SSH_KEYTYPE_SSH1;
- if (LOWORD(wParam) == IDC_EXPORT_OPENSSH)
- type = SSH_KEYTYPE_OPENSSH;
+ if (LOWORD(wParam) == IDC_EXPORT_OPENSSH_PEM)
+ type = SSH_KEYTYPE_OPENSSH_PEM;
+ else if (LOWORD(wParam) == IDC_EXPORT_OPENSSH_NEW)
+ type = SSH_KEYTYPE_OPENSSH_NEW;
else if (LOWORD(wParam) == IDC_EXPORT_SSHCOM)
type = SSH_KEYTYPE_SSHCOM;
else
case IDC_BITS:
topic = WINHELP_CTX_puttygen_bits; break;
case IDC_IMPORT:
- case IDC_EXPORT_OPENSSH:
+ case IDC_EXPORT_OPENSSH_PEM:
+ case IDC_EXPORT_OPENSSH_NEW:
case IDC_EXPORT_SSHCOM:
topic = WINHELP_CTX_puttygen_conversions; break;
}