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);