Skip to content

Commit 3da3039

Browse files
committed
Merge pull request #34 from rzcoder/dev
Dev
2 parents a838ee0 + 1829853 commit 3da3039

File tree

7 files changed

+309
-275
lines changed

7 files changed

+309
-275
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,13 +210,12 @@ Questions, comments, bug reports, and pull requests are all welcome.
210210
## Changelog
211211

212212
### 0.2.22
213-
* Native support for `encryptPrivate` and `decryptPublic` in io.js caused error in linux and was removed.
213+
* `encryptPrivate` and `decryptPublic` now using only pkcs1 (type 1) padding.
214214

215215
### 0.2.20
216216
* Added `.encryptPrivate()` and `.decryptPublic()` methods.
217217
* Encrypt/decrypt methods in nodejs 0.12.x and io.js using native implementation (> 40x speed boost).
218218
* Fixed some regex issue causing catastrophic backtracking.
219-
* *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.
220219

221220
### 0.2.10
222221
* **Methods `.exportPrivate()` and `.exportPublic()` was replaced by `.exportKey([format])`.**

src/encryptEngines/encryptEngines.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,11 @@ module.exports = {
55
var engine = require('./js.js');
66
if (options.environment === 'node') {
77
if (typeof crypt.publicEncrypt === 'function' && typeof crypt.privateDecrypt === 'function') {
8-
engine = require('./node12.js');
9-
10-
/*
11-
12-
io.js privateEncrypt/publicDecrypt with different environments causing error in linux
13-
148
if (typeof crypt.privateEncrypt === 'function' && typeof crypt.publicDecrypt === 'function') {
159
engine = require('./io.js');
1610
} else {
1711
engine = require('./node12.js');
18-
}*/
12+
}
1913
}
2014
}
2115
return engine(keyPair, options);

src/encryptEngines/io.js

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,21 @@ var crypto = require('crypto');
22
var constants = require('constants');
33

