Few more steps

This commit is contained in:
Matt Corallo 2014-03-06 17:44:59 -04:00
parent 465bdf2bd3
commit 6e0fe271ab
2 changed files with 63 additions and 31 deletions

View file

@ -77,6 +77,7 @@ function base64EncArr (aBytes) {
*** Type conversion utilities ***
*********************************/
// Strings/arrays
//TODO: Throw all this shit in favor of consistent types
var StaticByteBufferProto = new dcodeIO.ByteBuffer().__proto__;
var StaticArrayBufferProto = new ArrayBuffer().__proto__;
var StaticUint8ArrayProto = new Uint8Array().__proto__;
@ -108,6 +109,8 @@ function toArrayBuffer(thing) {
//TODO: Optimize this for specific cases
if (thing === undefined)
return undefined;
if (thing === Object(thing) && thing.__proto__ == StaticArrayBufferProto)
return thing;
if (!getStringable(thing))
throw "Tried to convert a non-stringable thing of type " + typeof thing + " to an array buffer";
var str = getString(thing);
@ -396,6 +399,8 @@ function getRandomBytes(size) {
}
}
var crypto_tests = {};
(function(crypto, $, undefined) {
var createNewKeyPair = function(callback) {
var privKey = getRandomBytes(32);
@ -467,31 +472,39 @@ function getRandomBytes(size) {
}
var HMACSHA256 = function(input, key) {
//TODO: return type
//TODO: Waaayyyy less type conversion here (probably just means replacing CryptoJS)
return CryptoJS.HmacSHA256(
CryptoJS.lib.WordArray.create(toArrayBuffer(input)),
CryptoJS.enc.Latin1.parse(getString(key)))
.toString(CryptoJS.enc.Latin1);
}
crypto_tests.HKDF = function(input, salt, info) {
// Specific implementation of RFC 5869 that only returns exactly 64 bytes
var PRK = HMACSHA256(input, salt);
var infoString = getString(info);
var T1 = HMACSHA256(infoString + String.fromCharCode(1), PRK);
var T2 = HMACSHA256(getString(T1) + infoString + String.fromCharCode(2), PRK);
return [ T1, T2 ];
}
var HKDF = function(input, salt, info) {
var key;
// HKDF for TextSecure has a bit of additional handling - salts always end up being 32 bytes
if (salt == '') {
var key = new ArrayBuffer(32);
var uintKey = new Uint8Array(key);
salt = new ArrayBuffer(32);
var uintKey = new Uint8Array(salt);
for (var i = 0; i < 32; i++)
uintKey[i] = 0;
} else
key = toArrayBuffer(salt);
}
if (key.byteLength != 32)
salt = toArrayBuffer(salt);
if (salt.byteLength != 32)
throw "Got salt of incorrect length";
var PRK = HMACSHA256(input, salt);
HMACSHA256(salt, input);
var hkdf = "HKDF(" + input + ", " + salt + ", " + info + ")"; //TODO
return [ hkdf.substring(0, 32), hkdf.substring(32, 64) ];
return crypto_tests.HKDF(input, salt, info);
}
var decryptPaddedAES = function(ciphertext, key, iv) {
@ -518,11 +531,11 @@ function getRandomBytes(size) {
var sharedSecret;
ECDHE(theirEphemeralPubKey, ourIdentityPrivKey, function(ecRes) {
sharedSecret = ecRes;
sharedSecret = getString(ecRes);
function finishInit() {
ECDHE(theirEphemeralPubKey, ourEphemeralPrivKey, function(ecRes) {
sharedSecret += ecRes;
sharedSecret += getString(ecRes);
var masterKey = HKDF(sharedSecret, '', "WhisperText");
callback({ rootKey: masterKey[0], chainKey: masterKey[1] });
@ -531,12 +544,12 @@ function getRandomBytes(size) {
if (isInitiator) {
ECDHE(theirIdentityPubKey, ourEphemeralPrivKey, function(ecRes) {
sharedSecret = sharedSecret + ecRes;
sharedSecret = sharedSecret + getString(ecRes);
finishInit();
});
} else {
ECDHE(theirIdentityPubKey, ourEphemeralPrivKey, function(ecRes) {
sharedSecret = ecRes + sharedSecret;
sharedSecret = getString(ecRes) + sharedSecret;
finishInit();
});
}
@ -631,7 +644,7 @@ function getRandomBytes(size) {
var message = decodeWhisperMessageProtobuf(messageProto);
maybeStepRatchet(session, getString(message.ephemeralKey), message.previousCounter, function() {
maybeStepRatchet(session, message.ephemeralKey, message.previousCounter, function() {
var chain = session[getString(message.ephemeralKey)];
fillMessageKeys(chain, message.counter);

View file

@ -114,7 +114,7 @@ registerOnLoadFunction(function() {
crypto.generateKeys(function() {
callback(true);
});
}, "Test simple create key");
}, "Test simple create key", true);
TEST(function(callback) {
// These are just some random curve25519 test vectors I found online
@ -167,21 +167,40 @@ registerOnLoadFunction(function() {
});
}, "Simple Curve25519 test vector");
TEST(function(callback) {
var IKM = new Uint8Array(new ArrayBuffer(22));
for (var i = 0; i < 22; i++)
IKM[i] = 11;
var salt = new Uint8Array(new ArrayBuffer(13));
for (var i = 0; i < 13; i++)
salt[i] = i;
var info = new Uint8Array(new ArrayBuffer(10));
for (var i = 0; i < 10; i++)
info[i] = 240 + i;
var OKM = crypto_tests.HKDF(IKM, salt, info);
var T1 = hexToArrayBuffer("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf");
var T2 = hexToArrayBuffer("34007208d5b887185865");
callback(getString(OKM[0]) == getString(T1) && getString(OKM[1]).substring(0, 10) == getString(T2));
}, "HMAC RFC5869 Test vectors");
var axolotlTestVectors = {
aliceIdentityPriv: hexToArrayBuffer("38115e981295947fb6130c3a9521760e9692476143810c64bb502d2a7757f953"),
aliceIdentityPub: hexToArrayBuffer("057f6f0cf5a353e3c2fa73774d36b07d491c2ba5285388a4dc7be3b08de4528933"),
bobIdentityPriv: hexToArrayBuffer("9069fadc08faaf6265a90a41fd1a9214bc70eb44ab30aa92ea5ad5a6b8609557"),
bobIdentityPub: hexToArrayBuffer("05889d0f94f4049fac36cc939c50dabec18c2af8e344f2cdf72cb5b0b02323337c"),
aliceLastResort: hexToArrayBuffer("10cd8adcbbf5a0157ed45e3be2e0bde5e91c3cdf77954530ac75c6ae9b8c2458"),
bobLastResort: hexToArrayBuffer("9855c7ce178404bb02c6c026103cc7d74d68a12f77d35d03df40a5f2dff6784d"),
alicePre0: hexToArrayBuffer("981bea233e094a34f7d564c63515af4691d3059268371c3b26f37a141e4fb553"),
alicePre1: hexToArrayBuffer("18b27cac90879c8ba5b1d6eb29d08ee380bac2e1022ead9a7dbe5ddfa0009852"),
bobPre0: hexToArrayBuffer("780fc02d2b8ffce8cd6f92233ce28b46a487dafeb97597461b1ed964fb118e5c"),
bobPre1: hexToArrayBuffer("c8e218839b33ae6c54d73ef56ad77551b6575e64c5b4acc0f0710b93799c3b56"),
aliceToBob: hexToArrayBuffer("08031205414c4943452203424f4228bff1f9c3c92832860122080012210541ef7f7215ffb6260413ab2c95bbd39d5d8d55241de87a6a7fa50ae5d99cbe741a21057f6f0cf5a353e3c2fa73774d36b07d491c2ba5285388a4dc7be3b08de4528933223b220a2105c851726034e7181614e21c6349d33f9bcff4f4becfc08c4422c6606cdc976d2c100018012209bb4876c684c88dd05207274341f4e3aa91"),
aliceIdentityPriv: hexToArrayBuffer("d8dab419978a2693f2842691931e4c8aaa09a11e8a94b5817cc4f81a1c474a62"),
aliceIdentityPub: hexToArrayBuffer("0502e9e6c0528ea9e44d8cb759aeaa02ae3eccbe3107de4f0815240b414744fd22"),
bobIdentityPriv: hexToArrayBuffer("18bd2244222329293a303343759e8e9feb4a4e2771273111528ef97abb6a567e"),
bobIdentityPub: hexToArrayBuffer("05b1cb0b5f1e5c93d20a3db2af0ab2512d39d91e6b671ee8e462a62658ba064a5b"),
aliceLastResort: hexToArrayBuffer("8825a933b97d40f65ea37701800900f10d8ba6dff6979a5634e0dc6de8d9b24f"),
bobLastResort: hexToArrayBuffer("c054dbefd8eee42ff3c1bb873def01f05411304ee07014ff86088c11f57b8e76"),
alicePre0: hexToArrayBuffer("384db59677ea9545f1da2c10426b463fb3180bd30d294ad69cd91b44e3a3ad43"),
alicePre1: hexToArrayBuffer("a841ece2aab82a0542c59c0daca5bd0ae36bc81b3f375ba0ffcc73ab2feacf6f"),
bobPre0: hexToArrayBuffer("10b6b52b867f79e330a5fa3b46fd6a542a1dc21d1103f4d2e8f741c0dd989474"),
bobPre1: hexToArrayBuffer("70be59ec978e3aaa95b64635b09ad1a614c2eda2142ac577b1eb6b1ec8e7f270"),
aliceToBob: hexToArrayBuffer("08031205414c4943452203424f4228c3dfc6cac92832860122080012210518761fa74e002dbbbb140ca7950fb83a3aab3dd4fb7b75ec87eea17f0cde7e0a1a210502e9e6c0528ea9e44d8cb759aeaa02ae3eccbe3107de4f0815240b414744fd22223b220a2105fbad228c11ab8098c3fcb9c16ff1f9df705dce81ea4b6e3df988148e254270751000180122093cfc98c3bc5557b31ffe8deba6900bcfe6"),
plain: hexToArrayBuffer("0a07486920426f6221"),
sessionKey: hexToArrayBuffer("03a3a58503e91c9e5ae179fa87bbb755f7afe35a2bffce4932cec2c2fcaa28832389e20000c7e1e7c7365959e4146d98f3620df9"),
encryptedMessage: hexToArrayBuffer("41576d4e6f7431327748385470366f724c7735416a62425446767139314c376857757a663854394e54775256326955384f76376265494463587030396634356441506159515a456a6e71704176364852574f3539584e35796d73507548423342716f78594e7136396346424c6e4145766439495a2f6674593835555a586e5668493574704e673946354c56627a4e70474563436672762f6a69393661675837755936335867746342683177412b5967364a472b37626a4a3044542b526e67383579325852705473644d3931794144776b5a744478616d7976412f714746556b37447a7353367061704a364459532b6e35673841457230764f37413d3d"),
sessionKey: hexToArrayBuffer("34400f1fde8f3b96beb435c280a6e93b829679b7e948a85c2f7250c6bfd419dd411a0e9cb5f62cd8b39e2ba23e013763169eb40a"),
encryptedMessage: hexToArrayBuffer("415733486e6d3165754275487778594d2f4b744a556e63364f67386e45754d6868663054704f486b45494b786c33616a79544552665531354c7539687a426736572f38546b7255583957653542724572724b3867367544554348425257555646774c4662614c67497446722f3242492f56434c31307a49666e2b765457524d324474475a46345a36553869717633566179443273354330417274386d6f48517342524970535a59387841566e584464572f466c4e7632706f6c5a6a2f464e597635552b56335933324552417572327464344a44654e6c544d4c6d4b7456387252384f354d7546626e735074336846456d496d374d7633573039673d3d")
};
// Axolotl test vectors