From 85216d3d95505c19a57d3bbe74e8a7eca109a8e6 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Fri, 30 Aug 2019 07:34:35 +0200 Subject: [PATCH] auth/rsa2asn1: implement private key export with -a flag (thanks kvik) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kvik writes: I needed to convert the RSA private key that was laying around in secstore into a format understood by UNIX® tools like SSH. With asn12rsa(8) we can go from the ASN.1/DER to Plan 9 format, but not back - so I wrote the libsec function asn1encodeRSApriv(2) and used it in rsa2asn1(8) by adding the -a flag which causes the full private key to be encoded and output. --- sys/include/ape/libsec.h | 1 + sys/include/libsec.h | 1 + sys/man/8/rsa | 6 ++++++ sys/src/cmd/auth/rsa2asn1.c | 18 ++++++++++++++---- sys/src/libsec/port/x509.c | 38 +++++++++++++++++++++++++++++++++++++ 5 files changed, 60 insertions(+), 4 deletions(-) diff --git a/sys/include/ape/libsec.h b/sys/include/ape/libsec.h index 68783000e..ba339f1f9 100644 --- a/sys/include/ape/libsec.h +++ b/sys/include/ape/libsec.h @@ -380,6 +380,7 @@ void X509dump(uchar *cert, int ncert); mpint* pkcs1padbuf(uchar *buf, int len, mpint *modulus, int blocktype); int pkcs1unpadbuf(uchar *buf, int len, mpint *modulus, int blocktype); int asn1encodeRSApub(RSApub *pk, uchar *buf, int len); +int asn1encodeRSApriv(RSApriv *k, uchar *buf, int len); int asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*), uchar *digest, uchar *buf, int len); diff --git a/sys/include/libsec.h b/sys/include/libsec.h index de0717c00..fd063ebc0 100644 --- a/sys/include/libsec.h +++ b/sys/include/libsec.h @@ -372,6 +372,7 @@ void X509dump(uchar *cert, int ncert); mpint* pkcs1padbuf(uchar *buf, int len, mpint *modulus, int blocktype); int pkcs1unpadbuf(uchar *buf, int len, mpint *modulus, int blocktype); int asn1encodeRSApub(RSApub *pk, uchar *buf, int len); +int asn1encodeRSApriv(RSApriv *k, uchar *buf, int len); int asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*), uchar *digest, uchar *buf, int len); diff --git a/sys/man/8/rsa b/sys/man/8/rsa index 40309c165..57a24e5ae 100644 --- a/sys/man/8/rsa +++ b/sys/man/8/rsa @@ -28,6 +28,9 @@ rsagen, rsafill, asn12rsa, rsa2asn1, rsa2pub, rsa2ssh, rsa2x509, rsa2csr \- gene .PP .B rsa2asn1 [ +-a +] +[ .I file ] .PP @@ -182,6 +185,9 @@ Comment attributes are preserved. is like .I rsa2pub but outputs the public key in ASN.1/DER format. +With the +.I -a +flag a private key is read and encoded in ANS.1/DER format. .PP .I Rsa2ssh reads a Plan 9 RSA public or private key and prints the public portion diff --git a/sys/src/cmd/auth/rsa2asn1.c b/sys/src/cmd/auth/rsa2asn1.c index 51f82282e..cf7bfc77d 100644 --- a/sys/src/cmd/auth/rsa2asn1.c +++ b/sys/src/cmd/auth/rsa2asn1.c @@ -5,10 +5,12 @@ #include #include "rsa2any.h" +int privatekey = 0; + void usage(void) { - fprint(2, "usage: auth/rsa2asn1 [file]\n"); + fprint(2, "usage: auth/rsa2asn1 [-a] [file]\n"); exits("usage"); } @@ -20,6 +22,9 @@ main(int argc, char **argv) int n; ARGBEGIN{ + case 'a': + privatekey = 1; + break; default: usage(); }ARGEND @@ -27,10 +32,15 @@ main(int argc, char **argv) if(argc > 1) usage(); - if((k = getrsakey(argc, argv, 0, nil)) == nil) + if((k = getrsakey(argc, argv, privatekey, nil)) == nil) sysfatal("%r"); - if((n = asn1encodeRSApub(&k->pub, buf, sizeof(buf))) < 0) - sysfatal("asn1encodeRSApub: %r"); + if(privatekey){ + if((n = asn1encodeRSApriv(k, buf, sizeof(buf))) < 0) + sysfatal("asn1encodeRSApriv: %r"); + }else{ + if((n = asn1encodeRSApub(&k->pub, buf, sizeof(buf))) < 0) + sysfatal("asn1encodeRSApub: %r"); + } if(write(1, buf, n) != n) sysfatal("write: %r"); exits(nil); diff --git a/sys/src/libsec/port/x509.c b/sys/src/libsec/port/x509.c index 873d19186..5b4d24952 100644 --- a/sys/src/libsec/port/x509.c +++ b/sys/src/libsec/port/x509.c @@ -2689,6 +2689,27 @@ encode_rsapubkey(RSApub *pk) return b; } +static Bytes* +encode_rsaprivkey(RSApriv *k) +{ + Bytes *b = nil; + RSApub *pk = &k->pub; + Elem e = mkseq( + mkel(mkint(0), + mkel(mkbigint(pk->n), + mkel(mpsignif(pk->ek)<32 ? mkint(mptoi(pk->ek)) : mkbigint(pk->ek), + mkel(mkbigint(k->dk), + mkel(mkbigint(k->p), + mkel(mkbigint(k->q), + mkel(mkbigint(k->kp), + mkel(mkbigint(k->kq), + mkel(mkbigint(k->c2), + nil)))))))))); + encode(e, &b); + freevalfields(&e.val); + return b; +} + int asn1encodeRSApub(RSApub *pk, uchar *buf, int len) { @@ -2705,6 +2726,23 @@ asn1encodeRSApub(RSApub *pk, uchar *buf, int len) return len; } +int +asn1encodeRSApriv(RSApriv *k, uchar *buf, int len) +{ + Bytes *b; + b = encode_rsaprivkey(k); + if(b == nil) + return -1; + if(b->len > len){ + freebytes(b); + werrstr("buffer too small"); + return -1; + } + memmove(buf, b->data, len = b->len); + freebytes(b); + return len; +} + uchar* X509rsagen(RSApriv *priv, char *subj, ulong valid[2], int *certlen) {