Naively move textsecure.crypto into axolotl.crypto
This commit is contained in:
parent
849fdb7ae4
commit
66cf5b08db
13 changed files with 16433 additions and 65 deletions
10
Gruntfile.js
10
Gruntfile.js
|
@ -109,6 +109,14 @@ module.exports = function(grunt) {
|
||||||
'libtextsecure/test/_test.js'
|
'libtextsecure/test/_test.js'
|
||||||
],
|
],
|
||||||
dest: 'libtextsecure/test/test.js',
|
dest: 'libtextsecure/test/test.js',
|
||||||
|
},
|
||||||
|
libaxolotltest: {
|
||||||
|
src: [
|
||||||
|
'components/mocha/mocha.js',
|
||||||
|
'components/chai/chai.js',
|
||||||
|
'libaxolotl/test/_test.js'
|
||||||
|
],
|
||||||
|
dest: 'libaxolotl/test/test.js',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sass: {
|
sass: {
|
||||||
|
@ -167,7 +175,7 @@ module.exports = function(grunt) {
|
||||||
'saucelabs-mocha': {
|
'saucelabs-mocha': {
|
||||||
all: {
|
all: {
|
||||||
options: {
|
options: {
|
||||||
urls: ['http://127.0.0.1:9999/test/index.html', 'http://127.0.0.1:9999/libtextsecure/test/index.html'],
|
urls: ['http://127.0.0.1:9999/test/index.html', 'http://127.0.0.1:9999/libtextsecure/test/index.html', 'http://127.0.0.1:9999/libaxolotl/test/index.html'],
|
||||||
build: process.env.TRAVIS_JOB_ID,
|
build: process.env.TRAVIS_JOB_ID,
|
||||||
browsers: [{ browserName: 'chrome', version: '38' }, { browserName: 'firefox', version: '34' }],
|
browsers: [{ browserName: 'chrome', version: '38' }, { browserName: 'firefox', version: '34' }],
|
||||||
testname: 'TextSecure-Browser Tests'
|
testname: 'TextSecure-Browser Tests'
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
;(function() {
|
;(function() {
|
||||||
window.textsecure = window.textsecure || {};
|
window.axolotl = window.axolotl || {};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* textsecure.crypto
|
* textsecure.crypto
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
* for all low-level crypto operations,
|
* for all low-level crypto operations,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
window.textsecure.crypto = {
|
window.axolotl.crypto = {
|
||||||
getRandomBytes: function(size) {
|
getRandomBytes: function(size) {
|
||||||
// At some point we might consider XORing in hashes of random
|
// At some point we might consider XORing in hashes of random
|
||||||
// UI events to strengthen ourselves against RNG flaws in crypto.getRandomValues
|
// UI events to strengthen ourselves against RNG flaws in crypto.getRandomValues
|
||||||
|
@ -50,18 +50,18 @@
|
||||||
HKDF: function(input, salt, info) {
|
HKDF: function(input, salt, info) {
|
||||||
// Specific implementation of RFC 5869 that only returns the first 3 32-byte chunks
|
// Specific implementation of RFC 5869 that only returns the first 3 32-byte chunks
|
||||||
// TODO: We dont always need the third chunk, we might skip it
|
// TODO: We dont always need the third chunk, we might skip it
|
||||||
return window.textsecure.crypto.sign(salt, input).then(function(PRK) {
|
return window.axolotl.crypto.sign(salt, input).then(function(PRK) {
|
||||||
var infoBuffer = new ArrayBuffer(info.byteLength + 1 + 32);
|
var infoBuffer = new ArrayBuffer(info.byteLength + 1 + 32);
|
||||||
var infoArray = new Uint8Array(infoBuffer);
|
var infoArray = new Uint8Array(infoBuffer);
|
||||||
infoArray.set(new Uint8Array(info), 32);
|
infoArray.set(new Uint8Array(info), 32);
|
||||||
infoArray[infoArray.length - 1] = 1;
|
infoArray[infoArray.length - 1] = 1;
|
||||||
return window.textsecure.crypto.sign(PRK, infoBuffer.slice(32)).then(function(T1) {
|
return window.axolotl.crypto.sign(PRK, infoBuffer.slice(32)).then(function(T1) {
|
||||||
infoArray.set(new Uint8Array(T1));
|
infoArray.set(new Uint8Array(T1));
|
||||||
infoArray[infoArray.length - 1] = 2;
|
infoArray[infoArray.length - 1] = 2;
|
||||||
return window.textsecure.crypto.sign(PRK, infoBuffer).then(function(T2) {
|
return window.axolotl.crypto.sign(PRK, infoBuffer).then(function(T2) {
|
||||||
infoArray.set(new Uint8Array(T2));
|
infoArray.set(new Uint8Array(T2));
|
||||||
infoArray[infoArray.length - 1] = 3;
|
infoArray[infoArray.length - 1] = 3;
|
||||||
return window.textsecure.crypto.sign(PRK, infoBuffer).then(function(T3) {
|
return window.axolotl.crypto.sign(PRK, infoBuffer).then(function(T3) {
|
||||||
return [ T1, T2, T3 ];
|
return [ T1, T2, T3 ];
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
// Curve 25519 crypto
|
// Curve 25519 crypto
|
||||||
createKeyPair: function(privKey) {
|
createKeyPair: function(privKey) {
|
||||||
if (privKey === undefined) {
|
if (privKey === undefined) {
|
||||||
privKey = textsecure.crypto.getRandomBytes(32);
|
privKey = axolotl.crypto.getRandomBytes(32);
|
||||||
}
|
}
|
||||||
if (privKey.byteLength != 32) {
|
if (privKey.byteLength != 32) {
|
||||||
throw new Error("Invalid private key");
|
throw new Error("Invalid private key");
|
||||||
|
|
|
@ -47,7 +47,7 @@ window.textsecure.protocol = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
crypto_storage.getNewStoredKeyPair = function(keyName) {
|
crypto_storage.getNewStoredKeyPair = function(keyName) {
|
||||||
return textsecure.crypto.createKeyPair().then(function(keyPair) {
|
return axolotl.crypto.createKeyPair().then(function(keyPair) {
|
||||||
crypto_storage.putKeyPair(keyName, keyPair);
|
crypto_storage.putKeyPair(keyName, keyPair);
|
||||||
return keyPair;
|
return keyPair;
|
||||||
});
|
});
|
||||||
|
@ -191,11 +191,11 @@ window.textsecure.protocol = function() {
|
||||||
|
|
||||||
info = toArrayBuffer(info); // TODO: maybe convert calls?
|
info = toArrayBuffer(info); // TODO: maybe convert calls?
|
||||||
|
|
||||||
return textsecure.crypto.HKDF(input, salt, info);
|
return axolotl.crypto.HKDF(input, salt, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
var verifyMAC = function(data, key, mac) {
|
var verifyMAC = function(data, key, mac) {
|
||||||
return textsecure.crypto.sign(key, data).then(function(calculated_mac) {
|
return axolotl.crypto.sign(key, data).then(function(calculated_mac) {
|
||||||
if (!isEqual(calculated_mac, mac, true))
|
if (!isEqual(calculated_mac, mac, true))
|
||||||
throw new Error("Bad MAC");
|
throw new Error("Bad MAC");
|
||||||
});
|
});
|
||||||
|
@ -207,7 +207,7 @@ window.textsecure.protocol = function() {
|
||||||
var calculateRatchet = function(session, remoteKey, sending) {
|
var calculateRatchet = function(session, remoteKey, sending) {
|
||||||
var ratchet = session.currentRatchet;
|
var ratchet = session.currentRatchet;
|
||||||
|
|
||||||
return textsecure.crypto.ECDHE(remoteKey, toArrayBuffer(ratchet.ephemeralKeyPair.privKey)).then(function(sharedSecret) {
|
return axolotl.crypto.ECDHE(remoteKey, toArrayBuffer(ratchet.ephemeralKeyPair.privKey)).then(function(sharedSecret) {
|
||||||
return HKDF(sharedSecret, toArrayBuffer(ratchet.rootKey), "WhisperRatchet").then(function(masterKey) {
|
return HKDF(sharedSecret, toArrayBuffer(ratchet.rootKey), "WhisperRatchet").then(function(masterKey) {
|
||||||
if (sending)
|
if (sending)
|
||||||
session[getString(ratchet.ephemeralKeyPair.pubKey)] = { messageKeys: {}, chainKey: { counter: -1, key: masterKey[1] } };
|
session[getString(ratchet.ephemeralKeyPair.pubKey)] = { messageKeys: {}, chainKey: { counter: -1, key: masterKey[1] } };
|
||||||
|
@ -240,9 +240,9 @@ window.textsecure.protocol = function() {
|
||||||
for (var i = 0; i < 32; i++)
|
for (var i = 0; i < 32; i++)
|
||||||
sharedSecret[i] = 0xff;
|
sharedSecret[i] = 0xff;
|
||||||
|
|
||||||
return textsecure.crypto.ECDHE(theirSignedPubKey, ourIdentityKey.privKey).then(function(ecRes1) {
|
return axolotl.crypto.ECDHE(theirSignedPubKey, ourIdentityKey.privKey).then(function(ecRes1) {
|
||||||
function finishInit() {
|
function finishInit() {
|
||||||
return textsecure.crypto.ECDHE(theirSignedPubKey, ourSignedKey.privKey).then(function(ecRes) {
|
return axolotl.crypto.ECDHE(theirSignedPubKey, ourSignedKey.privKey).then(function(ecRes) {
|
||||||
sharedSecret.set(new Uint8Array(ecRes), 32 * 3);
|
sharedSecret.set(new Uint8Array(ecRes), 32 * 3);
|
||||||
|
|
||||||
return HKDF(sharedSecret.buffer, '', "WhisperText").then(function(masterKey) {
|
return HKDF(sharedSecret.buffer, '', "WhisperText").then(function(masterKey) {
|
||||||
|
@ -258,7 +258,7 @@ window.textsecure.protocol = function() {
|
||||||
// If we're initiating we go ahead and set our first sending ephemeral key now,
|
// If we're initiating we go ahead and set our first sending ephemeral key now,
|
||||||
// otherwise we figure it out when we first maybeStepRatchet with the remote's ephemeral key
|
// otherwise we figure it out when we first maybeStepRatchet with the remote's ephemeral key
|
||||||
if (isInitiator) {
|
if (isInitiator) {
|
||||||
return textsecure.crypto.createKeyPair().then(function(ourSendingEphemeralKey) {
|
return axolotl.crypto.createKeyPair().then(function(ourSendingEphemeralKey) {
|
||||||
session.currentRatchet.ephemeralKeyPair = ourSendingEphemeralKey;
|
session.currentRatchet.ephemeralKeyPair = ourSendingEphemeralKey;
|
||||||
return calculateRatchet(session, theirSignedPubKey, true).then(function() {
|
return calculateRatchet(session, theirSignedPubKey, true).then(function() {
|
||||||
return session;
|
return session;
|
||||||
|
@ -276,17 +276,17 @@ window.textsecure.protocol = function() {
|
||||||
if (ourEphemeralKey === undefined || theirEphemeralPubKey === undefined)
|
if (ourEphemeralKey === undefined || theirEphemeralPubKey === undefined)
|
||||||
promise = Promise.resolve(new ArrayBuffer(0));
|
promise = Promise.resolve(new ArrayBuffer(0));
|
||||||
else
|
else
|
||||||
promise = textsecure.crypto.ECDHE(theirEphemeralPubKey, ourEphemeralKey.privKey);
|
promise = axolotl.crypto.ECDHE(theirEphemeralPubKey, ourEphemeralKey.privKey);
|
||||||
return promise.then(function(ecRes4) {
|
return promise.then(function(ecRes4) {
|
||||||
sharedSecret.set(new Uint8Array(ecRes4), 32 * 4);
|
sharedSecret.set(new Uint8Array(ecRes4), 32 * 4);
|
||||||
|
|
||||||
if (isInitiator)
|
if (isInitiator)
|
||||||
return textsecure.crypto.ECDHE(theirIdentityPubKey, ourSignedKey.privKey).then(function(ecRes2) {
|
return axolotl.crypto.ECDHE(theirIdentityPubKey, ourSignedKey.privKey).then(function(ecRes2) {
|
||||||
sharedSecret.set(new Uint8Array(ecRes1), 32);
|
sharedSecret.set(new Uint8Array(ecRes1), 32);
|
||||||
sharedSecret.set(new Uint8Array(ecRes2), 32 * 2);
|
sharedSecret.set(new Uint8Array(ecRes2), 32 * 2);
|
||||||
}).then(finishInit);
|
}).then(finishInit);
|
||||||
else
|
else
|
||||||
return textsecure.crypto.ECDHE(theirIdentityPubKey, ourSignedKey.privKey).then(function(ecRes2) {
|
return axolotl.crypto.ECDHE(theirIdentityPubKey, ourSignedKey.privKey).then(function(ecRes2) {
|
||||||
sharedSecret.set(new Uint8Array(ecRes1), 32 * 2);
|
sharedSecret.set(new Uint8Array(ecRes1), 32 * 2);
|
||||||
sharedSecret.set(new Uint8Array(ecRes2), 32)
|
sharedSecret.set(new Uint8Array(ecRes2), 32)
|
||||||
}).then(finishInit);
|
}).then(finishInit);
|
||||||
|
@ -430,9 +430,9 @@ window.textsecure.protocol = function() {
|
||||||
var key = toArrayBuffer(chain.chainKey.key);
|
var key = toArrayBuffer(chain.chainKey.key);
|
||||||
var byteArray = new Uint8Array(1);
|
var byteArray = new Uint8Array(1);
|
||||||
byteArray[0] = 1;
|
byteArray[0] = 1;
|
||||||
return textsecure.crypto.sign(key, byteArray.buffer).then(function(mac) {
|
return axolotl.crypto.sign(key, byteArray.buffer).then(function(mac) {
|
||||||
byteArray[0] = 2;
|
byteArray[0] = 2;
|
||||||
return textsecure.crypto.sign(key, byteArray.buffer).then(function(key) {
|
return axolotl.crypto.sign(key, byteArray.buffer).then(function(key) {
|
||||||
chain.messageKeys[chain.chainKey.counter + 1] = mac;
|
chain.messageKeys[chain.chainKey.counter + 1] = mac;
|
||||||
chain.chainKey.key = key
|
chain.chainKey.key = key
|
||||||
chain.chainKey.counter += 1;
|
chain.chainKey.counter += 1;
|
||||||
|
@ -456,7 +456,7 @@ window.textsecure.protocol = function() {
|
||||||
delete session[previousRatchet];
|
delete session[previousRatchet];
|
||||||
}
|
}
|
||||||
|
|
||||||
return textsecure.crypto.createKeyPair().then(function(keyPair) {
|
return axolotl.crypto.createKeyPair().then(function(keyPair) {
|
||||||
ratchet.ephemeralKeyPair = keyPair;
|
ratchet.ephemeralKeyPair = keyPair;
|
||||||
return calculateRatchet(session, remoteKey, true).then(function() {
|
return calculateRatchet(session, remoteKey, true).then(function() {
|
||||||
ratchet.lastRemoteEphemeralKey = remoteKey;
|
ratchet.lastRemoteEphemeralKey = remoteKey;
|
||||||
|
@ -510,7 +510,7 @@ window.textsecure.protocol = function() {
|
||||||
macInput.set(new Uint8Array(messageProtoArray), 33*2 + 1);
|
macInput.set(new Uint8Array(messageProtoArray), 33*2 + 1);
|
||||||
|
|
||||||
return verifyMAC(macInput.buffer, keys[1], mac).then(function() {
|
return verifyMAC(macInput.buffer, keys[1], mac).then(function() {
|
||||||
return window.textsecure.crypto.decrypt(keys[0], toArrayBuffer(message.ciphertext), keys[2].slice(0, 16))
|
return window.axolotl.crypto.decrypt(keys[0], toArrayBuffer(message.ciphertext), keys[2].slice(0, 16))
|
||||||
.then(function(paddedPlaintext) {
|
.then(function(paddedPlaintext) {
|
||||||
|
|
||||||
paddedPlaintext = new Uint8Array(paddedPlaintext);
|
paddedPlaintext = new Uint8Array(paddedPlaintext);
|
||||||
|
@ -563,7 +563,7 @@ window.textsecure.protocol = function() {
|
||||||
var mac = decodedMessage.slice(decodedMessage.byteLength - 10, decodedMessage.byteLength);
|
var mac = decodedMessage.slice(decodedMessage.byteLength - 10, decodedMessage.byteLength);
|
||||||
|
|
||||||
return verifyMAC(ivAndCiphertext, mac_key, mac).then(function() {
|
return verifyMAC(ivAndCiphertext, mac_key, mac).then(function() {
|
||||||
return window.textsecure.crypto.decrypt(aes_key, ciphertext, iv);
|
return window.axolotl.crypto.decrypt(aes_key, ciphertext, iv);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -577,7 +577,7 @@ window.textsecure.protocol = function() {
|
||||||
var mac = encryptedBin.slice(encryptedBin.byteLength - 32, encryptedBin.byteLength);
|
var mac = encryptedBin.slice(encryptedBin.byteLength - 32, encryptedBin.byteLength);
|
||||||
|
|
||||||
return verifyMAC(ivAndCiphertext, mac_key, mac).then(function() {
|
return verifyMAC(ivAndCiphertext, mac_key, mac).then(function() {
|
||||||
return window.textsecure.crypto.decrypt(aes_key, ciphertext, iv);
|
return window.axolotl.crypto.decrypt(aes_key, ciphertext, iv);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -585,12 +585,12 @@ window.textsecure.protocol = function() {
|
||||||
var aes_key = keys.slice(0, 32);
|
var aes_key = keys.slice(0, 32);
|
||||||
var mac_key = keys.slice(32, 64);
|
var mac_key = keys.slice(32, 64);
|
||||||
|
|
||||||
return window.textsecure.crypto.encrypt(aes_key, plaintext, iv).then(function(ciphertext) {
|
return window.axolotl.crypto.encrypt(aes_key, plaintext, iv).then(function(ciphertext) {
|
||||||
var ivAndCiphertext = new Uint8Array(16 + ciphertext.byteLength);
|
var ivAndCiphertext = new Uint8Array(16 + ciphertext.byteLength);
|
||||||
ivAndCiphertext.set(new Uint8Array(iv));
|
ivAndCiphertext.set(new Uint8Array(iv));
|
||||||
ivAndCiphertext.set(new Uint8Array(ciphertext), 16);
|
ivAndCiphertext.set(new Uint8Array(ciphertext), 16);
|
||||||
|
|
||||||
return textsecure.crypto.sign(mac_key, ivAndCiphertext.buffer).then(function(mac) {
|
return axolotl.crypto.sign(mac_key, ivAndCiphertext.buffer).then(function(mac) {
|
||||||
var encryptedBin = new Uint8Array(16 + ciphertext.byteLength + 32);
|
var encryptedBin = new Uint8Array(16 + ciphertext.byteLength + 32);
|
||||||
encryptedBin.set(ivAndCiphertext);
|
encryptedBin.set(ivAndCiphertext);
|
||||||
encryptedBin.set(new Uint8Array(mac), 16 + ciphertext.byteLength);
|
encryptedBin.set(new Uint8Array(mac), 16 + ciphertext.byteLength);
|
||||||
|
@ -639,7 +639,7 @@ window.textsecure.protocol = function() {
|
||||||
msg.counter = chain.chainKey.counter;
|
msg.counter = chain.chainKey.counter;
|
||||||
msg.previousCounter = session.currentRatchet.previousCounter;
|
msg.previousCounter = session.currentRatchet.previousCounter;
|
||||||
|
|
||||||
return window.textsecure.crypto.encrypt(keys[0], paddedPlaintext.buffer, keys[2].slice(0, 16)).then(function(ciphertext) {
|
return window.axolotl.crypto.encrypt(keys[0], paddedPlaintext.buffer, keys[2].slice(0, 16)).then(function(ciphertext) {
|
||||||
msg.ciphertext = ciphertext;
|
msg.ciphertext = ciphertext;
|
||||||
var encodedMsg = toArrayBuffer(msg.encode());
|
var encodedMsg = toArrayBuffer(msg.encode());
|
||||||
|
|
||||||
|
@ -649,7 +649,7 @@ window.textsecure.protocol = function() {
|
||||||
macInput[33*2] = (3 << 4) | 3;
|
macInput[33*2] = (3 << 4) | 3;
|
||||||
macInput.set(new Uint8Array(encodedMsg), 33*2 + 1);
|
macInput.set(new Uint8Array(encodedMsg), 33*2 + 1);
|
||||||
|
|
||||||
return textsecure.crypto.sign(keys[1], macInput.buffer).then(function(mac) {
|
return axolotl.crypto.sign(keys[1], macInput.buffer).then(function(mac) {
|
||||||
var result = new Uint8Array(encodedMsg.byteLength + 9);
|
var result = new Uint8Array(encodedMsg.byteLength + 9);
|
||||||
result[0] = (3 << 4) | 3;
|
result[0] = (3 << 4) | 3;
|
||||||
result.set(new Uint8Array(encodedMsg), 1);
|
result.set(new Uint8Array(encodedMsg), 1);
|
||||||
|
@ -677,7 +677,7 @@ window.textsecure.protocol = function() {
|
||||||
preKeyMsg.registrationId = textsecure.storage.getUnencrypted("registrationId");
|
preKeyMsg.registrationId = textsecure.storage.getUnencrypted("registrationId");
|
||||||
|
|
||||||
if (session === undefined) {
|
if (session === undefined) {
|
||||||
return textsecure.crypto.createKeyPair().then(function(baseKey) {
|
return axolotl.crypto.createKeyPair().then(function(baseKey) {
|
||||||
preKeyMsg.preKeyId = deviceObject.preKeyId;
|
preKeyMsg.preKeyId = deviceObject.preKeyId;
|
||||||
preKeyMsg.signedPreKeyId = deviceObject.signedKeyId;
|
preKeyMsg.signedPreKeyId = deviceObject.signedKeyId;
|
||||||
preKeyMsg.baseKey = toArrayBuffer(baseKey.pubKey);
|
preKeyMsg.baseKey = toArrayBuffer(baseKey.pubKey);
|
||||||
|
@ -733,7 +733,7 @@ window.textsecure.protocol = function() {
|
||||||
promises[i] = generateKey(i);
|
promises[i] = generateKey(i);
|
||||||
|
|
||||||
promises[firstPreKeyId + GENERATE_KEYS_KEYS_GENERATED] = crypto_storage.getNewStoredKeyPair("signedKey" + signedKeyId).then(function(keyPair) {
|
promises[firstPreKeyId + GENERATE_KEYS_KEYS_GENERATED] = crypto_storage.getNewStoredKeyPair("signedKey" + signedKeyId).then(function(keyPair) {
|
||||||
return textsecure.crypto.Ed25519Sign(identityKeyPair.privKey, keyPair.pubKey).then(function(sig) {
|
return axolotl.crypto.Ed25519Sign(identityKeyPair.privKey, keyPair.pubKey).then(function(sig) {
|
||||||
keys.signedPreKey = {keyId: signedKeyId, publicKey: keyPair.pubKey, signature: sig};
|
keys.signedPreKey = {keyId: signedKeyId, publicKey: keyPair.pubKey, signature: sig};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -766,7 +766,7 @@ window.textsecure.protocol = function() {
|
||||||
var masterEphemeral = toArrayBuffer(deviceInit.publicKey);
|
var masterEphemeral = toArrayBuffer(deviceInit.publicKey);
|
||||||
var message = toArrayBuffer(deviceInit.body);
|
var message = toArrayBuffer(deviceInit.body);
|
||||||
|
|
||||||
return textsecure.crypto.ECDHE(masterEphemeral, keyPair.privKey).then(function(ecRes) {
|
return axolotl.crypto.ECDHE(masterEphemeral, keyPair.privKey).then(function(ecRes) {
|
||||||
return HKDF(ecRes, '', "TextSecure Provisioning Message").then(function(keys) {
|
return HKDF(ecRes, '', "TextSecure Provisioning Message").then(function(keys) {
|
||||||
if (new Uint8Array(message)[0] != 1)
|
if (new Uint8Array(message)[0] != 1)
|
||||||
throw new Error("Bad version number on ProvisioningMessage");
|
throw new Error("Bad version number on ProvisioningMessage");
|
||||||
|
@ -777,10 +777,10 @@ window.textsecure.protocol = function() {
|
||||||
var ciphertext = message.slice(16 + 1, message.byteLength - 32);
|
var ciphertext = message.slice(16 + 1, message.byteLength - 32);
|
||||||
|
|
||||||
return verifyMAC(ivAndCiphertext, keys[1], mac).then(function() {
|
return verifyMAC(ivAndCiphertext, keys[1], mac).then(function() {
|
||||||
return window.textsecure.crypto.decrypt(keys[0], ciphertext, iv).then(function(plaintext) {
|
return window.axolotl.crypto.decrypt(keys[0], ciphertext, iv).then(function(plaintext) {
|
||||||
var identityKeyMsg = textsecure.protobuf.ProvisionMessage.decode(plaintext);
|
var identityKeyMsg = textsecure.protobuf.ProvisionMessage.decode(plaintext);
|
||||||
|
|
||||||
return textsecure.crypto.createKeyPair(toArrayBuffer(identityKeyMsg.identityKeyPrivate)).then(function(identityKeyPair) {
|
return axolotl.crypto.createKeyPair(toArrayBuffer(identityKeyMsg.identityKeyPrivate)).then(function(identityKeyPair) {
|
||||||
crypto_storage.putKeyPair("identityKey", identityKeyPair);
|
crypto_storage.putKeyPair("identityKey", identityKeyPair);
|
||||||
identityKeyMsg.identityKeyPrivate = null;
|
identityKeyMsg.identityKeyPrivate = null;
|
||||||
|
|
||||||
|
@ -792,7 +792,7 @@ window.textsecure.protocol = function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return textsecure.crypto.createKeyPair().then(function(newKeyPair) {
|
return axolotl.crypto.createKeyPair().then(function(newKeyPair) {
|
||||||
keyPair = newKeyPair;
|
keyPair = newKeyPair;
|
||||||
socketInfo.pubKey = keyPair.pubKey;
|
socketInfo.pubKey = keyPair.pubKey;
|
||||||
return socketInfo;
|
return socketInfo;
|
||||||
|
|
69
libaxolotl/test/_test.js
Normal file
69
libaxolotl/test/_test.js
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mocha.setup("bdd");
|
||||||
|
window.assert = chai.assert;
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var OriginalReporter = mocha._reporter;
|
||||||
|
|
||||||
|
var SauceReporter = function(runner) {
|
||||||
|
var failedTests = [];
|
||||||
|
|
||||||
|
runner.on('end', function() {
|
||||||
|
window.mochaResults = runner.stats;
|
||||||
|
window.mochaResults.reports = failedTests;
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.on('fail', function(test, err) {
|
||||||
|
var flattenTitles = function(test) {
|
||||||
|
var titles = [];
|
||||||
|
while (test.parent.title) {
|
||||||
|
titles.push(test.parent.title);
|
||||||
|
test = test.parent;
|
||||||
|
}
|
||||||
|
return titles.reverse();
|
||||||
|
};
|
||||||
|
failedTests.push({
|
||||||
|
name: test.title,
|
||||||
|
result: false,
|
||||||
|
message: err.message,
|
||||||
|
stack: err.stack,
|
||||||
|
titles: flattenTitles(test)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
new OriginalReporter(runner);
|
||||||
|
};
|
||||||
|
|
||||||
|
SauceReporter.prototype = OriginalReporter.prototype;
|
||||||
|
|
||||||
|
mocha.reporter(SauceReporter);
|
||||||
|
}());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* global helpers for tests
|
||||||
|
*/
|
||||||
|
function assertEqualArrayBuffers(ab1, ab2) {
|
||||||
|
assert.deepEqual(new Uint8Array(ab1), new Uint8Array(ab2));
|
||||||
|
};
|
||||||
|
|
||||||
|
function hexToArrayBuffer(str) {
|
||||||
|
var ret = new ArrayBuffer(str.length / 2);
|
||||||
|
var array = new Uint8Array(ret);
|
||||||
|
for (var i = 0; i < str.length/2; i++)
|
||||||
|
array[i] = parseInt(str.substr(i*2, 2), 16);
|
||||||
|
return ret;
|
||||||
|
};
|
5309
libaxolotl/test/blanket_mocha.js
Normal file
5309
libaxolotl/test/blanket_mocha.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -24,7 +24,7 @@ describe("Crypto", function() {
|
||||||
var iv = hexToArrayBuffer('000102030405060708090a0b0c0d0e0f');
|
var iv = hexToArrayBuffer('000102030405060708090a0b0c0d0e0f');
|
||||||
var plaintext = hexToArrayBuffer('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710');
|
var plaintext = hexToArrayBuffer('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710');
|
||||||
var ciphertext = hexToArrayBuffer('f58c4c04d6e5f1ba779eabfb5f7bfbd69cfc4e967edb808d679f777bc6702c7d39f23369a9d9bacfa530e26304231461b2eb05e2c39be9fcda6c19078c6a9d1b3f461796d6b0d6b2e0c2a72b4d80e644');
|
var ciphertext = hexToArrayBuffer('f58c4c04d6e5f1ba779eabfb5f7bfbd69cfc4e967edb808d679f777bc6702c7d39f23369a9d9bacfa530e26304231461b2eb05e2c39be9fcda6c19078c6a9d1b3f461796d6b0d6b2e0c2a72b4d80e644');
|
||||||
window.textsecure.crypto.encrypt(key, plaintext, iv).then(function(result) {
|
window.axolotl.crypto.encrypt(key, plaintext, iv).then(function(result) {
|
||||||
assertEqualArrayBuffers(result, ciphertext);
|
assertEqualArrayBuffers(result, ciphertext);
|
||||||
}).then(done).catch(done);
|
}).then(done).catch(done);
|
||||||
});
|
});
|
||||||
|
@ -36,7 +36,7 @@ describe("Crypto", function() {
|
||||||
var iv = hexToArrayBuffer('000102030405060708090a0b0c0d0e0f');
|
var iv = hexToArrayBuffer('000102030405060708090a0b0c0d0e0f');
|
||||||
var plaintext = hexToArrayBuffer('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710');
|
var plaintext = hexToArrayBuffer('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710');
|
||||||
var ciphertext = hexToArrayBuffer('f58c4c04d6e5f1ba779eabfb5f7bfbd69cfc4e967edb808d679f777bc6702c7d39f23369a9d9bacfa530e26304231461b2eb05e2c39be9fcda6c19078c6a9d1b3f461796d6b0d6b2e0c2a72b4d80e644');
|
var ciphertext = hexToArrayBuffer('f58c4c04d6e5f1ba779eabfb5f7bfbd69cfc4e967edb808d679f777bc6702c7d39f23369a9d9bacfa530e26304231461b2eb05e2c39be9fcda6c19078c6a9d1b3f461796d6b0d6b2e0c2a72b4d80e644');
|
||||||
window.textsecure.crypto.decrypt(key, ciphertext, iv).then(function(result) {
|
window.axolotl.crypto.decrypt(key, ciphertext, iv).then(function(result) {
|
||||||
assertEqualArrayBuffers(result, plaintext);
|
assertEqualArrayBuffers(result, plaintext);
|
||||||
}).then(done).catch(done);
|
}).then(done).catch(done);
|
||||||
});
|
});
|
||||||
|
@ -47,7 +47,7 @@ describe("Crypto", function() {
|
||||||
var key = hexToArrayBuffer('6f35628d65813435534b5d67fbdb54cb33403d04e843103e6399f806cb5df95febbdd61236f33245');
|
var key = hexToArrayBuffer('6f35628d65813435534b5d67fbdb54cb33403d04e843103e6399f806cb5df95febbdd61236f33245');
|
||||||
var input = hexToArrayBuffer('752cff52e4b90768558e5369e75d97c69643509a5e5904e0a386cbe4d0970ef73f918f675945a9aefe26daea27587e8dc909dd56fd0468805f834039b345f855cfe19c44b55af241fff3ffcd8045cd5c288e6c4e284c3720570b58e4d47b8feeedc52fd1401f698a209fccfa3b4c0d9a797b046a2759f82a54c41ccd7b5f592b');
|
var input = hexToArrayBuffer('752cff52e4b90768558e5369e75d97c69643509a5e5904e0a386cbe4d0970ef73f918f675945a9aefe26daea27587e8dc909dd56fd0468805f834039b345f855cfe19c44b55af241fff3ffcd8045cd5c288e6c4e284c3720570b58e4d47b8feeedc52fd1401f698a209fccfa3b4c0d9a797b046a2759f82a54c41ccd7b5f592b');
|
||||||
var mac = hexToArrayBuffer('05d1243e6465ed9620c9aec1c351a186');
|
var mac = hexToArrayBuffer('05d1243e6465ed9620c9aec1c351a186');
|
||||||
window.textsecure.crypto.sign(key, input).then(function(result) {
|
window.axolotl.crypto.sign(key, input).then(function(result) {
|
||||||
assertEqualArrayBuffers(result.slice(0, mac.byteLength), mac);
|
assertEqualArrayBuffers(result.slice(0, mac.byteLength), mac);
|
||||||
}).then(done).catch(done);
|
}).then(done).catch(done);
|
||||||
});
|
});
|
||||||
|
@ -71,7 +71,7 @@ describe("Crypto", function() {
|
||||||
for (var i = 0; i < 10; i++)
|
for (var i = 0; i < 10; i++)
|
||||||
info[i] = 240 + i;
|
info[i] = 240 + i;
|
||||||
|
|
||||||
return textsecure.crypto.HKDF(IKM.buffer, salt.buffer, info.buffer).then(function(OKM){
|
return axolotl.crypto.HKDF(IKM.buffer, salt.buffer, info.buffer).then(function(OKM){
|
||||||
assertEqualArrayBuffers(OKM[0], T1);
|
assertEqualArrayBuffers(OKM[0], T1);
|
||||||
assertEqualArrayBuffers(OKM[1].slice(0, 10), T2);
|
assertEqualArrayBuffers(OKM[1].slice(0, 10), T2);
|
||||||
}).then(done).catch(done);
|
}).then(done).catch(done);
|
||||||
|
@ -88,21 +88,21 @@ describe("Crypto", function() {
|
||||||
|
|
||||||
describe("createKeyPair", function() {
|
describe("createKeyPair", function() {
|
||||||
it ('converts alice private keys to a keypair', function(done) {
|
it ('converts alice private keys to a keypair', function(done) {
|
||||||
textsecure.crypto.createKeyPair(alice_bytes).then(function(keypair) {
|
axolotl.crypto.createKeyPair(alice_bytes).then(function(keypair) {
|
||||||
assertEqualArrayBuffers(keypair.privKey, alice_priv);
|
assertEqualArrayBuffers(keypair.privKey, alice_priv);
|
||||||
assertEqualArrayBuffers(keypair.pubKey, alice_pub);
|
assertEqualArrayBuffers(keypair.pubKey, alice_pub);
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
it ('converts bob private keys to a keypair', function(done) {
|
it ('converts bob private keys to a keypair', function(done) {
|
||||||
textsecure.crypto.createKeyPair(bob_bytes).then(function(keypair) {
|
axolotl.crypto.createKeyPair(bob_bytes).then(function(keypair) {
|
||||||
assertEqualArrayBuffers(keypair.privKey, bob_priv);
|
assertEqualArrayBuffers(keypair.privKey, bob_priv);
|
||||||
assertEqualArrayBuffers(keypair.pubKey, bob_pub);
|
assertEqualArrayBuffers(keypair.pubKey, bob_pub);
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
it ('generates a key if one is not provided', function(done) {
|
it ('generates a key if one is not provided', function(done) {
|
||||||
textsecure.crypto.createKeyPair().then(function(keypair) {
|
axolotl.crypto.createKeyPair().then(function(keypair) {
|
||||||
assert.strictEqual(keypair.privKey.byteLength, 32);
|
assert.strictEqual(keypair.privKey.byteLength, 32);
|
||||||
assert.strictEqual(keypair.pubKey.byteLength, 33);
|
assert.strictEqual(keypair.pubKey.byteLength, 33);
|
||||||
assert.strictEqual(new Uint8Array(keypair.pubKey)[0], 5);
|
assert.strictEqual(new Uint8Array(keypair.pubKey)[0], 5);
|
||||||
|
@ -113,13 +113,13 @@ describe("Crypto", function() {
|
||||||
|
|
||||||
describe("ECDHE", function() {
|
describe("ECDHE", function() {
|
||||||
it("computes the shared secret for alice", function(done) {
|
it("computes the shared secret for alice", function(done) {
|
||||||
textsecure.crypto.ECDHE(bob_pub, alice_priv).then(function(secret) {
|
axolotl.crypto.ECDHE(bob_pub, alice_priv).then(function(secret) {
|
||||||
assertEqualArrayBuffers(shared_sec, secret);
|
assertEqualArrayBuffers(shared_sec, secret);
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
it("computes the shared secret for bob", function(done) {
|
it("computes the shared secret for bob", function(done) {
|
||||||
textsecure.crypto.ECDHE(alice_pub, bob_priv).then(function(secret) {
|
axolotl.crypto.ECDHE(alice_pub, bob_priv).then(function(secret) {
|
||||||
assertEqualArrayBuffers(shared_sec, secret);
|
assertEqualArrayBuffers(shared_sec, secret);
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
|
@ -133,7 +133,7 @@ describe("Crypto", function() {
|
||||||
describe("Ed25519Sign", function() {
|
describe("Ed25519Sign", function() {
|
||||||
// Some self-generated test vectors
|
// Some self-generated test vectors
|
||||||
it('works', function(done) {
|
it('works', function(done) {
|
||||||
return textsecure.crypto.Ed25519Sign(priv, msg).then(function(sigCalc) {
|
return axolotl.crypto.Ed25519Sign(priv, msg).then(function(sigCalc) {
|
||||||
assertEqualArrayBuffers(sig, sigCalc);
|
assertEqualArrayBuffers(sig, sigCalc);
|
||||||
}).then(done).catch(done);
|
}).then(done).catch(done);
|
||||||
});
|
});
|
||||||
|
@ -144,7 +144,7 @@ describe("Crypto", function() {
|
||||||
var badsig = sig.slice(0);
|
var badsig = sig.slice(0);
|
||||||
new Uint8Array(badsig).set([0], 0);
|
new Uint8Array(badsig).set([0], 0);
|
||||||
|
|
||||||
textsecure.crypto.Ed25519Verify(pub, msg, badsig).catch(function(e) {
|
axolotl.crypto.Ed25519Verify(pub, msg, badsig).catch(function(e) {
|
||||||
if (e.message === 'Invalid signature') {
|
if (e.message === 'Invalid signature') {
|
||||||
done();
|
done();
|
||||||
} else { throw e; }
|
} else { throw e; }
|
||||||
|
@ -152,7 +152,7 @@ describe("Crypto", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not throw on good signature", function(done) {
|
it("does not throw on good signature", function(done) {
|
||||||
return textsecure.crypto.Ed25519Verify(pub, msg, sig).then(done).catch(done);
|
return axolotl.crypto.Ed25519Verify(pub, msg, sig).then(done).catch(done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
40
libaxolotl/test/index.html
Normal file
40
libaxolotl/test/index.html
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<!--This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>libTextSecure test runner</title>
|
||||||
|
<link rel="stylesheet" href="../../components/mocha/mocha.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Run this out of the chrome-plugin:// namespace (and expect plugin state to be cleared/corrupted), not file://</h2>
|
||||||
|
|
||||||
|
<div id="mocha">
|
||||||
|
</div>
|
||||||
|
<div id="tests">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="test.js"></script>
|
||||||
|
<script type="text/javascript" src="blanket_mocha.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="../components.js"></script>
|
||||||
|
<script type="text/javascript" src="../curve25519_concat.js"></script>
|
||||||
|
<script type="text/javascript" src="../webcrypto_concat.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="../crypto.js" data-cover></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="crypto_test.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
10943
libaxolotl/test/test.js
Normal file
10943
libaxolotl/test/test.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -196,7 +196,7 @@ window.textsecure.api = function () {
|
||||||
for (var i = 0; i < res.devices.length; i++) {
|
for (var i = 0; i < res.devices.length; i++) {
|
||||||
res.devices[i].signedPreKey.publicKey = StringView.base64ToBytes(res.devices[i].signedPreKey.publicKey);
|
res.devices[i].signedPreKey.publicKey = StringView.base64ToBytes(res.devices[i].signedPreKey.publicKey);
|
||||||
res.devices[i].signedPreKey.signature = StringView.base64ToBytes(res.devices[i].signedPreKey.signature);
|
res.devices[i].signedPreKey.signature = StringView.base64ToBytes(res.devices[i].signedPreKey.signature);
|
||||||
promises[i] = window.textsecure.crypto.Ed25519Verify(res.identityKey, res.devices[i].signedPreKey.publicKey, res.devices[i].signedPreKey.signature);
|
promises[i] = window.axolotl.crypto.Ed25519Verify(res.identityKey, res.devices[i].signedPreKey.publicKey, res.devices[i].signedPreKey.signature);
|
||||||
res.devices[i].preKey.publicKey = StringView.base64ToBytes(res.devices[i].preKey.publicKey);
|
res.devices[i].preKey.publicKey = StringView.base64ToBytes(res.devices[i].preKey.publicKey);
|
||||||
//TODO: Is this still needed?
|
//TODO: Is this still needed?
|
||||||
//if (res.devices[i].keyId === undefined)
|
//if (res.devices[i].keyId === undefined)
|
||||||
|
|
|
@ -242,14 +242,14 @@ textsecure.processDecrypted = function(decrypted, source) {
|
||||||
}
|
}
|
||||||
|
|
||||||
window.textsecure.registerSingleDevice = function(number, verificationCode, stepDone) {
|
window.textsecure.registerSingleDevice = function(number, verificationCode, stepDone) {
|
||||||
var signalingKey = textsecure.crypto.getRandomBytes(32 + 20);
|
var signalingKey = axolotl.crypto.getRandomBytes(32 + 20);
|
||||||
textsecure.storage.putEncrypted('signaling_key', signalingKey);
|
textsecure.storage.putEncrypted('signaling_key', signalingKey);
|
||||||
|
|
||||||
var password = btoa(getString(textsecure.crypto.getRandomBytes(16)));
|
var password = btoa(getString(axolotl.crypto.getRandomBytes(16)));
|
||||||
password = password.substring(0, password.length - 2);
|
password = password.substring(0, password.length - 2);
|
||||||
textsecure.storage.putEncrypted("password", password);
|
textsecure.storage.putEncrypted("password", password);
|
||||||
|
|
||||||
var registrationId = new Uint16Array(textsecure.crypto.getRandomBytes(2))[0];
|
var registrationId = new Uint16Array(axolotl.crypto.getRandomBytes(2))[0];
|
||||||
registrationId = registrationId & 0x3fff;
|
registrationId = registrationId & 0x3fff;
|
||||||
textsecure.storage.putUnencrypted("registrationId", registrationId);
|
textsecure.storage.putUnencrypted("registrationId", registrationId);
|
||||||
|
|
||||||
|
@ -273,14 +273,14 @@ window.textsecure.registerSecondDevice = function(encodedProvisionEnvelope, cryp
|
||||||
return cryptoInfo.decryptAndHandleDeviceInit(envelope).then(function(identityKey) {
|
return cryptoInfo.decryptAndHandleDeviceInit(envelope).then(function(identityKey) {
|
||||||
stepDone(1);
|
stepDone(1);
|
||||||
|
|
||||||
var signalingKey = textsecure.crypto.getRandomBytes(32 + 20);
|
var signalingKey = axolotl.crypto.getRandomBytes(32 + 20);
|
||||||
textsecure.storage.putEncrypted('signaling_key', signalingKey);
|
textsecure.storage.putEncrypted('signaling_key', signalingKey);
|
||||||
|
|
||||||
var password = btoa(getString(textsecure.crypto.getRandomBytes(16)));
|
var password = btoa(getString(axolotl.crypto.getRandomBytes(16)));
|
||||||
password = password.substring(0, password.length - 2);
|
password = password.substring(0, password.length - 2);
|
||||||
textsecure.storage.putEncrypted("password", password);
|
textsecure.storage.putEncrypted("password", password);
|
||||||
|
|
||||||
var registrationId = new Uint16Array(textsecure.crypto.getRandomBytes(2))[0];
|
var registrationId = new Uint16Array(axolotl.crypto.getRandomBytes(2))[0];
|
||||||
registrationId = registrationId & 0x3fff;
|
registrationId = registrationId & 0x3fff;
|
||||||
textsecure.storage.putUnencrypted("registrationId", registrationId);
|
textsecure.storage.putUnencrypted("registrationId", registrationId);
|
||||||
|
|
||||||
|
|
|
@ -231,9 +231,9 @@ window.textsecure.messaging = function() {
|
||||||
|
|
||||||
makeAttachmentPointer = function(attachment) {
|
makeAttachmentPointer = function(attachment) {
|
||||||
var proto = new textsecure.protobuf.PushMessageContent.AttachmentPointer();
|
var proto = new textsecure.protobuf.PushMessageContent.AttachmentPointer();
|
||||||
proto.key = textsecure.crypto.getRandomBytes(64);
|
proto.key = axolotl.crypto.getRandomBytes(64);
|
||||||
|
|
||||||
var iv = textsecure.crypto.getRandomBytes(16);
|
var iv = axolotl.crypto.getRandomBytes(16);
|
||||||
return textsecure.protocol.encryptAttachment(attachment.data, proto.key, iv).then(function(encryptedBin) {
|
return textsecure.protocol.encryptAttachment(attachment.data, proto.key, iv).then(function(encryptedBin) {
|
||||||
return textsecure.api.putAttachment(encryptedBin).then(function(id) {
|
return textsecure.api.putAttachment(encryptedBin).then(function(id) {
|
||||||
proto.id = id;
|
proto.id = id;
|
||||||
|
|
|
@ -47,7 +47,6 @@
|
||||||
|
|
||||||
<script type="text/javascript" src="fake_api.js"></script>
|
<script type="text/javascript" src="fake_api.js"></script>
|
||||||
<script type="text/javascript" src="testvectors.js"></script>
|
<script type="text/javascript" src="testvectors.js"></script>
|
||||||
<script type="text/javascript" src="crypto_test.js"></script>
|
|
||||||
<script type="text/javascript" src="helpers_test.js"></script>
|
<script type="text/javascript" src="helpers_test.js"></script>
|
||||||
<script type="text/javascript" src="websocket-resources_test.js"></script>
|
<script type="text/javascript" src="websocket-resources_test.js"></script>
|
||||||
<script type="text/javascript" src="protocol_test.js"></script>
|
<script type="text/javascript" src="protocol_test.js"></script>
|
||||||
|
|
|
@ -84,30 +84,30 @@ describe('Protocol', function() {
|
||||||
|
|
||||||
describe("Axolotl", function() {
|
describe("Axolotl", function() {
|
||||||
var runAxolotlTest = function(v) {
|
var runAxolotlTest = function(v) {
|
||||||
var origCreateKeyPair = textsecure.crypto.createKeyPair;
|
var origCreateKeyPair = axolotl.crypto.createKeyPair;
|
||||||
var doStep;
|
var doStep;
|
||||||
var stepDone;
|
var stepDone;
|
||||||
|
|
||||||
stepDone = function(res) {
|
stepDone = function(res) {
|
||||||
if (!res || privKeyQueue.length != 0 || Object.keys(getKeysForNumberMap).length != 0 || Object.keys(messagesSentMap).length != 0) {
|
if (!res || privKeyQueue.length != 0 || Object.keys(getKeysForNumberMap).length != 0 || Object.keys(messagesSentMap).length != 0) {
|
||||||
textsecure.crypto.createKeyPair = origCreateKeyPair;
|
axolotl.crypto.createKeyPair = origCreateKeyPair;
|
||||||
return false;
|
return false;
|
||||||
} else if (step == v.length) {
|
} else if (step == v.length) {
|
||||||
textsecure.crypto.createKeyPair = origCreateKeyPair;
|
axolotl.crypto.createKeyPair = origCreateKeyPair;
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
return doStep().then(stepDone);
|
return doStep().then(stepDone);
|
||||||
}
|
}
|
||||||
|
|
||||||
var privKeyQueue = [];
|
var privKeyQueue = [];
|
||||||
textsecure.crypto.createKeyPair = function(privKey) {
|
axolotl.crypto.createKeyPair = function(privKey) {
|
||||||
if (privKey !== undefined)
|
if (privKey !== undefined)
|
||||||
return origCreateKeyPair(privKey);
|
return origCreateKeyPair(privKey);
|
||||||
if (privKeyQueue.length == 0)
|
if (privKeyQueue.length == 0)
|
||||||
throw new Error('Out of private keys');
|
throw new Error('Out of private keys');
|
||||||
else {
|
else {
|
||||||
var privKey = privKeyQueue.shift();
|
var privKey = privKeyQueue.shift();
|
||||||
return textsecure.crypto.createKeyPair(privKey).then(function(keyPair) {
|
return axolotl.crypto.createKeyPair(privKey).then(function(keyPair) {
|
||||||
var a = btoa(getString(keyPair.privKey)); var b = btoa(getString(privKey));
|
var a = btoa(getString(keyPair.privKey)); var b = btoa(getString(privKey));
|
||||||
if (getString(keyPair.privKey) != getString(privKey))
|
if (getString(keyPair.privKey) != getString(privKey))
|
||||||
throw new Error('Failed to rederive private key!');
|
throw new Error('Failed to rederive private key!');
|
||||||
|
@ -151,13 +151,13 @@ describe('Protocol', function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.ourIdentityKey !== undefined)
|
if (data.ourIdentityKey !== undefined)
|
||||||
return textsecure.crypto.createKeyPair(data.ourIdentityKey).then(function(keyPair) {
|
return axolotl.crypto.createKeyPair(data.ourIdentityKey).then(function(keyPair) {
|
||||||
textsecure.storage.putEncrypted("25519KeyidentityKey", keyPair);
|
textsecure.storage.putEncrypted("25519KeyidentityKey", keyPair);
|
||||||
return textsecure.crypto.createKeyPair(data.ourSignedPreKey).then(function(keyPair) {
|
return axolotl.crypto.createKeyPair(data.ourSignedPreKey).then(function(keyPair) {
|
||||||
textsecure.storage.putEncrypted("25519KeysignedKey" + data.signedPreKeyId, keyPair);
|
textsecure.storage.putEncrypted("25519KeysignedKey" + data.signedPreKeyId, keyPair);
|
||||||
|
|
||||||
if (data.ourPreKey !== undefined)
|
if (data.ourPreKey !== undefined)
|
||||||
return textsecure.crypto.createKeyPair(data.ourPreKey).then(function(keyPair) {
|
return axolotl.crypto.createKeyPair(data.ourPreKey).then(function(keyPair) {
|
||||||
textsecure.storage.putEncrypted("25519KeypreKey" + data.preKeyId, keyPair);
|
textsecure.storage.putEncrypted("25519KeypreKey" + data.preKeyId, keyPair);
|
||||||
return postLocalKeySetup();
|
return postLocalKeySetup();
|
||||||
});
|
});
|
||||||
|
@ -204,7 +204,7 @@ describe('Protocol', function() {
|
||||||
privKeyQueue.push(data.ourEphemeralKey);
|
privKeyQueue.push(data.ourEphemeralKey);
|
||||||
|
|
||||||
if (data.ourIdentityKey !== undefined)
|
if (data.ourIdentityKey !== undefined)
|
||||||
return textsecure.crypto.createKeyPair(data.ourIdentityKey).then(function(keyPair) {
|
return axolotl.crypto.createKeyPair(data.ourIdentityKey).then(function(keyPair) {
|
||||||
textsecure.storage.putEncrypted("25519KeyidentityKey", keyPair);
|
textsecure.storage.putEncrypted("25519KeyidentityKey", keyPair);
|
||||||
return postLocalKeySetup();
|
return postLocalKeySetup();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue