node-forge 0.6.29 → 0.6.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.npmignore +1 -0
- package/.travis.yml +2 -0
- package/README.md +2 -1
- package/bower.json +2 -1
- package/js/aes.js +1 -0
- package/js/aesCipherSuites.js +33 -7
- package/js/cipher.js +3 -1
- package/js/x509.js +1 -1
- package/nodejs/.istanbul.yml +2 -0
- package/nodejs/package.json +22 -15
- package/nodejs/test/aes.js +168 -6
- package/nodejs/ui/test.js +1 -1
- package/package.json +1 -1
package/.npmignore
CHANGED
package/.travis.yml
CHANGED
package/README.md
CHANGED
|
@@ -553,6 +553,7 @@ of operation: [ECB][], [CBC][], [CFB][], [OFB][], [CTR][], and [GCM][].
|
|
|
553
553
|
|
|
554
554
|
These algorithms are currently supported:
|
|
555
555
|
|
|
556
|
+
* AES-ECB
|
|
556
557
|
* AES-CBC
|
|
557
558
|
* AES-CFB
|
|
558
559
|
* AES-OFB
|
|
@@ -582,7 +583,7 @@ var key = forge.pkcs5.pbkdf2('password', salt, numIterations, 16);
|
|
|
582
583
|
*/
|
|
583
584
|
|
|
584
585
|
// encrypt some bytes using CBC mode
|
|
585
|
-
// (other modes include: CFB, OFB, CTR, and GCM)
|
|
586
|
+
// (other modes include: ECB, CFB, OFB, CTR, and GCM)
|
|
586
587
|
var cipher = forge.cipher.createCipher('AES-CBC', key);
|
|
587
588
|
cipher.start({iv: iv});
|
|
588
589
|
cipher.update(forge.util.createBuffer(someBytes));
|
package/bower.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forge",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.33",
|
|
4
4
|
"description": "JavaScript implementations of network transports, cryptography, ciphers, PKI, message digests, and various utilities.",
|
|
5
|
+
"moduleType": ["amd"],
|
|
5
6
|
"authors": [
|
|
6
7
|
"Digital Bazaar, Inc."
|
|
7
8
|
],
|
package/js/aes.js
CHANGED
|
@@ -251,6 +251,7 @@ forge.aes._updateBlock = _updateBlock;
|
|
|
251
251
|
|
|
252
252
|
/** Register AES algorithms **/
|
|
253
253
|
|
|
254
|
+
registerAlgorithm('AES-ECB', forge.cipher.modes.ecb);
|
|
254
255
|
registerAlgorithm('AES-CBC', forge.cipher.modes.cbc);
|
|
255
256
|
registerAlgorithm('AES-CFB', forge.cipher.modes.cfb);
|
|
256
257
|
registerAlgorithm('AES-OFB', forge.cipher.modes.ofb);
|
package/js/aesCipherSuites.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @author Dave Longley
|
|
5
5
|
*
|
|
6
|
-
* Copyright (c) 2009-
|
|
6
|
+
* Copyright (c) 2009-2015 Digital Bazaar, Inc.
|
|
7
7
|
*
|
|
8
8
|
*/
|
|
9
9
|
(function() {
|
|
@@ -232,11 +232,9 @@ function decrypt_aes_cbc_sha1(record, s) {
|
|
|
232
232
|
// last 20 bytes = MAC
|
|
233
233
|
var macLen = s.macLength;
|
|
234
234
|
|
|
235
|
-
// create a
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
mac += String.fromCharCode(0);
|
|
239
|
-
}
|
|
235
|
+
// create a random MAC to check against should the mac length check fail
|
|
236
|
+
// Note: do this regardless of the failure to keep timing consistent
|
|
237
|
+
var mac = forge.random.getBytesSync(macLen);
|
|
240
238
|
|
|
241
239
|
// get fragment and mac
|
|
242
240
|
var len = cipher.output.length();
|
|
@@ -253,10 +251,38 @@ function decrypt_aes_cbc_sha1(record, s) {
|
|
|
253
251
|
// see if data integrity checks out, update sequence number
|
|
254
252
|
var mac2 = s.macFunction(s.macKey, s.sequenceNumber, record);
|
|
255
253
|
s.updateSequenceNumber();
|
|
256
|
-
rval = (
|
|
254
|
+
rval = compareMacs(s.macKey, mac, mac2) && rval;
|
|
257
255
|
return rval;
|
|
258
256
|
}
|
|
259
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Safely compare two MACs. This function will compare two MACs in a way
|
|
260
|
+
* that protects against timing attacks.
|
|
261
|
+
*
|
|
262
|
+
* TODO: Expose elsewhere as a utility API.
|
|
263
|
+
*
|
|
264
|
+
* See: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/
|
|
265
|
+
*
|
|
266
|
+
* @param key the MAC key to use.
|
|
267
|
+
* @param mac1 as a binary-encoded string of bytes.
|
|
268
|
+
* @param mac2 as a binary-encoded string of bytes.
|
|
269
|
+
*
|
|
270
|
+
* @return true if the MACs are the same, false if not.
|
|
271
|
+
*/
|
|
272
|
+
function compareMacs(key, mac1, mac2) {
|
|
273
|
+
var hmac = forge.hmac.create();
|
|
274
|
+
|
|
275
|
+
hmac.start('SHA1', key);
|
|
276
|
+
hmac.update(mac1);
|
|
277
|
+
mac1 = hmac.digest().getBytes();
|
|
278
|
+
|
|
279
|
+
hmac.start(null, null);
|
|
280
|
+
hmac.update(mac2);
|
|
281
|
+
mac2 = hmac.digest().getBytes();
|
|
282
|
+
|
|
283
|
+
return mac1 === mac2;
|
|
284
|
+
}
|
|
285
|
+
|
|
260
286
|
} // end module implementation
|
|
261
287
|
|
|
262
288
|
/* ########## Begin module wrapper ########## */
|
package/js/cipher.js
CHANGED
|
@@ -128,6 +128,8 @@ var BlockCipher = forge.cipher.BlockCipher = function(options) {
|
|
|
128
128
|
* bytes, then it must be Nb (16) bytes in length. If the IV is given in as
|
|
129
129
|
* 32-bit integers, then it must be 4 integers long.
|
|
130
130
|
*
|
|
131
|
+
* Note: an IV is not required or used in ECB mode.
|
|
132
|
+
*
|
|
131
133
|
* For GCM-mode, the IV must be given as a binary-encoded string of bytes or
|
|
132
134
|
* a byte buffer. The number of bytes should be 12 (96 bits) as recommended
|
|
133
135
|
* by NIST SP-800-38D but another length may be given.
|
|
@@ -187,7 +189,7 @@ BlockCipher.prototype.update = function(input) {
|
|
|
187
189
|
BlockCipher.prototype.finish = function(pad) {
|
|
188
190
|
// backwards-compatibility w/deprecated padding API
|
|
189
191
|
// Note: will overwrite padding functions even after another start() call
|
|
190
|
-
if(pad && this.mode.name === 'CBC') {
|
|
192
|
+
if(pad && (this.mode.name === 'ECB' || this.mode.name === 'CBC')) {
|
|
191
193
|
this.mode.pad = function(input) {
|
|
192
194
|
return pad(this.blockSize, input, false);
|
|
193
195
|
};
|
package/js/x509.js
CHANGED
package/nodejs/package.json
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
2
|
+
"name": "forge-nodejs-example",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"main": "server.js",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"express": "~3.1.0",
|
|
8
|
+
"mocha": "~1.21.5",
|
|
9
|
+
"chai": "~1.10.0",
|
|
10
|
+
"grunt": "~0.4.5",
|
|
11
|
+
"grunt-mocha": "~0.4.12"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"run": "node server",
|
|
15
|
+
"test": "mocha -t 30000 -R spec test/*.js",
|
|
16
|
+
"coverage": "rm -rf coverage && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- -u exports -t 30000 -R spec test/*.js",
|
|
17
|
+
"coverage-lcov": "rm -rf coverage && ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha --report lcovonly -- -u exports -t 30000 -R spec test/*.js",
|
|
18
|
+
"coverage-report": "./node_modules/.bin/istanbul report"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"istanbul": "^0.3.14",
|
|
22
|
+
"mocha-lcov-reporter": "0.0.2"
|
|
23
|
+
}
|
|
17
24
|
}
|
package/nodejs/test/aes.js
CHANGED
|
@@ -112,6 +112,162 @@ function Tests(ASSERT, CIPHER, AES, UTIL) {
|
|
|
112
112
|
ASSERT.equal(out.toHex(), '00112233445566778899aabbccddeeff');
|
|
113
113
|
});
|
|
114
114
|
|
|
115
|
+
// AES-128-ECB
|
|
116
|
+
(function() {
|
|
117
|
+
var keys = [
|
|
118
|
+
'2b7e151628aed2a6abf7158809cf4f3c',
|
|
119
|
+
'2b7e151628aed2a6abf7158809cf4f3c',
|
|
120
|
+
'2b7e151628aed2a6abf7158809cf4f3c',
|
|
121
|
+
'2b7e151628aed2a6abf7158809cf4f3c'
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
var inputs = [
|
|
125
|
+
'6bc1bee22e409f96e93d7e117393172a',
|
|
126
|
+
'ae2d8a571e03ac9c9eb76fac45af8e51',
|
|
127
|
+
'30c81c46a35ce411e5fbc1191a0a52ef',
|
|
128
|
+
'f69f2445df4f9b17ad2b417be66c3710'
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
var outputs = [
|
|
132
|
+
'3ad77bb40d7a3660a89ecaf32466ef97',
|
|
133
|
+
'f5d3d58503b9699de785895a96fdbaaf',
|
|
134
|
+
'43b1cd7f598ece23881b00e3ed030688',
|
|
135
|
+
'7b0c785e27e8ad3f8223207104725dd4'
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
for(var i = 0; i < keys.length; ++i) {
|
|
139
|
+
(function(i) {
|
|
140
|
+
var key = UTIL.hexToBytes(keys[i]);
|
|
141
|
+
var input = UTIL.hexToBytes(inputs[i]);
|
|
142
|
+
var output = UTIL.hexToBytes(outputs[i]);
|
|
143
|
+
|
|
144
|
+
it('should aes-128-ecb encrypt: ' + inputs[i], function() {
|
|
145
|
+
// encrypt w/no padding
|
|
146
|
+
var cipher = CIPHER.createCipher('AES-ECB', key);
|
|
147
|
+
cipher.mode.pad = false;
|
|
148
|
+
cipher.start();
|
|
149
|
+
cipher.update(UTIL.createBuffer(input));
|
|
150
|
+
cipher.finish();
|
|
151
|
+
ASSERT.equal(cipher.output.toHex(), outputs[i]);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should aes-128-ecb decrypt: ' + outputs[i], function() {
|
|
155
|
+
// decrypt w/no padding
|
|
156
|
+
var cipher = CIPHER.createDecipher('AES-ECB', key);
|
|
157
|
+
cipher.mode.unpad = false;
|
|
158
|
+
cipher.start();
|
|
159
|
+
cipher.update(UTIL.createBuffer(output));
|
|
160
|
+
cipher.finish();
|
|
161
|
+
ASSERT.equal(cipher.output.toHex(), inputs[i]);
|
|
162
|
+
});
|
|
163
|
+
})(i);
|
|
164
|
+
}
|
|
165
|
+
})();
|
|
166
|
+
|
|
167
|
+
// AES-192-ECB
|
|
168
|
+
(function() {
|
|
169
|
+
var keys = [
|
|
170
|
+
'8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b',
|
|
171
|
+
'8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b',
|
|
172
|
+
'8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b',
|
|
173
|
+
'8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'
|
|
174
|
+
];
|
|
175
|
+
|
|
176
|
+
var inputs = [
|
|
177
|
+
'6bc1bee22e409f96e93d7e117393172a',
|
|
178
|
+
'ae2d8a571e03ac9c9eb76fac45af8e51',
|
|
179
|
+
'30c81c46a35ce411e5fbc1191a0a52ef',
|
|
180
|
+
'f69f2445df4f9b17ad2b417be66c3710'
|
|
181
|
+
];
|
|
182
|
+
|
|
183
|
+
var outputs = [
|
|
184
|
+
'bd334f1d6e45f25ff712a214571fa5cc',
|
|
185
|
+
'974104846d0ad3ad7734ecb3ecee4eef',
|
|
186
|
+
'ef7afd2270e2e60adce0ba2face6444e',
|
|
187
|
+
'9a4b41ba738d6c72fb16691603c18e0e'
|
|
188
|
+
];
|
|
189
|
+
|
|
190
|
+
for(var i = 0; i < keys.length; ++i) {
|
|
191
|
+
(function(i) {
|
|
192
|
+
var key = UTIL.hexToBytes(keys[i]);
|
|
193
|
+
var input = UTIL.hexToBytes(inputs[i]);
|
|
194
|
+
var output = UTIL.hexToBytes(outputs[i]);
|
|
195
|
+
|
|
196
|
+
it('should aes-192-ecb encrypt: ' + inputs[i], function() {
|
|
197
|
+
// encrypt w/no padding
|
|
198
|
+
var cipher = CIPHER.createCipher('AES-ECB', key);
|
|
199
|
+
cipher.mode.pad = false;
|
|
200
|
+
cipher.start();
|
|
201
|
+
cipher.update(UTIL.createBuffer(input));
|
|
202
|
+
cipher.finish();
|
|
203
|
+
ASSERT.equal(cipher.output.toHex(), outputs[i]);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('should aes-192-ecb decrypt: ' + outputs[i], function() {
|
|
207
|
+
// decrypt w/no padding
|
|
208
|
+
var cipher = CIPHER.createDecipher('AES-ECB', key);
|
|
209
|
+
cipher.mode.unpad = false;
|
|
210
|
+
cipher.start();
|
|
211
|
+
cipher.update(UTIL.createBuffer(output));
|
|
212
|
+
cipher.finish();
|
|
213
|
+
ASSERT.equal(cipher.output.toHex(), inputs[i]);
|
|
214
|
+
});
|
|
215
|
+
})(i);
|
|
216
|
+
}
|
|
217
|
+
})();
|
|
218
|
+
|
|
219
|
+
// AES-256-ECB
|
|
220
|
+
(function() {
|
|
221
|
+
var keys = [
|
|
222
|
+
'603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4',
|
|
223
|
+
'603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4',
|
|
224
|
+
'603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4',
|
|
225
|
+
'603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'
|
|
226
|
+
];
|
|
227
|
+
|
|
228
|
+
var inputs = [
|
|
229
|
+
'6bc1bee22e409f96e93d7e117393172a',
|
|
230
|
+
'ae2d8a571e03ac9c9eb76fac45af8e51',
|
|
231
|
+
'30c81c46a35ce411e5fbc1191a0a52ef',
|
|
232
|
+
'f69f2445df4f9b17ad2b417be66c3710'
|
|
233
|
+
];
|
|
234
|
+
|
|
235
|
+
var outputs = [
|
|
236
|
+
'f3eed1bdb5d2a03c064b5a7e3db181f8',
|
|
237
|
+
'591ccb10d410ed26dc5ba74a31362870',
|
|
238
|
+
'b6ed21b99ca6f4f9f153e7b1beafed1d',
|
|
239
|
+
'23304b7a39f9f3ff067d8d8f9e24ecc7'
|
|
240
|
+
];
|
|
241
|
+
|
|
242
|
+
for(var i = 0; i < keys.length; ++i) {
|
|
243
|
+
(function(i) {
|
|
244
|
+
var key = UTIL.hexToBytes(keys[i]);
|
|
245
|
+
var input = UTIL.hexToBytes(inputs[i]);
|
|
246
|
+
var output = UTIL.hexToBytes(outputs[i]);
|
|
247
|
+
|
|
248
|
+
it('should aes-256-ecb encrypt: ' + inputs[i], function() {
|
|
249
|
+
// encrypt w/no padding
|
|
250
|
+
var cipher = CIPHER.createCipher('AES-ECB', key);
|
|
251
|
+
cipher.mode.pad = false;
|
|
252
|
+
cipher.start();
|
|
253
|
+
cipher.update(UTIL.createBuffer(input));
|
|
254
|
+
cipher.finish();
|
|
255
|
+
ASSERT.equal(cipher.output.toHex(), outputs[i]);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('should aes-256-ecb decrypt: ' + outputs[i], function() {
|
|
259
|
+
// decrypt w/no padding
|
|
260
|
+
var cipher = CIPHER.createDecipher('AES-ECB', key);
|
|
261
|
+
cipher.mode.unpad = false;
|
|
262
|
+
cipher.start();
|
|
263
|
+
cipher.update(UTIL.createBuffer(output));
|
|
264
|
+
cipher.finish();
|
|
265
|
+
ASSERT.equal(cipher.output.toHex(), inputs[i]);
|
|
266
|
+
});
|
|
267
|
+
})(i);
|
|
268
|
+
}
|
|
269
|
+
})();
|
|
270
|
+
|
|
115
271
|
// AES-128-CBC
|
|
116
272
|
(function() {
|
|
117
273
|
var keys = [
|
|
@@ -160,18 +316,20 @@ function Tests(ASSERT, CIPHER, AES, UTIL) {
|
|
|
160
316
|
it('should aes-128-cbc encrypt: ' + inputs[i], function() {
|
|
161
317
|
// encrypt w/no padding
|
|
162
318
|
var cipher = CIPHER.createCipher('AES-CBC', key);
|
|
319
|
+
cipher.mode.pad = false;
|
|
163
320
|
cipher.start({iv: iv});
|
|
164
321
|
cipher.update(UTIL.createBuffer(input));
|
|
165
|
-
cipher.finish(
|
|
322
|
+
cipher.finish();
|
|
166
323
|
ASSERT.equal(cipher.output.toHex(), outputs[i]);
|
|
167
324
|
});
|
|
168
325
|
|
|
169
326
|
it('should aes-128-cbc decrypt: ' + outputs[i], function() {
|
|
170
327
|
// decrypt w/no padding
|
|
171
328
|
var cipher = CIPHER.createDecipher('AES-CBC', key);
|
|
329
|
+
cipher.mode.unpad = false;
|
|
172
330
|
cipher.start({iv: iv});
|
|
173
331
|
cipher.update(UTIL.createBuffer(output));
|
|
174
|
-
cipher.finish(
|
|
332
|
+
cipher.finish();
|
|
175
333
|
var out = (i & 1) ? cipher.output.toHex() : cipher.output.bytes();
|
|
176
334
|
ASSERT.equal(out, inputs[i]);
|
|
177
335
|
});
|
|
@@ -219,18 +377,20 @@ function Tests(ASSERT, CIPHER, AES, UTIL) {
|
|
|
219
377
|
it('should aes-192-cbc encrypt: ' + inputs[i], function() {
|
|
220
378
|
// encrypt w/no padding
|
|
221
379
|
var cipher = CIPHER.createCipher('AES-CBC', key);
|
|
380
|
+
cipher.mode.pad = false;
|
|
222
381
|
cipher.start({iv: iv});
|
|
223
382
|
cipher.update(UTIL.createBuffer(input));
|
|
224
|
-
cipher.finish(
|
|
383
|
+
cipher.finish();
|
|
225
384
|
ASSERT.equal(cipher.output.toHex(), outputs[i]);
|
|
226
385
|
});
|
|
227
386
|
|
|
228
387
|
it('should aes-192-cbc decrypt: ' + outputs[i], function() {
|
|
229
388
|
// decrypt w/no padding
|
|
230
389
|
var cipher = CIPHER.createDecipher('AES-CBC', key);
|
|
390
|
+
cipher.mode.unpad = false;
|
|
231
391
|
cipher.start({iv: iv});
|
|
232
392
|
cipher.update(UTIL.createBuffer(output));
|
|
233
|
-
cipher.finish(
|
|
393
|
+
cipher.finish();
|
|
234
394
|
var out = cipher.output.toHex();
|
|
235
395
|
ASSERT.equal(out, inputs[i]);
|
|
236
396
|
});
|
|
@@ -278,18 +438,20 @@ function Tests(ASSERT, CIPHER, AES, UTIL) {
|
|
|
278
438
|
it('should aes-256-cbc encrypt: ' + inputs[i], function() {
|
|
279
439
|
// encrypt w/no padding
|
|
280
440
|
var cipher = CIPHER.createCipher('AES-CBC', key);
|
|
441
|
+
cipher.mode.pad = false;
|
|
281
442
|
cipher.start({iv: iv});
|
|
282
443
|
cipher.update(UTIL.createBuffer(input));
|
|
283
|
-
cipher.finish(
|
|
444
|
+
cipher.finish();
|
|
284
445
|
ASSERT.equal(cipher.output.toHex(), outputs[i]);
|
|
285
446
|
});
|
|
286
447
|
|
|
287
448
|
it('should aes-256-cbc decrypt: ' + outputs[i], function() {
|
|
288
449
|
// decrypt w/no padding
|
|
289
450
|
var cipher = CIPHER.createDecipher('AES-CBC', key);
|
|
451
|
+
cipher.mode.unpad = false;
|
|
290
452
|
cipher.start({iv: iv});
|
|
291
453
|
cipher.update(UTIL.createBuffer(output));
|
|
292
|
-
cipher.finish(
|
|
454
|
+
cipher.finish();
|
|
293
455
|
var out = cipher.output.toHex();
|
|
294
456
|
ASSERT.equal(out, inputs[i]);
|
|
295
457
|
});
|
package/nodejs/ui/test.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-forge",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.33",
|
|
4
4
|
"description": "JavaScript implementations of network transports, cryptography, ciphers, PKI, message digests, and various utilities.",
|
|
5
5
|
"homepage": "http://github.com/digitalbazaar/forge",
|
|
6
6
|
"author": {
|