Skip to content

Commit b06c387

Browse files
committed
Added support for loading PEM key from Buffer (fs.readFileSync output)
Added isEmpty() method
1 parent 7fc6453 commit b06c387

File tree

5 files changed

+97
-11
lines changed

5 files changed

+97
-11
lines changed

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ Also you can use next methods:
8181

8282
```javascript
8383
key.generateKeyPair([bits], [exp]);
84-
key.loadFromPEM(pem_string);
84+
key.loadFromPEM(pem_string|buffer_contains_pem);
8585
```
8686
**bits** - key size in bits. 2048 by default.
8787
**exp** - public exponent. 65537 by default.
@@ -101,6 +101,11 @@ key.isPublic([strict]);
101101
```
102102
**strict** - if true method will return false if key pair have private exponent. Default `false`.
103103

104+
```javascript
105+
key.isEmpty();
106+
```
107+
Return `true` if key pair doesn't have any data.
108+
104109
#### Key info
105110
```javascript
106111
key.getKeySize();
@@ -150,6 +155,13 @@ Questions, comments, bug reports, and pull requests are all welcome.
150155

151156
## Changelog
152157

158+
### 0.1.54
159+
* Added support for loading PEM key from Buffer (fs.readFileSync output)
160+
* Added `isEmpty()` method
161+
162+
### 0.1.54
163+
* Improve work with not properly trimming PEM strings
164+
153165
### 0.1.50
154166
* Implemented native js signing and verifying for browsers
155167
* `options.signingAlgorithm` now takes only hash-algorithm name

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "node-rsa",
3-
"version": "0.1.53",
3+
"version": "0.1.54",
44
"description": "Node.js RSA library",
55
"main": "src/NodeRSA.js",
66
"scripts": {

src/NodeRSA.js

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@ var PUBLIC_RSA_OID = '1.2.840.113549.1.1.1';
1717

1818
module.exports = (function() {
1919
/**
20-
* @param key {string|object} Key in PEM format, or data for generate key {b: bits, e: exponent}
20+
* @param key {string|buffer|object} Key in PEM format, or data for generate key {b: bits, e: exponent}
2121
* @constructor
2222
*/
2323
function NodeRSA(key, options) {
24+
if (! this instanceof NodeRSA) {
25+
return new NodeRSA(key, options);
26+
}
27+
2428
this.keyPair = new rsa.Key();
2529
this.$cache = {};
2630

@@ -29,10 +33,10 @@ module.exports = (function() {
2933
environment: utils.detectEnvironment()
3034
}, options || {});
3135

32-
if (_.isObject(key)) {
33-
this.generateKeyPair(key.b, key.e);
34-
} else if (_.isString(key)) {
36+
if (Buffer.isBuffer(key) || _.isString(key)) {
3537
this.loadFromPEM(key);
38+
} else if (_.isObject(key)) {
39+
this.generateKeyPair(key.b, key.e);
3640
}
3741
}
3842

@@ -61,9 +65,13 @@ module.exports = (function() {
6165
* @param pem {string}
6266
*/
6367
NodeRSA.prototype.loadFromPEM = function(pem) {
64-
if (/^\s*-----BEGIN RSA PRIVATE KEY-----\s([A-Za-z0-9+/=]+\s)+-----END RSA PRIVATE KEY-----\s*$/g.test(pem)) {
68+
if (Buffer.isBuffer(pem)) {
69+
pem = pem.toString('utf8');
70+
}
71+
72+
if (/^\s*-----BEGIN RSA PRIVATE KEY-----\s*([A-Za-z0-9+/=]+\s*)+-----END RSA PRIVATE KEY-----\s*$/g.test(pem)) {
6573
this.$loadFromPrivatePEM(pem, 'base64');
66-
} else if (/^\s*-----BEGIN PUBLIC KEY-----\s([A-Za-z0-9+/=]+\s)+-----END PUBLIC KEY-----\s*$/g.test(pem)) {
74+
} else if (/^\s*-----BEGIN PUBLIC KEY-----\s*([A-Za-z0-9+/=]+\s*)+-----END PUBLIC KEY-----\s*$/g.test(pem)) {
6775
this.$loadFromPublicPEM(pem, 'base64');
6876
} else
6977
throw Error('Invalid PEM format');
@@ -126,20 +134,27 @@ module.exports = (function() {
126134
};
127135

128136
/**
129-
* Check if keypair contains private key
137+
* Check if key pair contains private key
130138
*/
131139
NodeRSA.prototype.isPrivate = function() {
132140
return this.keyPair.n && this.keyPair.e && this.keyPair.d || false;
133141
};
134142

135143
/**
136-
* Check if keypair contains public key
144+
* Check if key pair contains public key
137145
* @param strict {boolean} - public key only, return false if have private exponent
138146
*/
139147
NodeRSA.prototype.isPublic = function(strict) {
140148
return this.keyPair.n && this.keyPair.e && !(strict && this.keyPair.d) || false;
141149
};
142150

151+
/**
152+
* Check if key pair doesn't contains any data
153+
*/
154+
NodeRSA.prototype.isEmpty = function(strict) {
155+
return !(this.keyPair.n || this.keyPair.e || this.keyPair.d);
156+
};
157+
143158
/**
144159
* Encrypting data method
145160
*

test/private.key

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIICXAIBAAKBgQCCdY+EpDC/vPa335l751SBM8d5Lf4z4QZX4bc+DqTY9zVY/rmP
3+
GbTkCueKnIKApuOGMXJOaCwNH9wUftNt7T0foEwjl16uIC8m4hwSjjNL5TKqMVey
4+
Syv04oBuidv76u5yNiLC4J85lbmW3WAyYkTCbm/VJZAXNJuqCm7AVWmQMQIDAQAB
5+
AoGAEYR3oPfrE9PrzQTZNyn4zuCFCGCEobK1h1dno42T1Q5cu3Z4tB5fi79rF9Gs
6+
NFo0cvBwyNZ0E88TXi0pdrlEW6mdPgQFd3CFxrOgKt9AGpOtI1zzVOb1Uddywq/m
7+
WBPyETwEKzq7lC2nAcMUr0rlFrrDmUT2dafHeuWnFMZ/1YECQQDCtftsH9/prbgu
8+
Q4F2lOWsLz96aix/jnI8FhBmukKmfLMXjCZYYv+Dsr8TIl/iriGqcSgGkBHHoGe1
9+
nmLUZ4EHAkEAq4YcB8T9DLIYUeaS+JRWwLOejU6/rYdgxBIaGn2m0Ldp/z7lLM7g
10+
b0H5Al+7POajkAdnDclBDhyxqInHO4VvBwJBAJ25jNEpgNhqQKg5RsYoF2RDYchn
11+
+WPan+7McLzGZPc4TFrmzKkMiK7GPMHjNokJRXwr7aBjVAPBjEEy7BvjPEECQFOJ
12+
4rcKAzEewGeLREObg9Eg6nTqSMLMb52vL1V9ozR+UDrHuDilnXuyhwPX+kqEDl+E
13+
q3V0cqHb6c8rI4TizRsCQANIyhoJ33ughNzbCIknkMPKtgvLOUARnbya/bkfRexL
14+
icyYzXPNuqZDY8JZQHlshN8cCcZcYjGPYYscd2LKB6o=
15+
-----END RSA PRIVATE KEY-----

test/tests.js

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
* TODO: tests for compatibility with other rsa libraries
33
*/
44

5+
var fs = require('fs');
56
var assert = require("chai").assert;
67
var _ = require("lodash");
78
var NodeRSA = require("../src/NodeRSA");
89

10+
911
describe("NodeRSA", function(){
1012
var keySizes = [
1113
{b: 512, e: 3},
@@ -60,15 +62,27 @@ describe("NodeRSA", function(){
6062
describe("Generating keys", function() {
6163
for (var size in keySizes) {
6264
(function(size){
63-
it("should make key pair " + size.b + "-bit length and public exponent is " + (size.e ? size.e : size.e + ' and should be 65537'), function () {
65+
it("should make key pair " + size.b + "-bit length and public exponent is " + (size.e ? size.e : size.e + " and should be 65537"), function () {
6466
generatedKeys.push(new NodeRSA({b: size.b, e: size.e}));
6567
assert.instanceOf(generatedKeys[generatedKeys.length - 1].keyPair, Object);
68+
assert.equal(generatedKeys[generatedKeys.length - 1].isEmpty(), false);
6669
assert.equal(generatedKeys[generatedKeys.length - 1].getKeySize(), size.b);
6770
assert.equal(generatedKeys[generatedKeys.length - 1].getMaxMessageSize(), (size.b / 8 - 11));
6871
assert.equal(generatedKeys[generatedKeys.length - 1].keyPair.e, size.e || 65537);
6972
});
7073
})(keySizes[size]);
7174
}
75+
76+
it("should make empty key pair", function () {
77+
var key = new NodeRSA(null);
78+
assert.equal(key.isEmpty(), true);
79+
});
80+
81+
it("should make empty key pair with md5 signing option", function () {
82+
var key = new NodeRSA(null, {signingAlgorithm: 'md5'});
83+
assert.equal(key.isEmpty(), true);
84+
assert.equal(key.options.signingAlgorithm, 'md5');
85+
});
7286
});
7387

7488
describe("PEM", function(){
@@ -120,6 +134,23 @@ describe("NodeRSA", function(){
120134
var privateKeyPEMNotTrimmed = ' \n\n \n\n ' + privateKeyPEM + '\n \n \n\n ';
121135
var publicKeyPEMNotTrimmed = '\n\n\n\n ' + publicKeyPEM + '\n \n\n\n ';
122136

137+
var fileKey = __dirname + "/private.key";
138+
var fileKeyPEM = "-----BEGIN RSA PRIVATE KEY-----\n"+
139+
"MIICXAIBAAKBgQCCdY+EpDC/vPa335l751SBM8d5Lf4z4QZX4bc+DqTY9zVY/rmP\n"+
140+
"GbTkCueKnIKApuOGMXJOaCwNH9wUftNt7T0foEwjl16uIC8m4hwSjjNL5TKqMVey\n"+
141+
"Syv04oBuidv76u5yNiLC4J85lbmW3WAyYkTCbm/VJZAXNJuqCm7AVWmQMQIDAQAB\n"+
142+
"AoGAEYR3oPfrE9PrzQTZNyn4zuCFCGCEobK1h1dno42T1Q5cu3Z4tB5fi79rF9Gs\n"+
143+
"NFo0cvBwyNZ0E88TXi0pdrlEW6mdPgQFd3CFxrOgKt9AGpOtI1zzVOb1Uddywq/m\n"+
144+
"WBPyETwEKzq7lC2nAcMUr0rlFrrDmUT2dafHeuWnFMZ/1YECQQDCtftsH9/prbgu\n"+
145+
"Q4F2lOWsLz96aix/jnI8FhBmukKmfLMXjCZYYv+Dsr8TIl/iriGqcSgGkBHHoGe1\n"+
146+
"nmLUZ4EHAkEAq4YcB8T9DLIYUeaS+JRWwLOejU6/rYdgxBIaGn2m0Ldp/z7lLM7g\n"+
147+
"b0H5Al+7POajkAdnDclBDhyxqInHO4VvBwJBAJ25jNEpgNhqQKg5RsYoF2RDYchn\n"+
148+
"+WPan+7McLzGZPc4TFrmzKkMiK7GPMHjNokJRXwr7aBjVAPBjEEy7BvjPEECQFOJ\n"+
149+
"4rcKAzEewGeLREObg9Eg6nTqSMLMb52vL1V9ozR+UDrHuDilnXuyhwPX+kqEDl+E\n"+
150+
"q3V0cqHb6c8rI4TizRsCQANIyhoJ33ughNzbCIknkMPKtgvLOUARnbya/bkfRexL\n"+
151+
"icyYzXPNuqZDY8JZQHlshN8cCcZcYjGPYYscd2LKB6o=\n"+
152+
"-----END RSA PRIVATE KEY-----";
153+
123154
describe("Good cases", function () {
124155
it(".loadFromPrivatePEM() should load private key from (not trimmed) PEM string", function(){
125156
privateNodeRSA = new NodeRSA(privateKeyPEMNotTrimmed);
@@ -148,6 +179,19 @@ describe("NodeRSA", function(){
148179
it(".getPublicPEM() from private key should return public PEM string", function(){
149180
assert.equal(privateNodeRSA.getPublicPEM(), publicKeyPEM);
150181
});
182+
183+
it("should create key from buffer/fs.readFileSync output", function(){
184+
var key = new NodeRSA(fs.readFileSync(fileKey));
185+
assert.equal(key.getPrivatePEM(), fileKeyPEM);
186+
});
187+
188+
it("should load PEM from buffer/fs.readFileSync output", function(){
189+
var key = new NodeRSA();
190+
assert.equal(key.isEmpty(), true);
191+
key.loadFromPEM(fs.readFileSync(fileKey));
192+
assert.equal(key.isEmpty(), false);
193+
assert.equal(key.getPrivatePEM(), fileKeyPEM);
194+
});
151195
});
152196

153197
describe("Bad cases", function () {

0 commit comments

Comments
 (0)