ref: 85216d3d95505c19a57d3bbe74e8a7eca109a8e6
parent: 7bb1a9a18566ea9c8ae7f6c2fa99e448026521d2
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Aug 30 03:34:35 EDT 2019
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.
--- a/sys/include/ape/libsec.h
+++ b/sys/include/ape/libsec.h
@@ -380,6 +380,7 @@
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);
--- a/sys/include/libsec.h
+++ b/sys/include/libsec.h
@@ -372,6 +372,7 @@
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);
--- a/sys/man/8/rsa
+++ b/sys/man/8/rsa
@@ -28,6 +28,9 @@
.PP
.B rsa2asn1
[
+-a
+]
+[
.I file
]
.PP
@@ -182,6 +185,9 @@
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
--- a/sys/src/cmd/auth/rsa2asn1.c
+++ b/sys/src/cmd/auth/rsa2asn1.c
@@ -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 @@
int n;
ARGBEGIN{
+ case 'a':
+ privatekey = 1;
+ break;
default:
usage();
}ARGEND
@@ -27,10 +32,15 @@
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);
--- a/sys/src/libsec/port/x509.c
+++ b/sys/src/libsec/port/x509.c
@@ -2689,10 +2689,48 @@
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)
{
Bytes *b = encode_rsapubkey(pk);
+ 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;
+}
+
+int
+asn1encodeRSApriv(RSApriv *k, uchar *buf, int len)
+{
+ Bytes *b;
+ b = encode_rsaprivkey(k);
if(b == nil)
return -1;
if(b->len > len){