Skip to content

Commit 5679171

Browse files
committed
initial export/import formats
1 parent 4c20232 commit 5679171

File tree

4 files changed

+171
-48
lines changed

4 files changed

+171
-48
lines changed

src/NodeRSA.js

Lines changed: 42 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ var ber = require('asn1').Ber;
1313
var _ = require('lodash');
1414
var utils = require('./utils');
1515
var schemes = require('./schemes/schemes.js');
16+
var formats = require('./formats/formats.js');
1617

1718
var PUBLIC_RSA_OID = '1.2.840.113549.1.1.1';
1819

@@ -25,6 +26,9 @@ module.exports = (function () {
2526
var DEFAULT_ENCRYPTION_SCHEME = 'pkcs1_oaep';
2627
var DEFAULT_SIGNING_SCHEME = 'pkcs1';
2728

29+
var DEFAULT_EXPORT_PRIVATE_FORMAT = 'pkcs1';
30+
var DEFAULT_EXPORT_PUBLIC_FORMAT = 'pkcs8';
31+
2832
/**
2933
* @param key {string|buffer|object} Key in PEM format, or data for generate key {b: bits, e: exponent}
3034
* @constructor
@@ -142,7 +146,7 @@ module.exports = (function () {
142146
}
143147

144148
this.keyPair.generate(bits, exp.toString(16));
145-
this.$recalculateCache();
149+
this.$cache = {};
146150
return this;
147151
};
148152

@@ -162,7 +166,7 @@ module.exports = (function () {
162166
} else
163167
throw Error('Invalid PEM format');
164168

165-
this.$recalculateCache();
169+
this.$cache = {};
166170
};
167171

168172
/**
@@ -251,7 +255,7 @@ module.exports = (function () {
251255
*/
252256
NodeRSA.prototype.encrypt = function (buffer, encoding, source_encoding) {
253257
try {
254-
var res = this.keyPair.encrypt(this.$getDataForEcrypt(buffer, source_encoding));
258+
var res = this.keyPair.encrypt(this.$getDataForEncrypt(buffer, source_encoding));
255259

256260
if (encoding == 'buffer' || !encoding) {
257261
return res;
@@ -295,7 +299,7 @@ module.exports = (function () {
295299
if (!this.isPrivate()) {
296300
throw Error("It is not private key");
297301
}
298-
var res = this.keyPair.sign(this.$getDataForEcrypt(buffer, source_encoding));
302+
var res = this.keyPair.sign(this.$getDataForEncrypt(buffer, source_encoding));
299303

300304
if (encoding && encoding != 'buffer') {
301305
res = res.toString(encoding);
@@ -317,21 +321,45 @@ module.exports = (function () {
317321
throw Error("It is not public key");
318322
}
319323
signature_encoding = (!signature_encoding || signature_encoding == 'buffer' ? null : signature_encoding);
320-
return this.keyPair.verify(this.$getDataForEcrypt(buffer, source_encoding), signature, signature_encoding);
324+
return this.keyPair.verify(this.$getDataForEncrypt(buffer, source_encoding), signature, signature_encoding);
321325
};
322326

323-
NodeRSA.prototype.exportPrivate = function () {
327+
NodeRSA.prototype.exportPrivate = function (format) {
324328
if (!this.isPrivate()) {
325329
throw Error("It is not private key");
326330
}
327-
return this.$cache.privatePEM;
331+
332+
format = format || DEFAULT_EXPORT_PRIVATE_FORMAT;
333+
if (this.$cache.privateKey && this.$cache.privateKey[format]) {
334+
return this.$cache.privateKey[format];
335+
} else {
336+
var fmt = format.split('-');
337+
if (!formats.isPrivateExport(fmt[0])) {
338+
throw Error('Unsupported private key export format');
339+
}
340+
341+
this.$cache.privateKey = this.$cache.privateKey || {};
342+
return this.$cache.privateKey[format] = formats[fmt[0]].privateExport(this.keyPair, fmt[1]);
343+
}
328344
};
329345

330-
NodeRSA.prototype.exportPublic = function () {
346+
NodeRSA.prototype.exportPublic = function (format) {
331347
if (!this.isPublic()) {
332348
throw Error("It is not public key");
333349
}
334-
return this.$cache.publicPEM;
350+
351+
format = format || DEFAULT_EXPORT_PUBLIC_FORMAT;
352+
if (this.$cache.publicKey && this.$cache.publicKey[format]) {
353+
return this.$cache.publicKey[format];
354+
} else {
355+
var fmt = format.split('-');
356+
if (!formats.isPublicExport(fmt[0])) {
357+
throw Error('Unsupported public key export format');
358+
}
359+
360+
this.$cache.publicKey = this.$cache.publicKey || {};
361+
return this.$cache.publicKey[format] = formats[fmt[0]].publicExport(this.keyPair, fmt[1]);
362+
}
335363
};
336364

337365
NodeRSA.prototype.getKeySize = function () {
@@ -349,7 +377,7 @@ module.exports = (function () {
349377
* @param encoding {string} - optional. Encoding for given string. Default utf8.
350378
* @returns {Buffer}
351379
*/
352-
NodeRSA.prototype.$getDataForEcrypt = function (buffer, encoding) {
380+
NodeRSA.prototype.$getDataForEncrypt = function (buffer, encoding) {
353381
if (_.isString(buffer) || _.isNumber(buffer)) {
354382
return new Buffer('' + buffer, encoding || 'utf8');
355383
} else if (Buffer.isBuffer(buffer)) {
@@ -383,16 +411,15 @@ module.exports = (function () {
383411
* private
384412
* Recalculating properties
385413
*/
386-
NodeRSA.prototype.$recalculateCache = function () {
414+
/*NodeRSA.prototype.$recalculateCache = function () {
387415
this.$cache.privatePEM = this.$makePrivatePEM();
388-
this.$cache.publicPEM = this.$makePublicPEM();
389-
};
416+
};*/
390417

391418
/**
392419
* private
393420
* @returns {string} private PEM string
394421
*/
395-
NodeRSA.prototype.$makePrivatePEM = function () {
422+
/*NodeRSA.prototype.$makePrivatePEM = function () {
396423
if (!this.isPrivate()) {
397424
return null;
398425
}
@@ -424,40 +451,7 @@ module.exports = (function () {
424451
utils.linebrk(writer.buffer.toString('base64'), 64) +
425452
'\n-----END RSA PRIVATE KEY-----';
426453
};
427-
428-
/**
429-
* private
430-
* @returns {string} public PEM string
431-
*/
432-
NodeRSA.prototype.$makePublicPEM = function () {
433-
if (!this.isPublic()) {
434-
return null;
435-
}
436-
437-
var n = this.keyPair.n.toBuffer();
438-
var length = n.length + 512; // magic
439-
440-
var bodyWriter = new ber.Writer({size: length});
441-
bodyWriter.writeByte(0);
442-
bodyWriter.startSequence();
443-
bodyWriter.writeBuffer(n, 2);
444-
bodyWriter.writeInt(this.keyPair.e);
445-
bodyWriter.endSequence();
446-
var body = bodyWriter.buffer;
447-
448-
var writer = new ber.Writer({size: length});
449-
writer.startSequence();
450-
writer.startSequence();
451-
writer.writeOID(PUBLIC_RSA_OID);
452-
writer.writeNull();
453-
writer.endSequence();
454-
writer.writeBuffer(body, 3);
455-
writer.endSequence();
456-
457-
return '-----BEGIN PUBLIC KEY-----\n' +
458-
utils.linebrk(writer.buffer.toString('base64'), 64) +
459-
'\n-----END PUBLIC KEY-----';
460-
};
454+
*/
461455

462456
return NodeRSA;
463457
})();

src/formats/formats.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module.exports = {
2+
pkcs1: require('./pkcs1'),
3+
pkcs8: require('./pkcs8'),
4+
5+
isPrivateExport: function(format) {
6+
return module.exports[format] && typeof module.exports[format].privateExport === 'function';
7+
},
8+
9+
isPrivateImport: function(format) {
10+
return module.exports[format] && typeof module.exports[format].privateImport === 'function';
11+
},
12+
13+
isPublicExport: function(format) {
14+
return module.exports[format] && typeof module.exports[format].publicExport === 'function';
15+
},
16+
17+
isPublicImport: function(format) {
18+
return module.exports[format] && typeof module.exports[format].publicImport === 'function';
19+
}
20+
};

src/formats/pkcs1.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
var ber = require('asn1').Ber;
2+
var utils = require('../utils');
3+
4+
module.exports = {
5+
privateExport: function(key, options) {
6+
options = options || {};
7+
8+
var der = module.exports.privateDerEncode(key);
9+
if (options.binary) {
10+
return der;
11+
} else {
12+
return '-----BEGIN RSA PRIVATE KEY-----\n' + utils.linebrk(der.toString('base64'), 64) + '\n-----END RSA PRIVATE KEY-----';
13+
}
14+
},
15+
16+
publicExport: function(key, options) {
17+
options = options || {};
18+
19+
var der = module.exports.publicDerEncode(key);
20+
if (options.binary) {
21+
return der;
22+
} else {
23+
return '-----BEGIN RSA PUBLIC KEY-----\n' + utils.linebrk(der.toString('base64'), 64) + '\n-----END RSA PUBLIC KEY-----';
24+
}
25+
},
26+
27+
privateDerEncode: function(key) {
28+
var n = key.n.toBuffer();
29+
var d = key.d.toBuffer();
30+
var p = key.p.toBuffer();
31+
var q = key.q.toBuffer();
32+
var dmp1 = key.dmp1.toBuffer();
33+
var dmq1 = key.dmq1.toBuffer();
34+
var coeff = key.coeff.toBuffer();
35+
36+
var length = n.length + d.length + p.length + q.length + dmp1.length + dmq1.length + coeff.length + 512; // magic
37+
var writer = new ber.Writer({size: length});
38+
39+
writer.startSequence();
40+
writer.writeInt(0);
41+
writer.writeBuffer(n, 2);
42+
writer.writeInt(key.e);
43+
writer.writeBuffer(d, 2);
44+
writer.writeBuffer(p, 2);
45+
writer.writeBuffer(q, 2);
46+
writer.writeBuffer(dmp1, 2);
47+
writer.writeBuffer(dmq1, 2);
48+
writer.writeBuffer(coeff, 2);
49+
writer.endSequence();
50+
51+
return writer.buffer;
52+
},
53+
54+
publicDerEncode: function (key) {
55+
var n = key.n.toBuffer();
56+
var length = n.length + 512; // magic
57+
58+
var bodyWriter = new ber.Writer({size: length});
59+
bodyWriter.startSequence();
60+
bodyWriter.writeBuffer(n, 2);
61+
bodyWriter.writeInt(key.e);
62+
bodyWriter.endSequence();
63+
return bodyWriter.buffer;
64+
}
65+
};

src/formats/pkcs8.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
var ber = require('asn1').Ber;
2+
var PUBLIC_RSA_OID = '1.2.840.113549.1.1.1';
3+
var utils = require('../utils');
4+
5+
module.exports = {
6+
publicExport: function(key, options) {
7+
options = options || {};
8+
9+
var der = module.exports.publicDerEncode(key);
10+
if (options.binary) {
11+
return der;
12+
} else {
13+
return '-----BEGIN PUBLIC KEY-----\n' + utils.linebrk(der.toString('base64'), 64) + '\n-----END PUBLIC KEY-----';
14+
}
15+
},
16+
17+
publicImport: function(key) {
18+
19+
},
20+
21+
publicDerEncode: function (key) {
22+
var n = key.n.toBuffer();
23+
var length = n.length + 512; // magic
24+
25+
var bodyWriter = new ber.Writer({size: length});
26+
bodyWriter.writeByte(0);
27+
bodyWriter.startSequence();
28+
bodyWriter.writeBuffer(n, 2);
29+
bodyWriter.writeInt(key.e);
30+
bodyWriter.endSequence();
31+
var body = bodyWriter.buffer;
32+
33+
var writer = new ber.Writer({size: length});
34+
writer.startSequence();
35+
writer.startSequence();
36+
writer.writeOID(PUBLIC_RSA_OID);
37+
writer.writeNull();
38+
writer.endSequence();
39+
writer.writeBuffer(body, 3);
40+
writer.endSequence();
41+
42+
return writer.buffer;
43+
}
44+
};

0 commit comments

Comments
 (0)