From fe570c754afb05082c9358322a2e0efc351f848c Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 8 Mar 2014 19:08:40 -0400 Subject: [PATCH] Genericify initSession (and break it for alice) --- js/helpers.js | 71 ++++++++++++++++---------- js/test.js | 6 +-- protos/IncomingPushMessageSignal.proto | 4 +- protos/WhisperTextProtocol.proto | 2 +- 4 files changed, 50 insertions(+), 33 deletions(-) diff --git a/js/helpers.js b/js/helpers.js index 50b500ed2..37cd3dca5 100644 --- a/js/helpers.js +++ b/js/helpers.js @@ -537,7 +537,7 @@ var crypto_tests = {}; /****************************** *** Ratchet implementation *** ******************************/ - var initSession = function(isInitiator, theirIdentityPubKey, ourEphemeralPrivKey, theirEphemeralPubKey, callback) { + var initSession = function(isInitiator, ourEphemeralKey, encodedNumber, theirIdentityPubKey, theirEphemeralPubKey, callback) { var ourIdentityPrivKey = crypto_storage.getIdentityPrivKey(); var sharedSecret; @@ -545,21 +545,30 @@ var crypto_tests = {}; sharedSecret = getString(ecRes); function finishInit() { - ECDHE(theirEphemeralPubKey, ourEphemeralPrivKey, function(ecRes) { + ECDHE(theirEphemeralPubKey, ourEphemeralKey.privKey, function(ecRes) { sharedSecret += getString(ecRes); - var masterKey = HKDF(sharedSecret, '', "WhisperText"); - callback({ rootKey: masterKey[0], chainKey: masterKey[1] }); + + var session = {currentRatchet: { rootKey: masterKey[0], ephemeralKeyPair: ourEphemeralKey, + lastRemoteEphemeralKey: theirEphemeralPubKey }, + oldRatchetList: [] + }; + session[getString(ourEphemeralKey.pubKey)] = { messageKeys: {}, chainKey: { counter: -1, key: masterKey[1] } }; + // This isnt an actual ratchet, its just here to make maybeStepRatchet work + session[getString(theirEphemeralPubKey)] = { messageKeys: {}, chainKey: { counter: 0xffffffff, key: '' } }; + crypto_storage.saveSession(encodedNumber, session); + + callback(); }); } if (isInitiator) { - ECDHE(theirIdentityPubKey, ourEphemeralPrivKey, function(ecRes) { + ECDHE(theirIdentityPubKey, ourEphemeralKey.privKey, function(ecRes) { sharedSecret = sharedSecret + getString(ecRes); finishInit(); }); } else { - ECDHE(theirIdentityPubKey, ourEphemeralPrivKey, function(ecRes) { + ECDHE(theirIdentityPubKey, ourEphemeralKey.privKey, function(ecRes) { sharedSecret = getString(ecRes) + sharedSecret; finishInit(); }); @@ -574,16 +583,7 @@ var crypto_tests = {}; if (preKeyPair === undefined) throw "Missing preKey for PreKeyWhisperMessage"; - initSession(false, message.identityKey, preKeyPair.privKey, message.baseKey, function(firstRatchet) { - var session = {currentRatchet: { rootKey: firstRatchet.rootKey, ephemeralKeyPair: preKeyPair, - lastRemoteEphemeralKey: message.baseKey }, - oldRatchetList: [] - }; - session[getString(preKeyPair.pubKey)] = { messageKeys: {}, chainKey: { counter: -1, key: firstRatchet.chainKey } }; - // This isnt an actual ratchet, its just here to make maybeStepRatchet work - session[getString(message.baseKey)] = { messageKeys: {}, chainKey: { counter: 0xffffffff, key: '' } }; - crypto_storage.saveSession(encodedNumber, session); - + initSession(false, preKeyPair, encodedNumber, message.identityKey, message.baseKey, function() { callback(); }); } @@ -633,14 +633,6 @@ var crypto_tests = {}; }); } - var doDecryptWhisperMessage = function(ciphertext, mac, messageKey, counter) { - //TODO keys swapped? - var keys = HKDF(messageKey, '', "WhisperMessageKeys"); - verifyMACWithVersionByte(ciphertext, keys[0], mac); - - return AES_CTR_NOPADDING(keys[1], CTR = counter, ciphertext); - } - // returns decrypted protobuf var decryptWhisperMessage = function(encodedNumber, messageBytes, callback) { var session = crypto_storage.getSession(encodedNumber); @@ -715,9 +707,34 @@ var crypto_tests = {}; } } - crypto.encryptMessageFor = function(deviceObject, message) { - return message + " encrypted to " + deviceObject.encodedNumber + " with relay " + deviceObject.relay + - " with identityKey " + deviceObject.identityKey + " and public key " + deviceObject.publicKey; //TODO + // callback(encoded [PreKey]WhisperMessage) + crypto.encryptMessageFor = function(deviceObject, pushMessageContent, callback) { + var session = crypto_storage.getSession(deviceObject.encodedNumber); + + var doEncryptPushMessageContent = function(callback) { + var msg = new WhisperMessageProtobuf(); + var plaintext = pushMessageContent.encode(); + //TODO + msg.ciphertext = plaintext;//TODO: WAT? + callback(msg.encode()); + } + + if (session === undefined) { + var preKeyMsg = new PreKeyWhisperMessageProtobuf(); + preKeyMsg.identityKey = getString(crypto_storage.getStoredPubKey("identityKey")); + createNewKeyPair(function(baseKey) { + preKeyMsg.baseKey = getString(baseKey.pubKey); + preKeyMsg.preKeyId = preKey.keyId; + initSession();//TODO + doEncryptPushMessageContent(function(message) { + preKeyMsg.message = getString(message); + callback(getString(preKeyMsg.encode())); + }); + }); + } else + doEncryptPushMessageContent(function(message) { + callback(getString(message)); + }); } var GENERATE_KEYS_KEYS_GENERATED = 100; diff --git a/js/test.js b/js/test.js index ff8384193..de0224e74 100644 --- a/js/test.js +++ b/js/test.js @@ -221,12 +221,12 @@ encryptedMessage: hexToArrayBuffer("415733486e6d3165754275487778594d2f4b744a556e postNaclMessage({command: "privToPub", priv: v.bobPre1}, function(message) { storage.putEncrypted("25519KeypreKey1", { pubKey: message.res, privKey: v.bobPre1 }); postNaclMessage({command: "privToPub", priv: v.bobLastResort}, function(message) { + storage.putEncrypted("25519KeypreKey16777215", { pubKey: message.res, privKey: v.bobLastResort }); storage.putEncrypted("signaling_key", v.sessionKey); var aliceToBob = crypto.decryptWebsocketMessage(v.encryptedMessage); if (getString(aliceToBob) != getString(v.aliceToBob)) callback(false); - storage.putEncrypted("25519KeypreKey16777215", { pubKey: message.res, privKey: v.bobLastResort }); - var b64 = base64EncArr(new Uint8Array(v.aliceToBob)); + var b64 = base64EncArr(new Uint8Array(toArrayBuffer(aliceToBob))); crypto.handleIncomingPushMessageProto(IncomingPushMessageProtobuf.decode(b64), function(decrypted_message) { callback(decrypted_message.body == "Hi Bob!" && decrypted_message.attachments.length == 0); }); @@ -251,5 +251,5 @@ encryptedMessage: hexToArrayBuffer("415733486e6d3165754275487778594d2f4b744a556e startNextExclusiveTest(); localStorage.clear(); - }, 250); + }, 500); }); diff --git a/protos/IncomingPushMessageSignal.proto b/protos/IncomingPushMessageSignal.proto index a86c2e1a4..69810c0cf 100644 --- a/protos/IncomingPushMessageSignal.proto +++ b/protos/IncomingPushMessageSignal.proto @@ -9,7 +9,7 @@ message IncomingPushMessageSignal { optional string relay = 3; repeated string destinations = 4; optional uint64 timestamp = 5; - optional bytes message = 6; // Contains an encrypted PushMessageContent + optional bytes message = 6; // Contains an encrypted [PreKey]WhisperMessage } message PushMessageContent { @@ -22,4 +22,4 @@ message PushMessageContent { } repeated AttachmentPointer attachments = 2; -} \ No newline at end of file +} diff --git a/protos/WhisperTextProtocol.proto b/protos/WhisperTextProtocol.proto index f14625b96..cea074584 100644 --- a/protos/WhisperTextProtocol.proto +++ b/protos/WhisperTextProtocol.proto @@ -7,7 +7,7 @@ message WhisperMessage { optional bytes ephemeralKey = 1; optional uint32 counter = 2; optional uint32 previousCounter = 3; - optional bytes ciphertext = 4; + optional bytes ciphertext = 4; // PushMessageContent } message PreKeyWhisperMessage {