summaryrefslogtreecommitdiff
path: root/test/simple/test-crypto.js
diff options
context:
space:
mode:
Diffstat (limited to 'test/simple/test-crypto.js')
-rw-r--r--test/simple/test-crypto.js312
1 files changed, 256 insertions, 56 deletions
diff --git a/test/simple/test-crypto.js b/test/simple/test-crypto.js
index 535af760f..291ac504b 100644
--- a/test/simple/test-crypto.js
+++ b/test/simple/test-crypto.js
@@ -32,6 +32,8 @@ try {
process.exit();
}
+crypto.DEFAULT_ENCODING = 'buffer';
+
var fs = require('fs');
var path = require('path');
@@ -79,6 +81,62 @@ var h1 = crypto.createHmac('sha1', 'Node')
.digest('hex');
assert.equal(h1, '19fd6e1ba73d9ed2224dd5094a71babe85d9a892', 'test HMAC');
+// Test HMAC (Wikipedia Test Cases)
+var wikipedia = [
+ {
+ key: 'key', data: 'The quick brown fox jumps over the lazy dog',
+ hmac: { // HMACs lifted from Wikipedia.
+ md5: '80070713463e7749b90c2dc24911e275',
+ sha1: 'de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9',
+ sha256:
+ 'f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc' +
+ '2d1a3cd8'
+ }
+ },
+ {
+ key: 'key', data: '',
+ hmac: { // Intermediate test to help debugging.
+ md5: '63530468a04e386459855da0063b6596',
+ sha1: 'f42bb0eeb018ebbd4597ae7213711ec60760843f',
+ sha256:
+ '5d5d139563c95b5967b9bd9a8c9b233a9dedb45072794cd232dc1b74' +
+ '832607d0'
+ }
+ },
+ {
+ key: '', data: 'The quick brown fox jumps over the lazy dog',
+ hmac: { // Intermediate test to help debugging.
+ md5: 'ad262969c53bc16032f160081c4a07a0',
+ sha1: '2ba7f707ad5f187c412de3106583c3111d668de8',
+ sha256:
+ 'fb011e6154a19b9a4c767373c305275a5a69e8b68b0b4c9200c383dc' +
+ 'ed19a416'
+ }
+ },
+ {
+ key: '', data: '',
+ hmac: { // HMACs lifted from Wikipedia.
+ md5: '74e6f7298a9c2d168935f58c001bad88',
+ sha1: 'fbdb1d1b18aa6c08324b7d64b71fb76370690e1d',
+ sha256:
+ 'b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c71214' +
+ '4292c5ad'
+ }
+ },
+]
+
+for (var i = 0, l = wikipedia.length; i < l; i++) {
+ for (var hash in wikipedia[i]['hmac']) {
+ var result = crypto.createHmac(hash, wikipedia[i]['key'])
+ .update(wikipedia[i]['data'])
+ .digest('hex');
+ assert.equal(wikipedia[i]['hmac'][hash],
+ result,
+ 'Test HMAC-' + hash + ': Test case ' + (i + 1) + ' wikipedia');
+ }
+}
+
+
// Test HMAC-SHA-* (rfc 4231 Test Cases)
var rfc4231 = [
{
@@ -228,15 +286,20 @@ var rfc4231 = [
for (var i = 0, l = rfc4231.length; i < l; i++) {
for (var hash in rfc4231[i]['hmac']) {
+ var str = crypto.createHmac(hash, rfc4231[i].key);
+ str.end(rfc4231[i].data);
+ var strRes = str.read().toString('hex');
var result = crypto.createHmac(hash, rfc4231[i]['key'])
.update(rfc4231[i]['data'])
.digest('hex');
if (rfc4231[i]['truncate']) {
result = result.substr(0, 32); // first 128 bits == 32 hex chars
+ strRes = strRes.substr(0, 32);
}
assert.equal(rfc4231[i]['hmac'][hash],
result,
'Test HMAC-' + hash + ': Test case ' + (i + 1) + ' rfc 4231');
+ assert.equal(strRes, result, 'Should get same result from stream');
}
}
@@ -369,18 +432,42 @@ var a0 = crypto.createHash('sha1').update('Test123').digest('hex');
var a1 = crypto.createHash('md5').update('Test123').digest('binary');
var a2 = crypto.createHash('sha256').update('Test123').digest('base64');
var a3 = crypto.createHash('sha512').update('Test123').digest(); // binary
+var a4 = crypto.createHash('sha1').update('Test123').digest('buffer');
+
+// stream interface
+var a5 = crypto.createHash('sha512');
+a5.end('Test123');
+a5 = a5.read();
+
+var a6 = crypto.createHash('sha512');
+a6.write('Te');
+a6.write('st');
+a6.write('123');
+a6.end();
+a6 = a6.read();
assert.equal(a0, '8308651804facb7b9af8ffc53a33a22d6a1c8ac2', 'Test SHA1');
assert.equal(a1, 'h\u00ea\u00cb\u0097\u00d8o\fF!\u00fa+\u000e\u0017\u00ca' +
'\u00bd\u008c', 'Test MD5 as binary');
assert.equal(a2, '2bX1jws4GYKTlxhloUB09Z66PoJZW+y+hq5R8dnx9l4=',
'Test SHA256 as base64');
-assert.equal(a3, '\u00c1(4\u00f1\u0003\u001fd\u0097!O\'\u00d4C/&Qz\u00d4' +
- '\u0094\u0015l\u00b8\u008dQ+\u00db\u001d\u00c4\u00b5}\u00b2' +
- '\u00d6\u0092\u00a3\u00df\u00a2i\u00a1\u009b\n\n*\u000f' +
- '\u00d7\u00d6\u00a2\u00a8\u0085\u00e3<\u0083\u009c\u0093' +
- '\u00c2\u0006\u00da0\u00a1\u00879(G\u00ed\'',
- 'Test SHA512 as assumed binary');
+assert.deepEqual(
+ a3,
+ new Buffer(
+ '\u00c1(4\u00f1\u0003\u001fd\u0097!O\'\u00d4C/&Qz\u00d4' +
+ '\u0094\u0015l\u00b8\u008dQ+\u00db\u001d\u00c4\u00b5}\u00b2' +
+ '\u00d6\u0092\u00a3\u00df\u00a2i\u00a1\u009b\n\n*\u000f' +
+ '\u00d7\u00d6\u00a2\u00a8\u0085\u00e3<\u0083\u009c\u0093' +
+ '\u00c2\u0006\u00da0\u00a1\u00879(G\u00ed\'',
+ 'binary'),
+ 'Test SHA512 as assumed buffer');
+assert.deepEqual(a4,
+ new Buffer('8308651804facb7b9af8ffc53a33a22d6a1c8ac2', 'hex'),
+ 'Test SHA1');
+
+// stream interface should produce the same result.
+assert.deepEqual(a5, a3, 'stream interface is consistent');
+assert.deepEqual(a6, a3, 'stream interface is consistent');
// Test multiple updates to same hash
var h1 = crypto.createHash('sha1').update('Test123').digest('hex');
@@ -409,6 +496,11 @@ assert.throws(function() {
var s1 = crypto.createSign('RSA-SHA1')
.update('Test123')
.sign(keyPem, 'base64');
+var s1stream = crypto.createSign('RSA-SHA1');
+s1stream.end('Test123');
+s1stream = s1stream.sign(keyPem, 'base64');
+assert.equal(s1, s1stream, 'Stream produces same output');
+
var verified = crypto.createVerify('RSA-SHA1')
.update('Test')
.update('123')
@@ -417,13 +509,41 @@ assert.strictEqual(verified, true, 'sign and verify (base 64)');
var s2 = crypto.createSign('RSA-SHA256')
.update('Test123')
- .sign(keyPem); // binary
+ .sign(keyPem, 'binary');
+var s2stream = crypto.createSign('RSA-SHA256');
+s2stream.end('Test123');
+s2stream = s2stream.sign(keyPem, 'binary');
+assert.equal(s2, s2stream, 'Stream produces same output');
+
var verified = crypto.createVerify('RSA-SHA256')
.update('Test')
.update('123')
- .verify(certPem, s2); // binary
+ .verify(certPem, s2, 'binary');
assert.strictEqual(verified, true, 'sign and verify (binary)');
+var verStream = crypto.createVerify('RSA-SHA256');
+verStream.write('Tes');
+verStream.write('t12');
+verStream.end('3');
+verified = verStream.verify(certPem, s2, 'binary');
+assert.strictEqual(verified, true, 'sign and verify (stream)');
+
+var s3 = crypto.createSign('RSA-SHA1')
+ .update('Test123')
+ .sign(keyPem, 'buffer');
+var verified = crypto.createVerify('RSA-SHA1')
+ .update('Test')
+ .update('123')
+ .verify(certPem, s3);
+assert.strictEqual(verified, true, 'sign and verify (buffer)');
+
+var verStream = crypto.createVerify('RSA-SHA1');
+verStream.write('Tes');
+verStream.write('t12');
+verStream.end('3');
+verified = verStream.verify(certPem, s3);
+assert.strictEqual(verified, true, 'sign and verify (stream)');
+
function testCipher1(key) {
// Test encryption and decryption
@@ -441,6 +561,20 @@ function testCipher1(key) {
txt += decipher.final('utf8');
assert.equal(txt, plaintext, 'encryption and decryption');
+
+ // streaming cipher interface
+ // NB: In real life, it's not guaranteed that you can get all of it
+ // in a single read() like this. But in this case, we know it's
+ // quite small, so there's no harm.
+ var cStream = crypto.createCipher('aes192', key);
+ cStream.end(plaintext);
+ ciph = cStream.read();
+
+ var dStream = crypto.createDecipher('aes192', key);
+ dStream.end(ciph);
+ txt = dStream.read().toString('utf8');
+
+ assert.equal(txt, plaintext, 'encryption and decryption with streams');
}
@@ -481,6 +615,38 @@ function testCipher3(key, iv) {
txt += decipher.final('utf8');
assert.equal(txt, plaintext, 'encryption and decryption with key and iv');
+
+ // streaming cipher interface
+ // NB: In real life, it's not guaranteed that you can get all of it
+ // in a single read() like this. But in this case, we know it's
+ // quite small, so there's no harm.
+ var cStream = crypto.createCipheriv('des-ede3-cbc', key, iv);
+ cStream.end(plaintext);
+ ciph = cStream.read();
+
+ var dStream = crypto.createDecipheriv('des-ede3-cbc', key, iv);
+ dStream.end(ciph);
+ txt = dStream.read().toString('utf8');
+
+ assert.equal(txt, plaintext, 'streaming cipher iv');
+}
+
+
+function testCipher4(key, iv) {
+ // Test encyrption and decryption with explicit key and iv
+ var plaintext =
+ '32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
+ 'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
+ 'jAfaFg**';
+ var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
+ var ciph = cipher.update(plaintext, 'utf8', 'buffer');
+ ciph = Buffer.concat([ciph, cipher.final('buffer')]);
+
+ var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
+ var txt = decipher.update(ciph, 'buffer', 'utf8');
+ txt += decipher.final('utf8');
+
+ assert.equal(txt, plaintext, 'encryption and decryption with key and iv');
}
@@ -495,36 +661,38 @@ testCipher3('0123456789abcd0123456789', new Buffer('12345678'));
testCipher3(new Buffer('0123456789abcd0123456789'), '12345678');
testCipher3(new Buffer('0123456789abcd0123456789'), new Buffer('12345678'));
+testCipher4(new Buffer('0123456789abcd0123456789'), new Buffer('12345678'));
+
// update() should only take buffers / strings
assert.throws(function() {
crypto.createHash('sha1').update({foo: 'bar'});
-}, /string or buffer/);
+}, /buffer/);
// Test Diffie-Hellman with two parties sharing a secret,
// using various encodings as we go along
var dh1 = crypto.createDiffieHellman(256);
-var p1 = dh1.getPrime('base64');
+var p1 = dh1.getPrime('buffer');
var dh2 = crypto.createDiffieHellman(p1, 'base64');
var key1 = dh1.generateKeys();
var key2 = dh2.generateKeys('hex');
var secret1 = dh1.computeSecret(key2, 'hex', 'base64');
-var secret2 = dh2.computeSecret(key1, 'binary', 'base64');
+var secret2 = dh2.computeSecret(key1, 'binary', 'buffer');
-assert.equal(secret1, secret2);
+assert.equal(secret1, secret2.toString('base64'));
// Create "another dh1" using generated keys from dh1,
// and compute secret again
-var dh3 = crypto.createDiffieHellman(p1, 'base64');
+var dh3 = crypto.createDiffieHellman(p1, 'buffer');
var privkey1 = dh1.getPrivateKey();
dh3.setPublicKey(key1);
dh3.setPrivateKey(privkey1);
-assert.equal(dh1.getPrime(), dh3.getPrime());
-assert.equal(dh1.getGenerator(), dh3.getGenerator());
-assert.equal(dh1.getPublicKey(), dh3.getPublicKey());
-assert.equal(dh1.getPrivateKey(), dh3.getPrivateKey());
+assert.deepEqual(dh1.getPrime(), dh3.getPrime());
+assert.deepEqual(dh1.getGenerator(), dh3.getGenerator());
+assert.deepEqual(dh1.getPublicKey(), dh3.getPublicKey());
+assert.deepEqual(dh1.getPrivateKey(), dh3.getPrivateKey());
var secret3 = dh3.computeSecret(key2, 'hex', 'base64');
@@ -534,6 +702,16 @@ assert.throws(function() {
dh3.computeSecret('');
}, /key is too small/i);
+// Create a shared using a DH group.
+var alice = crypto.createDiffieHellmanGroup('modp5');
+var bob = crypto.createDiffieHellmanGroup('modp5');
+alice.generateKeys();
+bob.generateKeys();
+var aSecret = alice.computeSecret(bob.getPublicKey()).toString('hex');
+var bSecret = bob.computeSecret(alice.getPublicKey()).toString('hex');
+assert.equal(aSecret, bSecret);
+
+
// https://github.com/joyent/node/issues/2338
assert.throws(function() {
var p = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' +
@@ -622,46 +800,68 @@ assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true);
//
// Test PBKDF2 with RFC 6070 test vectors (except #4)
//
-crypto.pbkdf2('password', 'salt', 1, 20, function(err, result) {
- assert.equal(result,
- '\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24' +
- '\xaf\x60\x12\x06\x2f\xe0\x37\xa6',
- 'pbkdf1 test vector 1');
-});
+function testPBKDF2(password, salt, iterations, keylen, expected) {
+ var actual = crypto.pbkdf2Sync(password, salt, iterations, keylen);
+ assert.equal(actual.toString('binary'), expected);
-crypto.pbkdf2('password', 'salt', 2, 20, function(err, result) {
- assert.equal(result,
- '\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a' +
- '\xce\x1d\x41\xf0\xd8\xde\x89\x57',
- 'pbkdf1 test vector 2');
-});
+ crypto.pbkdf2(password, salt, iterations, keylen, function(err, actual) {
+ assert.equal(actual.toString('binary'), expected);
+ });
+}
-crypto.pbkdf2('password', 'salt', 4096, 20, function(err, result) {
- assert.equal(result,
- '\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26' +
- '\xf7\x21\xd0\x65\xa4\x29\xc1',
- 'pbkdf1 test vector 3');
-});
-crypto.pbkdf2(
- 'passwordPASSWORDpassword',
- 'saltSALTsaltSALTsaltSALTsaltSALTsalt',
- 4096,
- 25, function(err, result) {
- assert.equal(result,
- '\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8\xd8\x36\x62' +
- '\xc0\xe4\x4a\x8b\x29\x1a\x96\x4c\xf2\xf0\x70\x38',
- 'pbkdf1 test vector 5');
- });
-
-crypto.pbkdf2('pass\0word', 'sa\0lt', 4096, 16, function(err, result) {
- assert.equal(result,
- '\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37\xd7\xf0\x34' +
- '\x25\xe0\xc3',
- 'pbkdf1 test vector 6');
-});
+testPBKDF2('password', 'salt', 1, 20,
+ '\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24' +
+ '\xaf\x60\x12\x06\x2f\xe0\x37\xa6');
-// Error path should not leak memory (check with valgrind).
-assert.throws(function() {
- crypto.pbkdf2('password', 'salt', 1, 20, null);
-});
+testPBKDF2('password', 'salt', 2, 20,
+ '\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a' +
+ '\xce\x1d\x41\xf0\xd8\xde\x89\x57');
+
+testPBKDF2('password', 'salt', 4096, 20,
+ '\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26' +
+ '\xf7\x21\xd0\x65\xa4\x29\xc1');
+
+testPBKDF2('passwordPASSWORDpassword',
+ 'saltSALTsaltSALTsaltSALTsaltSALTsalt',
+ 4096,
+ 25,
+ '\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8\xd8\x36\x62' +
+ '\xc0\xe4\x4a\x8b\x29\x1a\x96\x4c\xf2\xf0\x70\x38');
+
+testPBKDF2('pass\0word', 'sa\0lt', 4096, 16,
+ '\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37\xd7\xf0\x34' +
+ '\x25\xe0\xc3');
+
+function assertSorted(list) {
+ for (var i = 0, k = list.length - 1; i < k; ++i) {
+ var a = list[i + 0];
+ var b = list[i + 1];
+ assert(a <= b);
+ }
+}
+
+// Assume that we have at least AES256-SHA.
+assert.notEqual(0, crypto.getCiphers());
+assert.notEqual(-1, crypto.getCiphers().indexOf('AES256-SHA'));
+assertSorted(crypto.getCiphers());
+
+// Assert that we have sha and sha1 but not SHA and SHA1.
+assert.notEqual(0, crypto.getHashes());
+assert.notEqual(-1, crypto.getHashes().indexOf('sha1'));
+assert.notEqual(-1, crypto.getHashes().indexOf('sha'));
+assert.equal(-1, crypto.getHashes().indexOf('SHA1'));
+assert.equal(-1, crypto.getHashes().indexOf('SHA'));
+assertSorted(crypto.getHashes());
+
+(function() {
+ var c = crypto.createDecipher('aes-128-ecb', '');
+ assert.throws(function() { c.final('utf8') }, /invalid public key/);
+})();
+
+// Base64 padding regression test, see #4837.
+(function() {
+ var c = crypto.createCipher('aes-256-cbc', 'secret');
+ var s = c.update('test', 'utf8', 'base64') + c.final('base64');
+ assert.equal(s, '375oxUQCIocvxmC5At+rvA==');
+})();