44
module.exports = function (keyPair, options) {
5-
var jsEngine = require('./js.js')(keyPair);
5+
var jsEngine = require('./js.js')(keyPair, options);
66

77
return {
88
encrypt: function (buffer, usePrivate) {
9-
var padding = constants.RSA_PKCS1_OAEP_PADDING;
10-
if (options.encryptionScheme === 'pkcs1') {
11-
padding = constants.RSA_PKCS1_PADDING;
12-
}
139
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-
}
1810
return crypto.privateEncrypt({
1911
key: options.rsaUtils.exportKey('private'),
20-
padding: padding
12+
padding: constants.RSA_PKCS1_PADDING
2113
}, buffer);
2214
} else {
15+
var padding = constants.RSA_PKCS1_OAEP_PADDING;
16+
if (options.encryptionScheme === 'pkcs1') {
17+
padding = constants.RSA_PKCS1_PADDING;
18+
}
19+
2320
return crypto.publicEncrypt({
2421
key: options.rsaUtils.exportKey('public'),
2522
padding: padding
@@ -28,20 +25,17 @@ module.exports = function (keyPair, options) {
2825
},
2926

3027
decrypt: function (buffer, usePublic) {
31-
var padding = constants.RSA_PKCS1_OAEP_PADDING;
32-
if (options.encryptionScheme === 'pkcs1') {
33-
padding = constants.RSA_PKCS1_PADDING;
34-
}
3528
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-
}
4029
return crypto.publicDecrypt({
4130
key: options.rsaUtils.exportKey('public'),
42-
padding: padding
31+
padding: constants.RSA_PKCS1_PADDING
4332
}, buffer);
4433
} else {
34+
var padding = constants.RSA_PKCS1_OAEP_PADDING;
35+
if (options.encryptionScheme === 'pkcs1') {
36+
padding = constants.RSA_PKCS1_PADDING;
37+
}
38+
4539
return crypto.privateDecrypt({
4640
key: options.rsaUtils.exportKey('private'),
4741
padding: padding

src/encryptEngines/js.js

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,32 @@
11
var BigInteger = require('../libs/jsbn.js');
2+
var schemes = require('../schemes/schemes.js');
23

34
module.exports = function (keyPair, options) {
5+
var pkcs1Scheme = schemes.pkcs1.makeScheme(keyPair, options);
6+
47
return {
58
encrypt: function (buffer, usePrivate) {
6-
var m = new BigInteger(keyPair.encryptionScheme.encPad(buffer));
7-
var c = usePrivate ? keyPair.$doPrivate(m) : keyPair.$doPublic(m);
9+
var m, c;
10+
if (usePrivate) {
11+
m = new BigInteger(pkcs1Scheme.encPad(buffer, {type: 1}));
12+
c = keyPair.$doPrivate(m);
13+
} else {
14+
m = new BigInteger(keyPair.encryptionScheme.encPad(buffer));
15+
c = keyPair.$doPublic(m);
16+
}
817
return c.toBuffer(keyPair.encryptedDataLength);
918
},
1019

1120
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));
21+
var m, c = new BigInteger(buffer);
22+
23+
if (usePublic) {
24+
m = keyPair.$doPublic(c);
25+
return pkcs1Scheme.encUnPad(m.toBuffer(keyPair.encryptedDataLength), {type: 1});
26+
} else {
27+
m = keyPair.$doPrivate(c);
28+
return keyPair.encryptionScheme.encUnPad(m.toBuffer(keyPair.encryptedDataLength));
29+
}
1530
}
1631
};
1732
};

src/encryptEngines/node12.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ var crypto = require('crypto');
22
var constants = require('constants');
33

44
module.exports = function (keyPair, options) {
5-
var jsEngine = require('./js.js')(keyPair);
5+
var jsEngine = require('./js.js')(keyPair, options);
66

77
return {
88
encrypt: function (buffer, usePrivate) {

src/schemes/pkcs1.js

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -39,32 +39,39 @@ module.exports.makeScheme = function (key, options) {
3939

4040
/**
4141
* Pad input Buffer to encryptedDataLength bytes, and return new Buffer
42-
* alg: PKCS#1 (type 2, random)
42+
* alg: PKCS#1
4343
* @param buffer
4444
* @returns {Buffer}
4545
*/
46-
Scheme.prototype.encPad = function (buffer) {
46+
Scheme.prototype.encPad = function (buffer, options) {
47+
options = options || {};
48+
var filled;
4749
if (buffer.length > this.key.maxMessageLength) {
4850
throw new Error("Message too long for RSA (n=" + this.key.encryptedDataLength + ", l=" + buffer.length + ")");
4951
}
5052

51-
// TODO: make n-length buffer
52-
var ba = Array.prototype.slice.call(buffer, 0);
53+
if (options.type === 1) {
54+
filled = new Buffer(this.key.encryptedDataLength - buffer.length - 1);
55+
filled.fill(0xff, 0, filled.length - 1);
56+
filled[0] = 1;
57+
filled[filled.length - 1] = 0;
5358

54-
// random padding
55-
ba.unshift(0);
56-
var rand = crypt.randomBytes(this.key.encryptedDataLength - ba.length - 2);
57-
for (var i = 0; i < rand.length; i++) {
58-
var r = rand[i];
59-
while (r === 0) { // non-zero only
60-
r = crypt.randomBytes(1)[0];
59+
return Buffer.concat([filled, buffer]);
60+
} else {
61+
filled = new Buffer(this.key.encryptedDataLength - buffer.length);
62+
filled[0] = 0;
63+
filled[1] = 2;
64+
var rand = crypt.randomBytes(filled.length - 3);
65+
for (var i = 0; i < rand.length; i++) {
66+
var r = rand[i];
67+
while (r === 0) { // non-zero only
68+
r = crypt.randomBytes(1)[0];
69+
}
70+
filled[i + 2] = r;
6171
}
62-
ba.unshift(r);
72+
filled[filled.length - 1] = 0;
73+
return Buffer.concat([filled, buffer]);
6374
}
64-
ba.unshift(2);
65-
ba.unshift(0);
66-
67-
return ba;
6875
};
6976

7077
/**
@@ -73,32 +80,36 @@ module.exports.makeScheme = function (key, options) {
7380
* @param buffer
7481
* @returns {Buffer}
7582
*/
76-
Scheme.prototype.encUnPad = function (buffer) {
77-
//var buffer = buffer.toByteArray();
83+
Scheme.prototype.encUnPad = function (buffer, options) {
84+
options = options || {};
7885
var i = 0;
7986

80-
while (i < buffer.length && buffer[i] === 0) {
81-
++i;
82-
}
83-
84-
if (buffer.length - i != this.key.encryptedDataLength - 1 || buffer[i] != 2) {
87+
if (buffer.length < 4) {
8588
return null;
8689
}
8790

88-
++i;
89-
while (buffer[i] !== 0) {
90-
if (++i >= buffer.length) {
91+
if (options.type === 1) {
92+
if (buffer[0] !== 0 && buffer[1] !== 1) {
9193
return null;
9294
}
95+
i = 3;
96+
while (buffer[i] !== 0) {
97+
if (buffer[i] != 0xFF || ++i >= buffer.length) {
98+
return null;
99+
}
100+
}
101+
} else {
102+
if (buffer[0] !== 0 && buffer[1] !== 2) {
103+
return null;
104+
}
105+
i = 3;
106+
while (buffer[i] !== 0) {
107+
if (++i >= buffer.length) {
108+
return null;
109+
}
110+
}
93111
}
94-
95-
var c = 0;
96-
var res = new Buffer(buffer.length - i - 1);
97-
while (++i < buffer.length) {
98-
res[c++] = buffer[i] & 255;
99-
}
100-
101-
return res;
112+
return buffer.slice(i + 1, buffer.length);
102113
};
103114

104115
Scheme.prototype.sign = function (buffer) {

0 commit comments

Comments
 (0)