Skip to content

Commit c766bc6

Browse files
committed
Added import/export from/to raw key components.
Removed lodash from dependencies.
1 parent 157b9c6 commit c766bc6

File tree

11 files changed

+488
-291
lines changed

11 files changed

+488
-291
lines changed

README.md

+26-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,11 @@ key.importKey(keyData, [format]);
104104
key.exportKey([format]);
105105
```
106106

107-
* keyData — `{string|buffer}` — key in PEM string **or** Buffer containing PEM string **or** Buffer containing DER encoded data.
107+
* keyData — `{string|buffer}` — may be:
108+
* key in PEM string
109+
* Buffer containing PEM string
110+
* Buffer containing DER encoded data
111+
* Object contains key components
108112
* format — `{string}` — format id for export/import.
109113

110114
#### Format string syntax
@@ -114,6 +118,7 @@ Scheme — NodeRSA supports multiple format schemes for import/export keys:
114118

115119
* `'pkcs1'` — public key starts from `'-----BEGIN RSA PUBLIC KEY-----'` header and private key starts from `'-----BEGIN RSA PRIVATE KEY-----'` header
116120
* `'pkcs8'` — public key starts from `'-----BEGIN PUBLIC KEY-----'` header and private key starts from `'-----BEGIN PRIVATE KEY-----'` header
121+
* `'components'` — use it for import/export key from/to raw components (see example below). For private key, importing data should contain all private key components, for public key: only public exponent (`e`) and modulus (`n`). All components (except `e`) should be Buffer, `e` could be Buffer or just normal Number.
117122

118123
Key type — can be `'private'` or `'public'`. Default `'private'`<br/>
119124
Output type — can be:
@@ -139,6 +144,22 @@ var publicDer = key.exportKey('pkcs8-public-der');
139144
var privateDer = key.exportKey('pkcs1-der');
140145
```
141146

147+
```javascript
148+
key.importKey({
149+
n: new Buffer('0086fa9ba066685845fc03833a9699c8baefb53cfbf19052a7f10f1eaa30488cec1ceb752bdff2df9fad6c64b3498956e7dbab4035b4823c99a44cc57088a23783', 'hex'),
150+
e: 65537,
151+
d: new Buffer('5d2f0dd982596ef781affb1cab73a77c46985c6da2aafc252cea3f4546e80f40c0e247d7d9467750ea1321cc5aa638871b3ed96d19dcc124916b0bcb296f35e1', 'hex'),
152+
p: new Buffer('00c59419db615e56b9805cc45673a32d278917534804171edcf925ab1df203927f', 'hex'),
153+
q: new Buffer('00aee3f86b66087abc069b8b1736e38ad6af624f7ea80e70b95f4ff2bf77cd90fd', 'hex'),
154+
dmp1: new Buffer('008112f5a969fcb56f4e3a4c51a60dcdebec157ee4a7376b843487b53844e8ac85', 'hex'),
155+
dmq1: new Buffer('1a7370470e0f8a4095df40922a430fe498720e03e1f70d257c3ce34202249d21', 'hex'),
156+
coeff: new Buffer('00b399675e5e81506b729a777cc03026f0b2119853dfc5eb124610c0ab82999e45', 'hex')
157+
}, 'components');
158+
var publicComponents = key.exportKey('components-public');
159+
```
160+
161+
162+
142163
### Properties
143164

144165
#### Key testing
@@ -209,6 +230,10 @@ Questions, comments, bug reports, and pull requests are all welcome.
209230

210231
## Changelog
211232

233+
### 0.3.0
234+
* Added import/export from/to raw key components.
235+
* Removed lodash from dependencies.
236+
212237
### 0.2.30
213238
* Fixed a issue when the key was generated by 1 bit smaller than specified. It may slow down the generation of large keys.
214239

