Skip to content

Commit 2004ea1

Browse files
committed
Merge pull request #31 from rzcoder/dev
merge with dev
2 parents efb6a90 + 66f5323 commit 2004ea1

File tree

14 files changed

+468
-133
lines changed

14 files changed

+468
-133
lines changed

README.md

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ console.log('decrypted: ', decrypted);
2929
```shell
3030
npm install node-rsa
3131
```
32-
*Requires nodejs >= 0.10.x*
32+
*Requires nodejs >= 0.10.x or io.js >= 1.x*
3333

3434
### Testing
3535

@@ -57,35 +57,22 @@ var key = new NodeRSA([keyData, [format]], [options]);
5757
#### Options
5858
You can specify some options by second/third constructor argument, or over `key.setOptions()` method.
5959

60-
* environment — working environment, `'browser'` or `'node'`. Default autodetect.
60+
* environment — working environment (default autodetect):
61+
* `'browser'` — will run pure js implementation of RSA algorithms.
62+
* `'node'` for `nodejs >= 0.10.x or io.js >= 1.x` — provide some native methods like sign/verify and encrypt/decrypt.
6163
* encryptionScheme — padding scheme for encrypt/decrypt. Can be `'pkcs1_oaep'` or `'pkcs1'`. Default `'pkcs1_oaep'`.
6264
* signingScheme — scheme used for signing and verifying. Can be `'pkcs1'` or `'pss'` or 'scheme-hash' format string (eg `'pss-sha1'`). Default `'pkcs1-sha256'`, or, if chosen pss: `'pss-sha1'`.
6365

