Skip to content

Commit 4cc4e09

Browse files
committed
pkcs8 private export/import
1 parent ef7ed7b commit 4cc4e09

File tree

2 files changed

+120
-3
lines changed

2 files changed

+120
-3
lines changed

src/formats/pkcs1.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,42 @@ module.exports = {
8686
bodyWriter.writeInt(key.e);
8787
bodyWriter.endSequence();
8888

89-
if (options.binary) {
89+
if (options.type === 'der') {
9090
return bodyWriter.buffer;
9191
} else {
9292
return '-----BEGIN RSA PUBLIC KEY-----\n' + utils.linebrk(bodyWriter.buffer.toString('base64'), 64) + '\n-----END RSA PUBLIC KEY-----';
9393
}
9494
},
9595

96+
publicImport: function(key, data, options) {
97+
options = options || {};
98+
var buffer;
99+
100+
if (options.type !== 'der') {
101+
if (Buffer.isBuffer(data)) {
102+
data = data.toString('utf8');
103+
}
104+
105+
if (_.isString(data)) {
106+
var pem = data.replace('-----BEGIN RSA PUBLIC KEY-----', '')
107+
.replace('-----END RSA PUBLIC KEY-----', '')
108+
.replace(/\s+|\n\r|\n|\r$/gm, '');
109+
buffer = new Buffer(pem, 'base64');
110+
}
111+
} else if (Buffer.isBuffer(data)) {
112+
buffer = data;
113+
} else {
114+
throw Error('Unsupported key format');
115+
}
116+
117+
var body = new ber.Reader(buffer);
118+
body.readSequence();
119+
key.setPublic(
120+
body.readString(0x02, true), // modulus
121+
body.readString(0x02, true) // publicExponent
122+
);
123+
},
124+
96125
/**
97126
* Trying autodetect and import key
98127
* @param key

src/formats/pkcs8.js

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,95 @@ var PUBLIC_RSA_OID = '1.2.840.113549.1.1.1';
44
var utils = require('../utils');
55

66
module.exports = {
7+
privateExport: function (key, options) {
8+
options = options || {};
9+
10+
var n = key.n.toBuffer();
11+
var d = key.d.toBuffer();
12+
var p = key.p.toBuffer();
13+
var q = key.q.toBuffer();
14+
var dmp1 = key.dmp1.toBuffer();
15+
var dmq1 = key.dmq1.toBuffer();
16+
var coeff = key.coeff.toBuffer();
17+
18+
var length = n.length + d.length + p.length + q.length + dmp1.length + dmq1.length + coeff.length + 512; // magic
19+
var bodyWriter = new ber.Writer({size: length});
20+
21+
bodyWriter.startSequence();
22+
bodyWriter.writeInt(0);
23+
bodyWriter.writeBuffer(n, 2);
24+
bodyWriter.writeInt(key.e);
25+
bodyWriter.writeBuffer(d, 2);
26+
bodyWriter.writeBuffer(p, 2);
27+
bodyWriter.writeBuffer(q, 2);
28+
bodyWriter.writeBuffer(dmp1, 2);
29+
bodyWriter.writeBuffer(dmq1, 2);
30+
bodyWriter.writeBuffer(coeff, 2);
31+
bodyWriter.endSequence();
32+
33+
var writer = new ber.Writer({size: length});
34+
writer.startSequence();
35+
writer.writeInt(0);
36+
writer.startSequence();
37+
writer.writeOID(PUBLIC_RSA_OID);
38+
writer.writeNull();
39+
writer.endSequence();
40+
writer.writeBuffer(bodyWriter.buffer, 4);
41+
writer.endSequence();
42+
43+
if (options.type === 'der') {
44+
return writer.buffer;
45+
} else {
46+
return '-----BEGIN PRIVATE KEY-----\n' + utils.linebrk(writer.buffer.toString('base64'), 64) + '\n-----END PRIVATE KEY-----';
47+
}
48+
},
49+
50+
privateImport: function (key, data, options) {
51+
options = options || {};
52+
var buffer;
53+
54+
if (options.type !== 'der') {
55+
if (Buffer.isBuffer(data)) {
56+
data = data.toString('utf8');
57+
}
58+
59+
if (_.isString(data)) {
60+
var pem = data.replace('-----BEGIN PRIVATE KEY-----', '')
61+
.replace('-----END PRIVATE KEY-----', '')
62+
.replace(/\s+|\n\r|\n|\r$/gm, '');
63+
buffer = new Buffer(pem, 'base64');
64+
} else {
65+
throw Error('Unsupported key format');
66+
}
67+
} else if (Buffer.isBuffer(data)) {
68+
buffer = data;
69+
} else {
70+
throw Error('Unsupported key format');
71+
}
72+
73+
var reader = new ber.Reader(buffer);
74+
reader.readSequence();
75+
reader.readInt(0);
76+
var header = new ber.Reader(reader.readString(0x30, true));
77+
if (header.readOID(0x06, true) !== PUBLIC_RSA_OID) {
78+
throw Error('Invalid Public key format');
79+
}
80+
81+
var body = new ber.Reader(reader.readString(0x04, true));
82+
body.readSequence();
83+
body.readString(2, true); // just zero
84+
key.setPrivate(
85+
body.readString(2, true), // modulus
86+
body.readString(2, true), // publicExponent
87+
body.readString(2, true), // privateExponent
88+
body.readString(2, true), // prime1
89+
body.readString(2, true), // prime2
90+
body.readString(2, true), // exponent1 -- d mod (p1)
91+
body.readString(2, true), // exponent2 -- d mod (q-1)
92+
body.readString(2, true) // coefficient -- (inverse of q) mod p
93+
);
94+
},
95+
796
publicExport: function(key, options) {
897
options = options || {};
998

@@ -16,15 +105,14 @@ module.exports = {
16105
bodyWriter.writeBuffer(n, 2);
17106
bodyWriter.writeInt(key.e);
18107
bodyWriter.endSequence();
19-
var body = bodyWriter.buffer;
20108

21109
var writer = new ber.Writer({size: length});
22110
writer.startSequence();
23111
writer.startSequence();
24112
writer.writeOID(PUBLIC_RSA_OID);
25113
writer.writeNull();
26114
writer.endSequence();
27-
writer.writeBuffer(body, 3);
115+
writer.writeBuffer(bodyWriter.buffer, 3);
28116
writer.endSequence();
29117

30118
if (options.type === 'der') {

0 commit comments

Comments
 (0)