js-nacl
Version:
High-level API to libsodium.
248 lines (217 loc) • 10.5 kB
JavaScript
if (typeof module !== 'undefined' && module.exports) {
// We are running in node
var nacl;
require("../lib/nacl_factory.js").instantiate(function (nacl_instance) {
nacl = nacl_instance;
});
var assert = require("assert");
var suite = module.exports;
} else {
// We are running in browser, and runner.html has set nacl, assert
// and suite up for us.
}
function wouldBeRandomInARealProgram(howmuch) {
return new Uint8Array(howmuch);
}
suite.utf8Encoding = function () {
assert.equal(nacl.to_hex(nacl.encode_utf8("\xe5\xe4\xf6")), "c3a5c3a4c3b6");
};
suite.hexEncoding = function () {
assert.equal(nacl.to_hex(nacl.encode_utf8("hello")), "68656c6c6f");
};
suite.hexDecoding = function () {
assert.equal(nacl.decode_utf8(nacl.from_hex("68656c6c6f")), "hello");
assert.equal(nacl.decode_utf8(nacl.from_hex("68656C6C6F")), "hello");
};
suite.hashing = function () {
assert.equal(nacl.to_hex(nacl.crypto_hash_string("hello")),
"9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca7"+
"2323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043");
assert.equal(nacl.to_hex(nacl.crypto_hash(nacl.encode_utf8("hello"))),
"9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca7"+
"2323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043");
assert.equal(nacl.to_hex(nacl.crypto_hash_sha256(nacl.encode_utf8("hello"))),
"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824");
};
suite.boxKeypairFromSeed = function () {
var seed = nacl.encode_utf8("hello");
var kp = nacl.crypto_box_seed_keypair(seed);
assert.equal(nacl.to_hex(kp.boxPk),
"d8333ecf53dac465d59f3b03878ceff88947eec57c965105a049a0f5f1b7a510");
assert.equal(nacl.to_hex(kp.boxSk),
"9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca7");
var selfDHkey = nacl.crypto_box_precompute(kp.boxPk, kp.boxSk);
assert.equal(nacl.to_hex(selfDHkey.boxK),
"9f6c32cd88662c3cfc7e41c8f8b06960c71e560c35b693966085a68317b4cce9");
};
suite.randomBoxNonceLength = function () {
assert.equal(nacl.crypto_box_random_nonce().length, nacl.crypto_box_NONCEBYTES);
};
suite.precomputedBox = function () {
var seed = nacl.encode_utf8("hello");
var kp = nacl.crypto_box_seed_keypair(seed);
var selfShared = nacl.crypto_box_precompute(kp.boxPk, kp.boxSk);
var nonce = wouldBeRandomInARealProgram(nacl.crypto_box_NONCEBYTES);
var plaintext = "box test";
var c = nacl.crypto_box_precomputed(nacl.encode_utf8(plaintext), nonce, selfShared);
assert.equal(nacl.to_hex(c), "1ac48540344a19bd9516a2ea01d99f889dc97a47ba58946d");
var m = nacl.crypto_box_open_precomputed(c, nonce, selfShared);
assert.equal(nacl.decode_utf8(m), plaintext);
};
suite.normalBox = function () {
var seed = nacl.encode_utf8("hello");
var kp = nacl.crypto_box_seed_keypair(seed);
var nonce = wouldBeRandomInARealProgram(nacl.crypto_box_NONCEBYTES);
var plaintext = "box test";
var c = nacl.crypto_box(nacl.encode_utf8(plaintext), nonce, kp.boxPk, kp.boxSk);
assert.equal(nacl.to_hex(c), "1ac48540344a19bd9516a2ea01d99f889dc97a47ba58946d");
var m = nacl.crypto_box_open(c, nonce, kp.boxPk, kp.boxSk);
assert.equal(nacl.decode_utf8(m), plaintext);
};
suite.stream = function () {
var n = wouldBeRandomInARealProgram(nacl.crypto_stream_NONCEBYTES);
var k = wouldBeRandomInARealProgram(nacl.crypto_stream_KEYBYTES);
assert.equal(nacl.to_hex(nacl.crypto_stream(10, n, k)), "ba6e26df4b2ea2cf64d2");
var c = nacl.crypto_stream_xor(nacl.encode_utf8("hello"), n, k);
assert.equal(nacl.to_hex(c), "d20b4ab324");
var m = nacl.crypto_stream_xor(c, n, k);
assert.equal(nacl.decode_utf8(m), "hello");
};
suite.onetimeAuth = function () {
var authkey =
nacl.crypto_hash(nacl.encode_utf8("hello")).subarray(0, nacl.crypto_onetimeauth_KEYBYTES);
var auth = nacl.crypto_onetimeauth(nacl.encode_utf8("hello"), authkey);
assert.equal(nacl.to_hex(auth), "8acf9be1c2048a66ae442c83f2ae21c1");
assert.ok(nacl.crypto_onetimeauth_verify(auth, nacl.encode_utf8("hello"), authkey));
assert.equal(nacl.crypto_onetimeauth_verify(auth,
nacl.encode_utf8("hellp"), // <==
authkey),
false);
assert.equal(nacl.crypto_onetimeauth_verify(auth.subarray(1), // <==
nacl.encode_utf8("hello"),
authkey),
false);
auth[0] = auth[0] + 1;
assert.equal(nacl.crypto_onetimeauth_verify(auth, // <== modified
nacl.encode_utf8("hello"),
authkey),
false);
};
suite.auth = function () {
var authkey =
nacl.crypto_hash(nacl.encode_utf8("hello")).subarray(0, nacl.crypto_auth_KEYBYTES);
var auth = nacl.crypto_auth(nacl.encode_utf8("hello"), authkey);
assert.equal(nacl.to_hex(auth),
"3363a029b88688109b420ea8bed190228893c3fc85c18bf0dc4a1d14b4ce57fd");
assert.ok(nacl.crypto_auth_verify(auth, nacl.encode_utf8("hello"), authkey));
assert.equal(nacl.crypto_auth_verify(auth, nacl.encode_utf8("hellp"), authkey), false);
assert.equal(nacl.crypto_auth_verify(auth.subarray(1), nacl.encode_utf8("hello"), authkey),
false);
auth[0] = auth[0] + 1;
assert.equal(nacl.crypto_auth_verify(auth, nacl.encode_utf8("hello"), authkey), false);
};
suite.secretBox = function () {
var n = wouldBeRandomInARealProgram(nacl.crypto_secretbox_NONCEBYTES);
var secretboxkey =
nacl.crypto_hash(nacl.encode_utf8("thekey")).subarray(0, nacl.crypto_secretbox_KEYBYTES);
var plaintext = "hello";
var c = nacl.crypto_secretbox(nacl.encode_utf8(plaintext), n, secretboxkey);
assert.equal(nacl.to_hex(c), "08877931f3041765b847df995236a3c6b799cabe24");
var m = nacl.crypto_secretbox_open(c, n, secretboxkey);
assert.equal(nacl.decode_utf8(m), plaintext);
};
suite.signatures = function () {
var seedlen = nacl.crypto_sign_SECRETKEYBYTES / 2; // probably should be defined as a constant
var seed = nacl.crypto_hash_string("This is my passphrase").subarray(0, seedlen);
assert.equal(nacl.to_hex(seed),
"2268afda5a2a900cf07bdbaa05312a958b54e25c8042157840b8e79386512af1");
var kp = nacl.crypto_sign_seed_keypair(seed);
assert.equal(nacl.to_hex(kp.signPk),
"ba1000e3fe1213a53129e2d071c5e55a9afcad1c355fae453dd4dd2e7aaac242");
assert.equal(nacl.to_hex(kp.signSk),
"2268afda5a2a900cf07bdbaa05312a958b54e25c8042157840b8e79386512af1"+
"ba1000e3fe1213a53129e2d071c5e55a9afcad1c355fae453dd4dd2e7aaac242");
var message = "message";
var c = nacl.crypto_sign(nacl.encode_utf8(message), kp.signSk);
assert.equal(nacl.to_hex(c),
"d11d1612189ce965201e839bd007e2fe5f726a7ddc54ea3fba41f7d14207b542"+
"f60c6fee4eca64b630ef0d450b2ea0a72bdf5f526f5678ee55b979f368c52f0a"+
"6d657373616765");
var detached_sig = nacl.crypto_sign_detached(nacl.encode_utf8(message), kp.signSk);
assert.equal(nacl.to_hex(detached_sig),
"d11d1612189ce965201e839bd007e2fe5f726a7ddc54ea3fba41f7d14207b542"+
"f60c6fee4eca64b630ef0d450b2ea0a72bdf5f526f5678ee55b979f368c52f0a");
var m = nacl.crypto_sign_open(c, kp.signPk);
assert.notEqual(m, null);
assert.equal(nacl.decode_utf8(m), message);
assert.ok(nacl.crypto_sign_verify_detached(detached_sig, nacl.encode_utf8(message), kp.signPk));
// Corrupt the signature
c = nacl.decode_latin1(c);
c = c.substring(0, 35) + '!' + c.substring(36);
c = nacl.encode_latin1(c);
m = nacl.crypto_sign_open(c, kp.signPk);
assert.equal(m, null);
// Corrupt the detached signature
detached_sig = nacl.decode_latin1(detached_sig);
detached_sig = detached_sig.substring(0, 35) + '!' + detached_sig.substring(36);
detached_sig = nacl.encode_latin1(detached_sig);
assert.equal(nacl.crypto_sign_verify_detached(detached_sig,
nacl.encode_utf8(message),
kp.signPk),
false);
};
suite.randomBoxKeyRoundtrip = function () {
var kp = nacl.crypto_box_keypair_from_raw_sk(nacl.random_bytes(nacl.crypto_box_SECRETKEYBYTES));
var n = nacl.crypto_box_random_nonce();
var message = "message";
assert.equal(nacl.decode_utf8(nacl.crypto_box_open(nacl.crypto_box(nacl.encode_utf8(message),
n, kp.boxPk, kp.boxSk),
n, kp.boxPk, kp.boxSk)),
message);
};
suite.curve25519_correctness = function () {
// Check correctness of curve25519 via NaCl test vector
var alice_private =
nacl.from_hex("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a");
var bob_public =
nacl.from_hex("de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f");
assert.equal(nacl.to_hex(nacl.crypto_scalarmult(alice_private,bob_public)),
"4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");
};
suite.randomSignKeyRoundtrip = function () {
var kp = nacl.crypto_sign_keypair();
var message = "message";
assert.equal(nacl.decode_utf8(nacl.crypto_sign_open(nacl.crypto_sign(nacl.encode_utf8(message),
kp.signSk),
kp.signPk)),
message);
assert.ok(nacl.crypto_sign_verify_detached(nacl.crypto_sign_detached(nacl.encode_utf8(message),
kp.signSk),
nacl.encode_utf8(message),
kp.signPk));
};
suite.seededBoxKeypairIdentities1 = function () {
var kp1 = nacl.crypto_box_keypair();
var kp2 = nacl.crypto_box_keypair_from_raw_sk(kp1.boxSk);
assert.equal(nacl.to_hex(kp2.boxPk), nacl.to_hex(kp1.boxPk));
assert.equal(nacl.to_hex(kp2.boxSk), nacl.to_hex(kp1.boxSk));
};
suite.seededBoxKeypairIdentities2 = function () {
var seed = nacl.encode_utf8("the seed");
var sk = nacl.crypto_hash(seed).subarray(0, nacl.crypto_box_SECRETKEYBYTES);
var kp = nacl.crypto_box_seed_keypair(seed);
assert.equal(nacl.to_hex(kp.boxSk), nacl.to_hex(sk));
};
suite.seededSignKeypairIdentities1 = function () {
var seedlen = nacl.crypto_sign_SECRETKEYBYTES / 2; // probably should be defined as a constant
var kp1 = nacl.crypto_sign_keypair();
var kp2 = nacl.crypto_sign_seed_keypair(kp1.signSk.subarray(0, seedlen));
assert.equal(nacl.to_hex(kp2.signPk), nacl.to_hex(kp1.signPk));
assert.equal(nacl.to_hex(kp2.signSk), nacl.to_hex(kp1.signSk));
};
suite.seededSignKeypairIdentities2 = function () {
var seedlen = nacl.crypto_sign_SECRETKEYBYTES / 2; // probably should be defined as a constant
var seed = nacl.crypto_hash(nacl.encode_utf8("the seed")).subarray(0, seedlen);
var kp = nacl.crypto_sign_seed_keypair(seed);
assert.equal(nacl.to_hex(kp.signSk.subarray(0, seedlen)), nacl.to_hex(seed));
};