64-
**Advanced options:**<br/>
65-
You also can specify advanced options for some schemes like this:
66-
```javascript
67-
options = {
68-
encryptionScheme: {
69-
scheme: 'pkcs1_oaep', //scheme
70-
hash: 'md5', //hash using for scheme
71-
mgf: function(...) {...} //mask generation function
72-
},
73-
signingScheme: {
74-
scheme: 'pss', //scheme
75-
hash: 'sha1', //hash using for scheme
76-
saltLength: 20 //salt length for pss sign
77-
}
78-
}
79-
```
66+
> *Notice:* This lib supporting next hash algorithms: `'md5'`, `'ripemd160'`, `'sha1'`, `'sha256'`, `'sha512'` in browser and node environment and additional `'md4'`, `'sha'`, `'sha224'`, `'sha384'` in node only.
8067
81-
This lib supporting next hash algorithms: `'md5'`, `'ripemd160'`, `'sha1'`, `'sha256'`, `'sha512'` in browser and node environment and additional `'md4'`, `'sha'`, `'sha224'`, `'sha384'` in node only.
68+
<sub>Some [advanced options info](https://github.com/rzcoder/node-rsa/wiki/Advanced-options)</sub>
8269

8370
#### Creating "empty" key
8471
```javascript
8572
var key = new NodeRSA();
8673
```
8774

88-
#### Generate new key 512bit-length and with public exponent 65537
75+
#### Generate new 512bit-length key
8976
```javascript
9077
var key = new NodeRSA({b: 512});
9178
```
@@ -136,7 +123,7 @@ Output type — can be:
136123
* `'pem'` — Base64 encoded string with header and footer. Used by default.
137124
* `'der'` — Binary encoded key data.
138125

139-
**Notice:** For import, if *keyData* is PEM string or buffer containing string, you can do not specify format, but if you provide *keyData* as DER you must specify it in format string.
126+
> *Notice:* For import, if *keyData* is PEM string or buffer containing string, you can do not specify format, but if you provide *keyData* as DER you must specify it in format string.
140127
141128
**Shortcuts and examples**
142129
* `'private'` or `'pkcs1'` or `'pkcs1-private'` == `'pkcs1-private-pem'` — private key encoded in pcks1 scheme as pem string.
@@ -183,6 +170,7 @@ Return max data size for encrypt in bytes.
183170

184171
```javascript
185172
key.encrypt(buffer, [encoding], [source_encoding]);
173+
key.encryptPrivate(buffer, [encoding], [source_encoding]); // use private key for encryption
186174
```
187175
Return encrypted data.<br/>
188176

@@ -192,12 +180,15 @@ Return encrypted data.<br/>
192180

193181
```javascript
194182
key.decrypt(buffer, [encoding]);
183+
key.decryptPublic(buffer, [encoding]); // use public key for decryption
195184
```
196185
Return decrypted data.<br/>
197186

198187
* buffer — `{buffer}` — data for decrypting. Takes Buffer object or base64 encoded string.<br/>
199188
* encoding — `{string}` — encoding for result string. Can also take `'buffer'` for raw Buffer object, or `'json'` for automatic JSON.parse result. Default `'buffer'`.
200189

190+
> *Notice:* usage `encryptPrivate` and `decryptPublic` with `pkcs1_oaep` padding not described in the RSA [specification](http://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf)
191+
201192
### Signing/Verifying
202193
```javascript
203194
key.sign(buffer, [encoding], [source_encoding]);
@@ -220,6 +211,12 @@ Questions, comments, bug reports, and pull requests are all welcome.
220211

221212
## Changelog
222213

214+
### 0.2.20
215+
* Added `.encryptPrivate()` and `.decryptPublic()` methods.
216+
* Encrypt/decrypt methods in nodejs 0.12.x and io.js using native implementation (> 40x speed boost).
217+
* Fixed some regex issue causing catastrophic backtracking.
218+
* *KNOWN ISSUE*:`encryptPrivate` and `decryptPublic` don't have native implementation in nodejs and can't be use in native implementation with pkcs1_oaep padding in io.js.
219+
223220
### 0.2.10
224221
* **Methods `.exportPrivate()` and `.exportPublic()` was replaced by `.exportKey([format])`.**
225222
* By default `.exportKey()` returns private key as `.exportPrivate()`, if you need public key from `.exportPublic()` you must specify format as `'public'` or `'pkcs8-public-pem'`.
@@ -229,34 +226,34 @@ Questions, comments, bug reports, and pull requests are all welcome.
229226
* **`.getPublicPEM()` method was renamed to `.exportPublic()`**
230227
* **`.getPrivatePEM()` method was renamed to `.exportPrivate()`**
231228
* **`.loadFromPEM()` method was renamed to `.importKey()`**
232-
* Added PKCS1_OAEP encrypting/decrypting support
233-
* **PKCS1_OAEP now default scheme, you need to specify 'encryptingScheme' option to 'pkcs1' for compatibility with 0.1.x version of NodeRSA**
234-
* Added PSS signing/verifying support
229+
* Added PKCS1_OAEP encrypting/decrypting support.
230+
* **PKCS1_OAEP now default scheme, you need to specify 'encryptingScheme' option to 'pkcs1' for compatibility with 0.1.x version of NodeRSA.**
231+
* Added PSS signing/verifying support.
235232
* Signing now supports `'md5'`, `'ripemd160'`, `'sha1'`, `'sha256'`, `'sha512'` hash algorithms in both environments
236233
and additional `'md4'`, `'sha'`, `'sha224'`, `'sha384'` for nodejs env.
237234
* **`options.signingAlgorithm` was renamed to `options.signingScheme`**
238-
* Added `encryptingScheme` option
235+
* Added `encryptingScheme` option.
239236
* Property `key.options` now mark as private. Added `key.setOptions(options)` method.
240237

241238

242239
### 0.1.54
243-
* Added support for loading PEM key from Buffer (`fs.readFileSync()` output)
244-
* Added `isEmpty()` method
240+
* Added support for loading PEM key from Buffer (`fs.readFileSync()` output).
241+
* Added `isEmpty()` method.
245242

246243
### 0.1.52
247-
* Improve work with not properly trimming PEM strings
244+
* Improve work with not properly trimming PEM strings.
248245

249246
### 0.1.50
250-
* Implemented native js signing and verifying for browsers
251-
* `options.signingAlgorithm` now takes only hash-algorithm name
252-
* Added `.getKeySize()` and `.getMaxMessageSize()` methods
253-
* `.loadFromPublicPEM` and `.loadFromPrivatePEM` methods marked as private
247+
* Implemented native js signing and verifying for browsers.
248+
* `options.signingAlgorithm` now takes only hash-algorithm name.
249+
* Added `.getKeySize()` and `.getMaxMessageSize()` methods.
250+
* `.loadFromPublicPEM` and `.loadFromPrivatePEM` methods marked as private.
254251

255252
### 0.1.40
256-
* Added signing/verifying
253+
* Added signing/verifying.
257254

258255
### 0.1.30
259-
* Added long message support
256+
* Added long message support.
260257

261258

262259
## License

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "node-rsa",
3-
"version": "0.2.13",
3+
"version": "0.2.20",
44
"description": "Node.js RSA library",
55
"main": "src/NodeRSA.js",
66
"scripts": {
@@ -30,14 +30,14 @@
3030
},
3131
"homepage": "https://github.com/rzcoder/node-rsa",
3232
"devDependencies": {
33-
"grunt": "^0.4.4",
34-
"grunt-simple-mocha": "^0.4.0",
35-
"jit-grunt": "^0.3.2",
36-
"chai": "^1.9.1",
37-
"grunt-contrib-jshint": "^0.9.2"
33+
"grunt": "0.4.5",
34+
"grunt-simple-mocha": "0.4.0",
35+
"jit-grunt": "0.9.1",
36+
"chai": "2.0.0",
37+
"grunt-contrib-jshint": "0.11.0"
3838
},
3939
"dependencies": {
40-
"lodash": "^2.4.1",
41-
"asn1": "^0.2.0"
40+
"lodash": "3.3.0",
41+
"asn1": "0.2.2"
4242
}
4343
}

src/NodeRSA.js

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ var formats = require('./formats/formats.js');
1717

1818
module.exports = (function () {
1919
var SUPPORTED_HASH_ALGORITHMS = {
20+
node10: ['md4', 'md5', 'ripemd160', 'sha', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512'],
2021
node: ['md4', 'md5', 'ripemd160', 'sha', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512'],
22+
iojs: ['md4', 'md5', 'ripemd160', 'sha', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512'],
2123
browser: ['md5', 'ripemd160', 'sha1', 'sha256', 'sha512']
2224
};
2325

@@ -219,16 +221,52 @@ module.exports = (function () {
219221
};
220222

221223
/**
222-
* Encrypting data method
224+
* Encrypting data method with public key
223225
*
224226
* @param buffer {string|number|object|array|Buffer} - data for encrypting. Object and array will convert to JSON string.
225227
* @param encoding {string} - optional. Encoding for output result, may be 'buffer', 'binary', 'hex' or 'base64'. Default 'buffer'.
226228
* @param source_encoding {string} - optional. Encoding for given string. Default utf8.
227229
* @returns {string|Buffer}
228230
*/
229231
NodeRSA.prototype.encrypt = function (buffer, encoding, source_encoding) {
232+
return this.$$encryptKey(false, buffer, encoding, source_encoding);
233+
};
234+
235+
/**
236+
* Decrypting data method with private key
237+
*
238+
* @param buffer {Buffer} - buffer for decrypting
239+
* @param encoding - encoding for result string, can also take 'json' or 'buffer' for the automatic conversion of this type
240+
* @returns {Buffer|object|string}
241+
*/
242+
NodeRSA.prototype.decrypt = function (buffer, encoding) {
243+
return this.$$decryptKey(false, buffer, encoding);
244+
};
245+
246+
/**
247+
* Encrypting data method with private key
248+
*
249+
* Parameters same as `encrypt` method
250+
*/
251+
NodeRSA.prototype.encryptPrivate = function (buffer, encoding, source_encoding) {
252+
return this.$$encryptKey(true, buffer, encoding, source_encoding);
253+
};
254+
255+
/**
256+
* Decrypting data method with public key
257+
*
258+
* Parameters same as `decrypt` method
259+
*/
260+
NodeRSA.prototype.decryptPublic = function (buffer, encoding) {
261+
return this.$$decryptKey(true, buffer, encoding);
262+
};
263+
264+
/**
265+
* Encrypting data method with custom key
266+
*/
267+
NodeRSA.prototype.$$encryptKey = function (usePrivate, buffer, encoding, source_encoding) {
230268
try {
231-
var res = this.keyPair.encrypt(this.$getDataForEncrypt(buffer, source_encoding));
269+
var res = this.keyPair.encrypt(this.$getDataForEncrypt(buffer, source_encoding), usePrivate);
232270

233271
if (encoding == 'buffer' || !encoding) {
234272
return res;
@@ -241,16 +279,12 @@ module.exports = (function () {
241279
};
242280

243281
/**
244-
* Decrypting data method
245-
*
246-
* @param buffer {Buffer} - buffer for decrypting
247-
* @param encoding - encoding for result string, can also take 'json' or 'buffer' for the automatic conversion of this type
248-
* @returns {Buffer|object|string}
282+
* Decrypting data method with custom key
249283
*/
250-
NodeRSA.prototype.decrypt = function (buffer, encoding) {
284+
NodeRSA.prototype.$$decryptKey = function (usePublic, buffer, encoding) {
251285
try {
252286
buffer = _.isString(buffer) ? new Buffer(buffer, 'base64') : buffer;
253-
var res = this.keyPair.decrypt(buffer);
287+
var res = this.keyPair.decrypt(buffer, usePublic);
254288

255289
if (res === null) {
256290
throw Error('Key decrypt method returns null.');
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
var crypt = require('crypto');
2+
3+
module.exports = {
4+
getEngine: function (keyPair, options) {
5+
var engine;
6+
if (options.environment === 'browser') {
7+
engine = require('./js.js');
8+
} else {
9+
if (typeof crypt.publicEncrypt === 'function' && typeof crypt.privateDecrypt === 'function') {
10+
if (typeof crypt.privateEncrypt === 'function' && typeof crypt.publicDecrypt === 'function') {
11+
engine = require('./io.js');
12+
} else {
13+
engine = require('./node12.js');
14+
}
15+
}
16+
}
17+
return engine(keyPair, options);
18+
}
19+
};

src/encryptEngines/io.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
var crypto = require('crypto');
2+
var constants = require('constants');
3+
4+
module.exports = function (keyPair, options) {
5+
var jsEngine = require('./js.js')(keyPair);
6+
7+
return {
8+
encrypt: function (buffer, usePrivate) {
9+
var padding = constants.RSA_PKCS1_OAEP_PADDING;
10+
if (options.encryptionScheme === 'pkcs1') {
11+
padding = constants.RSA_PKCS1_PADDING;
12+
}
13+
if (usePrivate) {
14+
// openssl don't support oaep padding for private encrypt
15+
if (padding === constants.RSA_PKCS1_OAEP_PADDING) {
16+
return jsEngine.encrypt(buffer, usePrivate);
17+
}
18+
return crypto.privateEncrypt({
19+
key: options.rsaUtils.exportKey('private'),
20+
padding: padding
21+
}, buffer);
22+
} else {
23+
return crypto.publicEncrypt({
24+
key: options.rsaUtils.exportKey('public'),
25+
padding: padding
26+
}, buffer);
27+
}
28+
},
29+
30+
decrypt: function (buffer, usePublic) {
31+
var padding = constants.RSA_PKCS1_OAEP_PADDING;
32+
if (options.encryptionScheme === 'pkcs1') {
33+
padding = constants.RSA_PKCS1_PADDING;
34+
}
35+
if (usePublic) {
36+
// openssl don't support oaep padding for public decrypt
37+
if (padding === constants.RSA_PKCS1_OAEP_PADDING) {
38+
return jsEngine.decrypt(buffer, usePublic);
39+
}
40+
return crypto.publicDecrypt({
41+
key: options.rsaUtils.exportKey('public'),
42+
padding: padding
43+
}, buffer);
44+
} else {
45+
return crypto.privateDecrypt({
46+
key: options.rsaUtils.exportKey('private'),
47+
padding: padding
48+
}, buffer);
49+
}
50+
}
51+
};
52+
};

src/encryptEngines/js.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
var BigInteger = require('../libs/jsbn.js');
2+
3+
module.exports = function (keyPair, options) {
4+
return {
5+
encrypt: function (buffer, usePrivate) {
6+
var m = new BigInteger(keyPair.encryptionScheme.encPad(buffer));
7+
var c = usePrivate ? keyPair.$doPrivate(m) : keyPair.$doPublic(m);
8+
return c.toBuffer(keyPair.encryptedDataLength);
9+
},
10+
11+
decrypt: function (buffer, usePublic) {
12+
var c = new BigInteger(buffer);
13+
var m = usePublic ? keyPair.$doPublic(c) : keyPair.$doPrivate(c);
14+
return keyPair.encryptionScheme.encUnPad(m.toBuffer(keyPair.encryptedDataLength));
15+
}
16+
};
17+
};

src/encryptEngines/node12.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
var crypto = require('crypto');
2+
var constants = require('constants');
3+
4+
module.exports = function (keyPair, options) {
5+
var jsEngine = require('./js.js')(keyPair);
6+
7+
return {
8+
encrypt: function (buffer, usePrivate) {
9+
if (usePrivate) {
10+
return jsEngine.encrypt(buffer, usePrivate);
11+
}
12+
var padding = constants.RSA_PKCS1_OAEP_PADDING;
13+
if (options.encryptionScheme === 'pkcs1') {
14+
padding = constants.RSA_PKCS1_PADDING;
15+
}
16+
17+
return crypto.publicEncrypt({
18+
key: options.rsaUtils.exportKey('public'),
19+
padding: padding
20+
}, buffer);
21+
},
22+
23+
decrypt: function (buffer, usePublic) {
24+
if (usePublic) {
25+
return jsEngine.decrypt(buffer, usePublic);
26+
}
27+
var padding = constants.RSA_PKCS1_OAEP_PADDING;
28+
if (options.encryptionScheme === 'pkcs1') {
29+
padding = constants.RSA_PKCS1_PADDING;
30+
}
31+
32+
return crypto.privateDecrypt({
33+
key: options.rsaUtils.exportKey('private'),
34+
padding: padding
35+
}, buffer);
36+
}
37+
};
38+
};

0 commit comments

Comments
 (0)