auth/rsa2asn1: implement private key export with -a flag (thanks kvik)

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.
This commit is contained in:
cinap_lenrek 2019-08-30 07:34:35 +02:00
parent 7bb1a9a185
commit 85216d3d95
5 changed files with 60 additions and 4 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -5,10 +5,12 @@
#include <libsec.h>
#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);

View file

@ -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)
{