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'
|
||||
],
|
||||
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: {
|
||||
|
@ -167,7 +175,7 @@ module.exports = function(grunt) {
|
|||
'saucelabs-mocha': {
|
||||
all: {
|
||||
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,
|
||||
browsers: [{ browserName: 'chrome', version: '38' }, { browserName: 'firefox', version: '34' }],
|
||||
testname: 'TextSecure-Browser Tests'
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
;(function() {
|
||||
window.textsecure = window.textsecure || {};
|
||||
window.axolotl = window.axolotl || {};
|
||||
|
||||
/*
|
||||
* textsecure.crypto
|
||||
|
@ -22,7 +22,7 @@
|
|||
* for all low-level crypto operations,
|
||||
*/
|
||||
|
||||
window.textsecure.crypto = {
|
||||
window.axolotl.crypto = {
|
||||
getRandomBytes: function(size) {
|
||||
// At some point we might consider XORing in hashes of random
|
||||
// UI events to strengthen ourselves against RNG flaws in crypto.getRandomValues
|
||||
|
@ -50,18 +50,18 @@
|
|||
HKDF: function(input, salt, info) {
|
||||
// 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
|
||||
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 infoArray = new Uint8Array(infoBuffer);
|
||||
infoArray.set(new Uint8Array(info), 32);
|
||||
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[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[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 ];
|
||||
});
|
||||
});
|
||||
|
@ -72,7 +72,7 @@
|
|||
// Curve 25519 crypto
|
||||
createKeyPair: function(privKey) {
|
||||
if (privKey === undefined) {
|
||||
privKey = textsecure.crypto.getRandomBytes(32);
|
||||
privKey = axolotl.crypto.getRandomBytes(32);
|
||||
}
|
||||
if (privKey.byteLength != 32) {
|
||||
throw new Error("Invalid private key");
|
||||
|
|
|
@ -47,7 +47,7 @@ window.textsecure.protocol = function() {
|
|||
}
|
||||
|
||||
crypto_storage.getNewStoredKeyPair = function(keyName) {
|
||||
return textsecure.crypto.createKeyPair().then(function(keyPair) {
|
||||
return axolotl.crypto.createKeyPair().then(function(keyPair) {
|
||||
crypto_storage.putKeyPair(keyName, keyPair);
|
||||
return keyPair;
|
||||
});
|
||||
|
@ -191,11 +191,11 @@ window.textsecure.protocol = function() {
|
|||
|
||||
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) {
|
||||
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))
|
||||
throw new Error("Bad MAC");
|
||||
});
|
||||
|
@ -207,7 +207,7 @@ window.textsecure.protocol = function() {
|
|||
var calculateRatchet = function(session, remoteKey, sending) {
|
||||
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) {
|
||||
if (sending)
|
||||
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++)
|
||||
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() {
|
||||
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);
|
||||
|
||||
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,
|
||||
// otherwise we figure it out when we first maybeStepRatchet with the remote's ephemeral key
|
||||
if (isInitiator) {
|
||||
return textsecure.crypto.createKeyPair().then(function(ourSendingEphemeralKey) {
|
||||
return axolotl.crypto.createKeyPair().then(function(ourSendingEphemeralKey) {
|
||||
session.currentRatchet.ephemeralKeyPair = ourSendingEphemeralKey;
|
||||
return calculateRatchet(session, theirSignedPubKey, true).then(function() {
|
||||
return session;
|
||||
|
@ -276,17 +276,17 @@ window.textsecure.protocol = function() {
|
|||
if (ourEphemeralKey === undefined || theirEphemeralPubKey === undefined)
|
||||
promise = Promise.resolve(new ArrayBuffer(0));
|
||||
else
|
||||
promise = textsecure.crypto.ECDHE(theirEphemeralPubKey, ourEphemeralKey.privKey);
|
||||
promise = axolotl.crypto.ECDHE(theirEphemeralPubKey, ourEphemeralKey.privKey);
|
||||
return promise.then(function(ecRes4) {
|
||||
sharedSecret.set(new Uint8Array(ecRes4), 32 * 4);
|
||||
|
||||
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(ecRes2), 32 * 2);
|
||||
}).then(finishInit);
|
||||
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(ecRes2), 32)
|
||||
}).then(finishInit);
|
||||
|
@ -430,9 +430,9 @@ window.textsecure.protocol = function() {
|
|||
var key = toArrayBuffer(chain.chainKey.key);
|
||||
var byteArray = new Uint8Array(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;
|
||||
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.chainKey.key = key
|
||||
chain.chainKey.counter += 1;
|
||||
|
@ -456,7 +456,7 @@ window.textsecure.protocol = function() {
|
|||
delete session[previousRatchet];
|
||||
}
|
||||
|
||||
return textsecure.crypto.createKeyPair().then(function(keyPair) {
|
||||
return axolotl.crypto.createKeyPair().then(function(keyPair) {
|
||||
ratchet.ephemeralKeyPair = keyPair;
|
||||
return calculateRatchet(session, remoteKey, true).then(function() {
|
||||
ratchet.lastRemoteEphemeralKey = remoteKey;
|
||||
|
@ -510,7 +510,7 @@ window.textsecure.protocol = function() {
|
|||
macInput.set(new Uint8Array(messageProtoArray), 33*2 + 1);
|
||||
|
||||
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) {
|
||||
|
||||
paddedPlaintext = new Uint8Array(paddedPlaintext);
|
||||
|
@ -563,7 +563,7 @@ window.textsecure.protocol = function() {
|
|||
var mac = decodedMessage.slice(decodedMessage.byteLength - 10, decodedMessage.byteLength);
|
||||
|
||||
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);
|
||||
|
||||
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 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);
|
||||
ivAndCiphertext.set(new Uint8Array(iv));
|
||||
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);
|
||||
encryptedBin.set(ivAndCiphertext);
|
||||
encryptedBin.set(new Uint8Array(mac), 16 + ciphertext.byteLength);
|
||||
|
@ -639,7 +639,7 @@ window.textsecure.protocol = function() {
|
|||
msg.counter = chain.chainKey.counter;
|
||||
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;
|
||||
var encodedMsg = toArrayBuffer(msg.encode());
|
||||
|
||||
|
@ -649,7 +649,7 @@ window.textsecure.protocol = function() {
|
|||
macInput[33*2] = (3 << 4) | 3;
|
||||
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);
|
||||
result[0] = (3 << 4) | 3;
|
||||
result.set(new Uint8Array(encodedMsg), 1);
|
||||
|
@ -677,7 +677,7 @@ window.textsecure.protocol = function() {
|
|||
preKeyMsg.registrationId = textsecure.storage.getUnencrypted("registrationId");
|
||||
|
||||
if (session === undefined) {
|
||||
return textsecure.crypto.createKeyPair().then(function(baseKey) {
|
||||
return axolotl.crypto.createKeyPair().then(function(baseKey) {
|
||||
preKeyMsg.preKeyId = deviceObject.preKeyId;
|
||||
preKeyMsg.signedPreKeyId = deviceObject.signedKeyId;
|
||||
preKeyMsg.baseKey = toArrayBuffer(baseKey.pubKey);
|
||||
|
@ -733,7 +733,7 @@ window.textsecure.protocol = function() {
|
|||
promises[i] = generateKey(i);
|
||||
|
||||
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};
|
||||
});
|
||||
});
|
||||
|
@ -766,7 +766,7 @@ window.textsecure.protocol = function() {
|
|||
var masterEphemeral = toArrayBuffer(deviceInit.publicKey);
|
||||
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) {
|
||||
if (new Uint8Array(message)[0] != 1)
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
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;
|
||||
socketInfo.pubKey = keyPair.pubKey;
|
||||
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 plaintext = hexToArrayBuffer('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710');
|
||||
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);
|
||||
}).then(done).catch(done);
|
||||
});
|
||||
|
@ -36,7 +36,7 @@ describe("Crypto", function() {
|
|||
var iv = hexToArrayBuffer('000102030405060708090a0b0c0d0e0f');
|
||||
var plaintext = hexToArrayBuffer('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710');
|
||||
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);
|
||||
}).then(done).catch(done);
|
||||
});
|
||||
|
@ -47,7 +47,7 @@ describe("Crypto", function() {
|
|||
var key = hexToArrayBuffer('6f35628d65813435534b5d67fbdb54cb33403d04e843103e6399f806cb5df95febbdd61236f33245');
|
||||
var input = hexToArrayBuffer('752cff52e4b90768558e5369e75d97c69643509a5e5904e0a386cbe4d0970ef73f918f675945a9aefe26daea27587e8dc909dd56fd0468805f834039b345f855cfe19c44b55af241fff3ffcd8045cd5c288e6c4e284c3720570b58e4d47b8feeedc52fd1401f698a209fccfa3b4c0d9a797b046a2759f82a54c41ccd7b5f592b');
|
||||
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);
|
||||
}).then(done).catch(done);
|
||||
});
|
||||
|
@ -71,7 +71,7 @@ describe("Crypto", function() {
|
|||
for (var i = 0; i < 10; 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[1].slice(0, 10), T2);
|
||||
}).then(done).catch(done);
|
||||
|
@ -88,21 +88,21 @@ describe("Crypto", function() {
|
|||
|
||||
describe("createKeyPair", function() {
|
||||
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.pubKey, alice_pub);
|
||||
done();
|
||||
}).catch(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.pubKey, bob_pub);
|
||||
done();
|
||||
}).catch(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.pubKey.byteLength, 33);
|
||||
assert.strictEqual(new Uint8Array(keypair.pubKey)[0], 5);
|
||||
|
@ -113,13 +113,13 @@ describe("Crypto", function() {
|
|||
|
||||
describe("ECDHE", function() {
|
||||
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);
|
||||
done();
|
||||
}).catch(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);
|
||||
done();
|
||||
}).catch(done);
|
||||
|
@ -133,7 +133,7 @@ describe("Crypto", function() {
|
|||
describe("Ed25519Sign", function() {
|
||||
// Some self-generated test vectors
|
||||
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);
|
||||
}).then(done).catch(done);
|
||||
});
|
||||
|
@ -144,7 +144,7 @@ describe("Crypto", function() {
|
|||
var badsig = sig.slice(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') {
|
||||
done();
|
||||
} else { throw e; }
|
||||
|
@ -152,7 +152,7 @@ describe("Crypto", function() {
|
|||
});
|
||||
|
||||
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++) {
|
||||
res.devices[i].signedPreKey.publicKey = StringView.base64ToBytes(res.devices[i].signedPreKey.publicKey);
|
||||
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);
|
||||
//TODO: Is this still needed?
|
||||
//if (res.devices[i].keyId === undefined)
|
||||
|
|
|
@ -242,14 +242,14 @@ textsecure.processDecrypted = function(decrypted, source) {
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
var password = btoa(getString(textsecure.crypto.getRandomBytes(16)));
|
||||
var password = btoa(getString(axolotl.crypto.getRandomBytes(16)));
|
||||
password = password.substring(0, password.length - 2);
|
||||
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;
|
||||
textsecure.storage.putUnencrypted("registrationId", registrationId);
|
||||
|
||||
|
@ -273,14 +273,14 @@ window.textsecure.registerSecondDevice = function(encodedProvisionEnvelope, cryp
|
|||
return cryptoInfo.decryptAndHandleDeviceInit(envelope).then(function(identityKey) {
|
||||
stepDone(1);
|
||||
|
||||
var signalingKey = textsecure.crypto.getRandomBytes(32 + 20);
|
||||
var signalingKey = axolotl.crypto.getRandomBytes(32 + 20);
|
||||
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);
|
||||
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;
|
||||
textsecure.storage.putUnencrypted("registrationId", registrationId);
|
||||
|
||||
|
|
|
@ -231,9 +231,9 @@ window.textsecure.messaging = function() {
|
|||
|
||||
makeAttachmentPointer = function(attachment) {
|
||||
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.api.putAttachment(encryptedBin).then(function(id) {
|
||||
proto.id = id;
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
|
||||
<script type="text/javascript" src="fake_api.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="websocket-resources_test.js"></script>
|
||||
<script type="text/javascript" src="protocol_test.js"></script>
|
||||
|
|
|
@ -84,30 +84,30 @@ describe('Protocol', function() {
|
|||
|
||||
describe("Axolotl", function() {
|
||||
var runAxolotlTest = function(v) {
|
||||
var origCreateKeyPair = textsecure.crypto.createKeyPair;
|
||||
var origCreateKeyPair = axolotl.crypto.createKeyPair;
|
||||
var doStep;
|
||||
var stepDone;
|
||||
|
||||
stepDone = function(res) {
|
||||
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;
|
||||
} else if (step == v.length) {
|
||||
textsecure.crypto.createKeyPair = origCreateKeyPair;
|
||||
axolotl.crypto.createKeyPair = origCreateKeyPair;
|
||||
return true;
|
||||
} else
|
||||
return doStep().then(stepDone);
|
||||
}
|
||||
|
||||
var privKeyQueue = [];
|
||||
textsecure.crypto.createKeyPair = function(privKey) {
|
||||
axolotl.crypto.createKeyPair = function(privKey) {
|
||||
if (privKey !== undefined)
|
||||
return origCreateKeyPair(privKey);
|
||||
if (privKeyQueue.length == 0)
|
||||
throw new Error('Out of private keys');
|
||||
else {
|
||||
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));
|
||||
if (getString(keyPair.privKey) != getString(privKey))
|
||||
throw new Error('Failed to rederive private key!');
|
||||
|
@ -151,13 +151,13 @@ describe('Protocol', function() {
|
|||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
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);
|
||||
return postLocalKeySetup();
|
||||
});
|
||||
|
@ -204,7 +204,7 @@ describe('Protocol', function() {
|
|||
privKeyQueue.push(data.ourEphemeralKey);
|
||||
|
||||
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);
|
||||
return postLocalKeySetup();
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue