[PATCH] ssh-keygen: support public key import/export using SubjectPublicKeyInfo
Alon Bar-Lev
alon.barlev at gmail.com
Sun Jul 29 04:23:17 EST 2012
ssh-keygen already supports importing and exporting ssh keys using
various formats.
The "-m PEM" which should have been the easiest to be used with
various of external application expects PKCS#1 encoded key, while
many applications use SubjectPublicKeyInfo encoded key.
This change adds SubjectPublicKeyInfo support, to ease integration
with applications.
Examples:
## convert SubjectPublicKeyInfo public key to SSH public key
$ openssl req -newkey rsa:2048 -nodes -pubkey -subj "/CN=test" \
-noout -keyout /dev/null | \
ssh-keygen -i -m SUBJECTINFO -f /proc/self/fd/0
## convert X.509 certificate to SSH public key
$ openssl req -newkey rsa:2048 -nodes -x509 -subj "/CN=test" \
-keyout /dev/null | openssl x509 -pubkey -noout | \
ssh-keygen -i -m SUBJECTINFO -f /proc/self/fd/0
## convert SSH public key to SubjectPublicKeyInfo public key
$ ssh-keygen -e -m SUBJECTINFO -f ~/.ssh/id_rsa.pub | \
openssl rsa -pubin -text
Signed-off-by: Alon Bar-Lev <alon.barlev at gmail.com>
---
ssh-keygen.1 | 6 +++-
ssh-keygen.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 69 insertions(+), 3 deletions(-)
diff --git a/ssh-keygen.1 b/ssh-keygen.1
index 41da207..88451ac 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -334,9 +334,11 @@ The supported key formats are:
(RFC 4716/SSH2 public or private key),
.Dq PKCS8
(PEM PKCS8 public key)
-or
.Dq PEM
-(PEM public key).
+(PEM public key)
+or
+.Dq SUBJECTINFO
+(SubjectPublicKeyInfo public key).
The default conversion format is
.Dq RFC4716 .
.It Fl N Ar new_passphrase
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 5fcd3a1..072c49a 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -137,7 +137,8 @@ int convert_from = 0;
enum {
FMT_RFC4716,
FMT_PKCS8,
- FMT_PEM
+ FMT_PEM,
+ FMT_SUBJECTINFO
} convert_format = FMT_RFC4716;
int print_public = 0;
int print_generic = 0;
@@ -330,6 +331,27 @@ do_convert_to_pem(Key *k)
}
static void
+do_convert_to_subjectinfo(Key *k)
+{
+ switch (key_type_plain(k->type)) {
+ case KEY_RSA:
+ if (!PEM_write_RSA_PUBKEY(stdout, k->rsa))
+ fatal("PEM_write_RSAPublicKey failed");
+ break;
+#if notyet /* OpenSSH 0.9.8 lacks this function */
+ case KEY_DSA:
+ if (!PEM_write_DSA_PUBKEY(stdout, k->dsa))
+ fatal("PEM_write_DSAPublicKey failed");
+ break;
+#endif
+ /* XXX ECDSA? */
+ default:
+ fatal("%s: unsupported key type %s", __func__, key_type(k));
+ }
+ exit(0);
+}
+
+static void
do_convert_to(struct passwd *pw)
{
Key *k;
@@ -360,6 +382,9 @@ do_convert_to(struct passwd *pw)
case FMT_PEM:
do_convert_to_pem(k);
break;
+ case FMT_SUBJECTINFO:
+ do_convert_to_subjectinfo(k);
+ break;
default:
fatal("%s: unknown key format %d", __func__, convert_format);
}
@@ -631,6 +656,38 @@ do_convert_from_pem(Key **k, int *private)
}
static void
+do_convert_from_subjectinfo(Key **k, int *private)
+{
+ FILE *fp;
+ RSA *rsa;
+#ifdef notyet
+ DSA *dsa;
+#endif
+
+ if ((fp = fopen(identity_file, "r")) == NULL)
+ fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
+ if ((rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL)) != NULL) {
+ *k = key_new(KEY_UNSPEC);
+ (*k)->type = KEY_RSA;
+ (*k)->rsa = rsa;
+ fclose(fp);
+ return;
+ }
+#if notyet /* OpenSSH 0.9.8 lacks this function */
+ rewind(fp);
+ if ((dsa = PEM_read_DSA_PUBKEY(fp, NULL, NULL, NULL)) != NULL) {
+ *k = key_new(KEY_UNSPEC);
+ (*k)->type = KEY_DSA;
+ (*k)->dsa = dsa;
+ fclose(fp);
+ return;
+ }
+ /* XXX ECDSA */
+#endif
+ fatal("%s: unrecognised subjectinfo public key format", __func__);
+}
+
+static void
do_convert_from(struct passwd *pw)
{
Key *k = NULL;
@@ -652,6 +709,9 @@ do_convert_from(struct passwd *pw)
case FMT_PEM:
do_convert_from_pem(&k, &private);
break;
+ case FMT_SUBJECTINFO:
+ do_convert_from_subjectinfo(&k, &private);
+ break;
default:
fatal("%s: unknown key format %d", __func__, convert_format);
}
@@ -2005,6 +2065,10 @@ main(int argc, char **argv)
convert_format = FMT_PEM;
break;
}
+ if (strcasecmp(optarg, "SUBJECTINFO") == 0) {
+ convert_format = FMT_SUBJECTINFO;
+ break;
+ }
fatal("Unsupported conversion format \"%s\"", optarg);
case 'n':
cert_principals = optarg;
--
1.7.8.6
More information about the openssh-unix-dev
mailing list