package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "node-rsa",
3-
"version": "0.2.30",
3+
"version": "0.3.0",
44
"description": "Node.js RSA library",
55
"main": "src/NodeRSA.js",
66
"scripts": {
@@ -34,10 +34,10 @@
3434
"grunt-simple-mocha": "0.4.0",
3535
"jit-grunt": "0.9.1",
3636
"chai": "2.0.0",
37-
"grunt-contrib-jshint": "0.11.0"
37+
"grunt-contrib-jshint": "0.11.0",
38+
"lodash": "^4.0.0"
3839
},
3940
"dependencies": {
40-
"asn1": "0.2.3",
41-
"lodash": "3.3.0"
41+
"asn1": "0.2.3"
4242
}
4343
}

src/NodeRSA.js

+9-9
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
var rsa = require('./libs/rsa.js');
1111
var crypt = require('crypto');
1212
var ber = require('asn1').Ber;
13-
var _ = require('lodash');
13+
var _ = require('./utils')._;
1414
var utils = require('./utils');
1515
var schemes = require('./schemes/schemes.js');
1616
var formats = require('./formats/formats.js');
@@ -31,7 +31,7 @@ module.exports = (function () {
3131
'private': 'pkcs1-private-pem',
3232
'private-der': 'pkcs1-private-der',
3333
'public': 'pkcs8-public-pem',
34-
'public-der': 'pkcs8-public-der'
34+
'public-der': 'pkcs8-public-der',
3535
};
3636

3737
/**
@@ -88,7 +88,7 @@ module.exports = (function () {
8888
if (_.isString(options.signingScheme)) {
8989
var signingScheme = options.signingScheme.toLowerCase().split('-');
9090
if (signingScheme.length == 1) {
91-
if (_.indexOf(SUPPORTED_HASH_ALGORITHMS.node, signingScheme[0]) > -1) {
91+
if (SUPPORTED_HASH_ALGORITHMS.node.indexOf(signingScheme[0]) > -1) {
9292
this.$options.signingSchemeOptions = {
9393
hash: signingScheme[0]
9494
};
@@ -115,7 +115,7 @@ module.exports = (function () {
115115
}
116116

117117
if (this.$options.signingSchemeOptions.hash &&
118-
_.indexOf(SUPPORTED_HASH_ALGORITHMS[this.$options.environment], this.$options.signingSchemeOptions.hash) == -1) {
118+
SUPPORTED_HASH_ALGORITHMS[this.$options.environment].indexOf(this.$options.signingSchemeOptions.hash) === -1) {
119119
throw Error('Unsupported hashing algorithm for ' + this.$options.environment + ' environment');
120120
}
121121
}
@@ -134,7 +134,7 @@ module.exports = (function () {
134134
}
135135

136136
if (this.$options.encryptionSchemeOptions.hash &&
137-
_.indexOf(SUPPORTED_HASH_ALGORITHMS[this.$options.environment], this.$options.encryptionSchemeOptions.hash) == -1) {
137+
SUPPORTED_HASH_ALGORITHMS[this.$options.environment].indexOf(this.$options.encryptionSchemeOptions.hash) === -1) {
138138
throw Error('Unsupported hashing algorithm for ' + this.$options.environment + ' environment');
139139
}
140140
}
@@ -164,7 +164,7 @@ module.exports = (function () {
164164

165165
/**
166166
* Importing key
167-
* @param keyData {string|buffer}
167+
* @param keyData {string|buffer|Object}
168168
* @param format {string}
169169
*/
170170
NodeRSA.prototype.importKey = function (keyData, format) {
@@ -207,7 +207,7 @@ module.exports = (function () {
207207

208208
/**
209209
* Check if key pair contains public key
210-
* @param strict {boolean} - public key only, return false if have private exponent
210+
* @param [strict] {boolean} - public key only, return false if have private exponent
211211
*/
212212
NodeRSA.prototype.isPublic = function (strict) {
213213
return this.keyPair.isPublic(strict);
@@ -306,7 +306,7 @@ module.exports = (function () {
306306
*/
307307
NodeRSA.prototype.sign = function (buffer, encoding, source_encoding) {
308308
if (!this.isPrivate()) {
309-
throw Error("It is not private key");
309+
throw Error("This is not private key");
310310
}
311311

312312
var res = this.keyPair.sign(this.$getDataForEncrypt(buffer, source_encoding));
@@ -329,7 +329,7 @@ module.exports = (function () {
329329
*/
330330
NodeRSA.prototype.verify = function (buffer, signature, source_encoding, signature_encoding) {
331331
if (!this.isPublic()) {
332-
throw Error("It is not public key");
332+
throw Error("This is not public key");
333333
}
334334
signature_encoding = (!signature_encoding || signature_encoding == 'buffer' ? null : signature_encoding);
335335
return this.keyPair.verify(this.$getDataForEncrypt(buffer, source_encoding), signature, signature_encoding);

src/formats/components.js

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
var _ = require('../utils')._;
2+
var utils = require('../utils');
3+
4+
module.exports = {
5+
privateExport: function (key, options) {
6+
return {
7+
n: key.n.toBuffer(),
8+
e: key.e,
9+
d: key.d.toBuffer(),
10+
p: key.p.toBuffer(),
11+
q: key.q.toBuffer(),
12+
dmp1: key.dmp1.toBuffer(),
13+
dmq1: key.dmq1.toBuffer(),
14+
coeff: key.coeff.toBuffer()
15+
}
16+
},
17+
18+
privateImport: function (key, data, options) {
19+
if (data.n && data.e && data.d && data.p && data.q && data.dmp1 && data.dmq1 && data.coeff) {
20+
key.setPrivate(
21+
data.n,
22+
data.e,
23+
data.d,
24+
data.p,
25+
data.q,
26+
data.dmp1,
27+
data.dmq1,
28+
data.coeff
29+
);
30+
} else {
31+
throw Error("Invalid key data");
32+
}
33+
},
34+
35+
publicExport: function (key, options) {
36+
return {
37+
n: key.n.toBuffer(),
38+
e: key.e
39+
}
40+
},
41+
42+
publicImport: function (key, data, options) {
43+
if (data.n && data.e) {
44+
key.setPublic(
45+
data.n,
46+
data.e
47+
);
48+
} else {
49+
throw Error("Invalid key data");
50+
}
51+
},
52+
53+
/**
54+
* Trying autodetect and import key
55+
* @param key
56+
* @param data
57+
*/
58+
autoImport: function (key, data) {
59+
if (data.n && data.e) {
60+
if (data.d && data.p && data.q && data.dmp1 && data.dmq1 && data.coeff) {
61+
module.exports.privateImport(key, data);
62+
return true;
63+
} else {
64+
module.exports.publicImport(key, data);
65+
return true;
66+
}
67+
}
68+
69+
return false;
70+
}
71+
};

src/formats/formats.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var _ = require('lodash');
1+
var _ = require('../utils')._;
22

33
function formatParse(format) {
44
format = format.split('-');
@@ -30,6 +30,7 @@ function formatParse(format) {
3030
module.exports = {
3131
pkcs1: require('./pkcs1'),
3232
pkcs8: require('./pkcs8'),
33+
components: require('./components'),
3334

3435
isPrivateExport: function (format) {
3536
return module.exports[format] && typeof module.exports[format].privateExport === 'function';
@@ -78,12 +79,12 @@ module.exports = {
7879
if (module.exports[fmt.scheme]) {
7980
if (fmt.keyType === 'private') {
8081
if (!key.isPrivate()) {
81-
throw Error("It is not private key");
82+
throw Error("This is not private key");
8283
}
8384
return module.exports[fmt.scheme].privateExport(key, fmt.keyOpt);
8485
} else {
8586
if (!key.isPublic()) {
86-
throw Error("It is not public key");
87+
throw Error("This is not public key");
8788
}
8889
return module.exports[fmt.scheme].publicExport(key, fmt.keyOpt);
8990
}

src/formats/pkcs1.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
var ber = require('asn1').Ber;
2-
var _ = require('lodash');
2+
var _ = require('../utils')._;
33
var utils = require('../utils');
44

55
module.exports = {

src/formats/pkcs8.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
var ber = require('asn1').Ber;
2-
var _ = require('lodash');
2+
var _ = require('../utils')._;
33
var PUBLIC_RSA_OID = '1.2.840.113549.1.1.1';
44
var utils = require('../utils');
55

src/libs/jsbn.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
*/
3838

3939
var crypt = require('crypto');
40-
var _ = require('lodash');
40+
var _ = require('../utils')._;
4141

4242
// Bits per digit
4343
var dbits;

src/libs/rsa.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
* 2014 rzcoder
4040
*/
4141

42-
var _ = require('lodash');
42+
var _ = require('../utils')._;
4343
var crypt = require('crypto');
4444
var BigInteger = require('./jsbn.js');
4545
var utils = require('../utils.js');
@@ -141,9 +141,9 @@ module.exports.Key = (function () {
141141
* @param C
142142
*/
143143
RSAKey.prototype.setPrivate = function (N, E, D, P, Q, DP, DQ, C) {
144-
if (N && E && D && N.length > 0 && E.length > 0 && D.length > 0) {
144+
if (N && E && D && N.length > 0 && (_.isNumber(E) || E.length > 0) && D.length > 0) {
145145
this.n = new BigInteger(N);
146-
this.e = utils.get32IntFromBuffer(E, 0);
146+
this.e = _.isNumber(E) ? E : utils.get32IntFromBuffer(E, 0);
147147
this.d = new BigInteger(D);
148148

149149
if (P && Q && DP && DQ && C) {
@@ -156,8 +156,9 @@ module.exports.Key = (function () {
156156
// TODO: re-calculate any missing CRT params
157157
}
158158
this.$$recalculateCache();
159-
} else
159+
} else {
160160
throw Error("Invalid RSA private key");
161+
}
161162
};
162163

163164
/**
@@ -166,12 +167,13 @@ module.exports.Key = (function () {
166167
* @param E
167168
*/
168169
RSAKey.prototype.setPublic = function (N, E) {
169-
if (N && E && N.length > 0 && E.length > 0) {
170+
if (N && E && N.length > 0 && (_.isNumber(E) || E.length > 0)) {
170171
this.n = new BigInteger(N);
171-
this.e = utils.get32IntFromBuffer(E, 0);
172+
this.e = _.isNumber(E) ? E : utils.get32IntFromBuffer(E, 0);
172173
this.$$recalculateCache();
173-
} else
174+
} else {
174175
throw Error("Invalid RSA public key");
176+
}
175177
};
176178

177179
/**

src/utils.js

+33
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,36 @@ module.exports.get32IntFromBuffer = function (buffer, offset) {
5353
return NaN;
5454
}
5555
};
56+
57+
module.exports._ = {
58+
isObject: function (value) {
59+
var type = typeof value;
60+
return !!value && (type == 'object' || type == 'function');
61+
},
62+
63+
isString: function (value) {
64+
return typeof value == 'string' || value instanceof String;
65+
},
66+
67+
isNumber: function (value) {
68+
return typeof value == 'number' || !isNaN(parseFloat(value)) && isFinite(value);
69+
},
70+
71+
/**
72+
* Returns copy of `obj` without `removeProp` field.
73+
* @param obj
74+
* @param removeProp
75+
* @returns Object
76+
*/
77+
omit: function (obj, removeProp) {
78+
var newObj = {};
79+
for (var prop in obj) {
80+
if (!obj.hasOwnProperty(prop) || prop === removeProp) {
81+
continue;
82+
}
83+
newObj[prop] = obj[prop];
84+
}
85+
86+
return newObj;
87+
}
88+
};

0 commit comments

Comments
 (0)