Skip to content

Commit 22ffb51

Browse files
committed
long message implementation (wip)
1 parent 1a56ce0 commit 22ffb51

File tree

4 files changed

+117
-42
lines changed

4 files changed

+117
-42
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ Questions, comments, bug reports, and pull requests are all welcome.
9090
## License for NodeRSA.js
9191

9292
Copyright (c) 2014 rzcoder
93+
9394
All Rights Reserved.
9495

9596
BSD

src/libs/jsbn.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ function BigInteger(a, b) {
4545
if (a != null) {
4646
if ("number" == typeof a) {
4747
this.fromNumber(a, b);
48+
} else if (Buffer.isBuffer(a)) {
49+
this.fromBuffer(a);
4850
} else if (b == null && "string" != typeof a) {
4951
this.fromByteArray(a);
5052
} else {
@@ -172,7 +174,7 @@ function nbv(i) {
172174
}
173175

174176
// (protected) set from string and radix
175-
function bnpFromString(data, radix) {
177+
function bnpFromString(data, radix, unsigned) {
176178
var k;
177179
if (radix == 16) k = 4;
178180
else if (radix == 8) k = 3;
@@ -217,6 +219,10 @@ function bnpFromByteArray(a) {
217219
this.fromString(a, 256)
218220
}
219221

222+
function bnpFromBuffer(a) {
223+
this.fromString(a, 256, true)
224+
}
225+
220226
// (protected) clamp off excess high words
221227
function bnpClamp() {
222228
var c = this.s & this.DM;
@@ -793,8 +799,14 @@ function bnToByteArray() {
793799
return r;
794800
}
795801

796-
function bnToBuffer() {
797-
return new Buffer(this.toByteArray());
802+
/**
803+
* return Buffer object
804+
* @param trim {boolean} slice buffer if first element == 0
805+
* @returns {Buffer}
806+
*/
807+
function bnToBuffer(trim) {
808+
var res = new Buffer(this.toByteArray());
809+
return trim && res[0] === 0 ? res.slice(1) : res;
798810
}
799811

800812
function bnEquals(a) {
@@ -1394,6 +1406,7 @@ BigInteger.prototype.copyTo = bnpCopyTo;
13941406
BigInteger.prototype.fromInt = bnpFromInt;
13951407
BigInteger.prototype.fromString = bnpFromString;
13961408
BigInteger.prototype.fromByteArray = bnpFromByteArray;
1409+
BigInteger.prototype.fromBuffer = bnpFromBuffer;
13971410
BigInteger.prototype.clamp = bnpClamp;
13981411
BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
13991412
BigInteger.prototype.drShiftTo = bnpDRShiftTo;

src/libs/rsa.js

Lines changed: 79 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@
3232
*/
3333

3434
/*
35-
* Node.js adaptation, long message implementation
35+
* Node.js adaptation, long message support implementation
3636
* 2014 rzcoder
37-
*
3837
*/
38+
3939
var crypt = require('crypto');
4040
var BigInteger = require("./jsbn.js");
4141
var utils = require('../utils.js')
@@ -189,25 +189,46 @@ module.exports.Key = (function() {
189189
var buffers = [];
190190
var results = [];
191191

192-
if (buffer.length <= this.maxMessageLength) {
192+
var bufferSize = buffer.length;
193+
var buffersCount = Math.ceil(bufferSize / this.maxMessageLength); // total buffers count for encrypt
194+
var dividedSize = Math.ceil(bufferSize / buffersCount); // each buffer size
195+
196+
if ( buffersCount == 1) {
193197
buffers.push(buffer);
198+
} else {
199+
for (var bufNum = 0; bufNum < buffersCount; bufNum++) {
200+
buffers.push(buffer.slice(bufNum * dividedSize, (bufNum+1) * dividedSize));
201+
}
194202
}
195203

204+
this.debug = {}
205+
this.debug.s = {}
206+
this.debug.s.b = [];
207+
this.debug.s.m = [];
208+
this.debug.s.c = [];
209+
this.debug.s.resbuf = [];
196210
for(var i in buffers) {
197211
var buf = buffers[i];
212+
this.debug.s.b[i] = buf;
198213

199-
var m = this.$$pkcs1pad2(buf, this.maxEncryptDataLength);
214+
var m = this.$$pkcs1pad2(buf, this.encryptedDataLength);
215+
this.debug.s.m[i] = m;
200216

201217
if (m === null) {
202218
return null;
203219
}
204220

205221
var c = this.$doPublic(m);
222+
this.debug.s.c[i] = c;
206223
if (c === null) {
207224
return null;
208225
}
209226

210-
results.push(new Buffer(c.toByteArray()));
227+
this.debug.s.resbuf[i] = c.toBuffer(true)
228+
while (this.debug.s.resbuf[i].length < this.encryptedDataLength)
229+
this.debug.s.resbuf[i] = Buffer.concat(new Buffer([0]), this.debug.s.resbuf[i]);
230+
231+
results.push( this.debug.s.resbuf[i]);
211232
}
212233

213234
return Buffer.concat(results);
@@ -219,22 +240,55 @@ module.exports.Key = (function() {
219240
* @returns {Buffer}
220241
*/
221242
RSAKey.prototype.decrypt = function (buffer) {
222-
var c = new BigInteger(buffer);
223-
var m = this.$doPrivate(c);
243+
// if (buffer.length % this.encryptedDataLength > 0)
244+
// throw Error('Incorrect data or key');
245+
246+
var result = [];
247+
248+
var s = '';
249+
var offset = 0;
250+
var length = 0;
251+
252+
this.debug.o = {}
253+
this.debug.o.b = [];
254+
this.debug.o.m = [];
255+
this.debug.o.c = [];
256+
this.debug.o.resbuf = [];
257+
for (var i = 0; ; i++) {
258+
offset = length;
259+
length = offset + this.encryptedDataLength// + (buffer[offset] === 0 ? 1 : 0);
260+
261+
this.debug.o.resbuf[i] = buffer.slice(offset, Math.min(length, buffer.length))
262+
var c = new BigInteger(this.debug.o.resbuf[i]);
263+
this.debug.o.c[i] = c;
264+
var m = this.$doPrivate(c);
265+
this.debug.o.m[i] = m;
266+
if (m === null) {
267+
return null;
268+
}
224269

225-
if (m === null) {
226-
return null;
270+
this.debug.o.b[i] = this.$$pkcs1unpad2(m, this.encryptedDataLength)
271+
result.push(this.debug.o.b[i]);
272+
273+
if (length >= buffer.length)
274+
break;
227275
}
228276

229-
return this.$$pkcs1unpad2(m, (this.n.bitLength() + 7) >> 3);
277+
try{
278+
a = Buffer.concat(result);
279+
} catch (e) {
280+
console.log(e)
281+
throw e;
282+
}
283+
return a;
230284
};
231285

232-
Object.defineProperty(RSAKey.prototype, 'maxEncryptDataLength', {
286+
Object.defineProperty(RSAKey.prototype, 'encryptedDataLength', {
233287
get: function() { return this.cache.keyByteLength; }
234288
});
235289

236290
Object.defineProperty(RSAKey.prototype, 'maxMessageLength', {
237-
get: function() { return this.maxEncryptDataLength - 11; }
291+
get: function() { return this.encryptedDataLength - 11; }
238292
});
239293

240294
/**
@@ -285,22 +339,27 @@ module.exports.Key = (function() {
285339
RSAKey.prototype.$$pkcs1unpad2 = function (d, n) {
286340
var b = d.toByteArray();
287341
var i = 0;
288-
while (i < b.length && b[i] === 0)
342+
while (i < b.length && b[i] === 0) {
289343
++i;
344+
}
290345

291-
if (b.length - i != n - 1 || b[i] != 2)
346+
if (b.length - i != n - 1 || b[i] != 2) {
292347
return null;
348+
}
349+
293350
++i;
294-
while (b[i] !== 0)
295-
if (++i >= b.length)
351+
while (b[i] !== 0) {
352+
if (++i >= b.length) {
296353
return null;
354+
}
355+
}
297356

298-
var res = [];
357+
var c = 0;
358+
var res = new Buffer(b.length - i - 1);
299359
while (++i < b.length) {
300-
var c = b[i] & 255;
301-
res.push(c);
360+
res[c++] = b[i] & 255;
302361
}
303-
return new Buffer(res);
362+
return res;
304363
}
305364

306365
return RSAKey;

test/tests.js

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
var assert = require('chai').assert
2-
var NodeRSA = (require('../src/NodeRSA'))
1+
var assert = require('chai').assert;
2+
var _ = require('lodash');
3+
var NodeRSA = (require('../src/NodeRSA'));
34

5+
for(var i=0;i<100;i++)
46
describe('NodeRSA', function(){
57
var nodeRSA = null;
68
var privateNodeRSA = null;
@@ -58,31 +60,31 @@ describe('NodeRSA', function(){
5860
'KY4kQIIx8JEBsAYzgyP2iy0CAwEAAQ==\n'+
5961
'-----END PUBLIC KEY-----';
6062

61-
it('.loadFromPrivatePEM() should load private key from PEM string', function(){
63+
false && it('.loadFromPrivatePEM() should load private key from PEM string', function(){
6264
privateNodeRSA = new NodeRSA(privateKeyPEM);
6365
assert.instanceOf(privateNodeRSA.keyPair, Object);
6466
assert(privateNodeRSA.isPrivate());
6567
assert(privateNodeRSA.isPublic());
6668
assert(!privateNodeRSA.isPublic(true));
6769
});
6870

69-
it('.loadFromPublicPEM() should load public key from PEM string', function(){
71+
false && it('.loadFromPublicPEM() should load public key from PEM string', function(){
7072
publicNodeRSA = new NodeRSA(publicKeyPEM);
7173
assert.instanceOf(privateNodeRSA.keyPair, Object);
7274
assert(publicNodeRSA.isPublic());
7375
assert(publicNodeRSA.isPublic(true));
7476
assert(!publicNodeRSA.isPrivate());
7577
});
7678

77-
it('.toPrivatePEM() should return private PEM string', function(){
79+
false && it('.toPrivatePEM() should return private PEM string', function(){
7880
assert.equal(privateNodeRSA.toPrivatePEM(), privateKeyPEM);
7981
});
8082

81-
it('.toPublicPEM() from public key should return public PEM string', function(){
83+
false && it('.toPublicPEM() from public key should return public PEM string', function(){
8284
assert.equal(publicNodeRSA.toPublicPEM(), publicKeyPEM);
8385
});
8486

85-
it('.toPublicPEM() from private key should return public PEM string', function(){
87+
false && it('.toPublicPEM() from private key should return public PEM string', function(){
8688
assert.equal(privateNodeRSA.toPublicPEM(), publicKeyPEM);
8789
});
8890
});
@@ -103,36 +105,36 @@ describe('NodeRSA', function(){
103105
var decryptedJSON = null;
104106

105107
describe('Encrypting', function(){
106-
it('.encrypt() should return Buffer object', function(){
108+
false && it('.encrypt() should return Buffer object', function(){
107109
encryptedBuffer = nodeRSA.encrypt(dataForEncrypt, null, 'buffer');
108110
assert(Buffer.isBuffer(encryptedBuffer));
109111
});
110112

111-
it('.encrypt() should return base64 encrypted string', function(){
113+
false && it('.encrypt() should return base64 encrypted string', function(){
112114
encrypted = nodeRSA.encrypt(dataForEncrypt);
113115
assert.isString(encrypted);
114116
assert.match(encrypted, /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/);
115117
});
116118

117-
it('.encrypt() should return encrypted string for long message', function(){
118-
encryptedLong = nodeRSA.encrypt(longDataForEncrypt, null, Buffer);
119+
it('.encrypt() should return encrypted Buffer for long message', function(){
120+
encryptedLong = nodeRSA.encrypt(longDataForEncrypt, null, 'buffer');
119121
assert(Buffer.isBuffer(encryptedLong));
120122
});
121123

122-
it('.encrypt() for js object). Should return Buffer object', function(){
124+
false && it('.encrypt() for js object. Should return Buffer object', function(){
123125
encryptedJSON = nodeRSA.encrypt(JSONForEncrypt, null, 'buffer');
124126
assert(Buffer.isBuffer(encryptedJSON));
125127
});
126128
});
127129

128130
describe('Decrypting', function(){
129-
it('.decrypt() should return decrypted Buffer', function(){
131+
false && it('.decrypt() should return decrypted Buffer', function(){
130132
decrypted = nodeRSA.decrypt(encryptedBuffer, 'buffer');
131133
assert(Buffer.isBuffer(decrypted));
132134
});
133135

134-
it('.decrypt() should return decrypted string', function(){
135-
decrypted = nodeRSA.decrypt(new Buffer(encrypted, 'base64'), 'utf8');
136+
false && it('.decrypt() should return decrypted string', function(){
137+
decrypted = nodeRSA.decrypt(new Buffer(encrypted, 'base64'));
136138
assert.isString(decrypted);
137139
});
138140

@@ -141,20 +143,20 @@ describe('NodeRSA', function(){
141143
assert.isString(decryptedLong);
142144
});
143145

144-
it('.decrypt() for js object. Should return decrypted js object', function(){
145-
decryptedJSON = nodeRSA.decrypt(new Buffer(encrypted, 'base64'), 'utf8');
146+
false && it('.decrypt() for js object. Should return decrypted js object', function(){
147+
decryptedJSON = nodeRSA.decrypt(encryptedJSON, 'json');
146148
assert.isObject(decryptedJSON);
147149
});
148150

149-
it('source and decrypted should be the same', function(){
151+
false && it('source and decrypted should be the same', function(){
150152
assert.equal(decrypted, dataForEncrypt);
151153
});
152154

153155
it('long source and decrypted should be the same', function(){
154156
assert.equal(decryptedLong, longDataForEncrypt);
155157
});
156158

157-
it('source JSON and decrypted JSON should be the same', function(){
159+
false && it('source JSON and decrypted JSON should be the same', function(){
158160
assert(_.isEqual(decryptedJSON, JSONForEncrypt));
159161
});
160162
});

0 commit comments

Comments
 (0)