Request new keys (largely untested)
This commit is contained in:
parent
56433bd9af
commit
aec36468bc
4 changed files with 88 additions and 69 deletions
|
@ -218,8 +218,11 @@ window.textsecure.api = function() {
|
||||||
var code = jqXHR.status;
|
var code = jqXHR.status;
|
||||||
if (code > 999 || code < 100)
|
if (code > 999 || code < 100)
|
||||||
code = -1;
|
code = -1;
|
||||||
|
|
||||||
var e = new Error(code);
|
var e = new Error(code);
|
||||||
e.name = "HTTPError";
|
e.name = "HTTPError";
|
||||||
|
if (jqXHR.responseJSON)
|
||||||
|
e.response = jqXHR.responseJSON;
|
||||||
reject(e);
|
reject(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
// Random shared utilities that are used only by chromium things
|
// Random shared utilities that are used only by chromium things
|
||||||
|
|
||||||
function registrationDone() {
|
function registrationDone() {
|
||||||
textsecure.storage.putUnencrypted("registration_done", "");
|
localStorage.setItem("chromiumRegistrationDone", "");
|
||||||
//TODO: Fix dirty hack:
|
//TODO: Fix dirty hack:
|
||||||
chrome.runtime.reload();
|
chrome.runtime.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
function isRegistrationDone() {
|
function isRegistrationDone() {
|
||||||
return textsecure.storage.getUnencrypted("registration_done") !== undefined;
|
return localStorage.getItem("chromiumRegistrationDone") !== null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,6 +231,11 @@ window.textsecure.crypto = new function() {
|
||||||
throw new Error("Datastore inconsistency: session was stored without identity key");
|
throw new Error("Datastore inconsistency: session was stored without identity key");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used when device keys change - we assume key compromise so refuse all new messages
|
||||||
|
self.forceRemoveAllSessions = function(encodedNumber) {
|
||||||
|
textsecure.storage.removeEncrypted("session" + encodedNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************
|
/*****************************
|
||||||
*** Internal Crypto stuff ***
|
*** Internal Crypto stuff ***
|
||||||
|
|
137
js/helpers.js
137
js/helpers.js
|
@ -334,58 +334,46 @@ window.textsecure.storage = function() {
|
||||||
*** Device Storage ***
|
*** Device Storage ***
|
||||||
**********************/
|
**********************/
|
||||||
self.devices = function() {
|
self.devices = function() {
|
||||||
//TODO: Just store numbers with the device list in the object, not a list of pointers...
|
|
||||||
var self = {};
|
var self = {};
|
||||||
|
|
||||||
self.getDeviceObject = function(encodedNumber) {
|
|
||||||
return textsecure.storage.getEncrypted("deviceObject" + encodedNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
var getDeviceIdListFromNumber = function(number) {
|
|
||||||
return textsecure.storage.getEncrypted("deviceIdList" + number, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
var addDeviceIdForNumber = function(number, deviceId) {
|
|
||||||
var deviceIdList = getDeviceIdListFromNumber(number);
|
|
||||||
for (var i = 0; i < deviceIdList.length; i++) {
|
|
||||||
if (deviceIdList[i] == deviceId)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
deviceIdList[deviceIdList.length] = deviceId;
|
|
||||||
textsecure.storage.putEncrypted("deviceIdList" + number, deviceIdList);
|
|
||||||
}
|
|
||||||
|
|
||||||
var getDeviceId = function(encodedNumber) {
|
|
||||||
var split = encodedNumber.split(".");
|
|
||||||
if (split.length > 1)
|
|
||||||
return split[1];
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// throws "Identity key mismatch"
|
|
||||||
self.saveDeviceObject = function(deviceObject) {
|
self.saveDeviceObject = function(deviceObject) {
|
||||||
var existing = this.getDeviceObject(deviceObject.encodedNumber);
|
var number = textsecure.utils.unencodeNumber(deviceObject.encodedNumber);
|
||||||
if (existing === undefined)
|
var map = textsecure.storage.getEncrypted("devices" + number);
|
||||||
existing = {encodedNumber: deviceObject.encodedNumber};
|
|
||||||
for (key in deviceObject) {
|
|
||||||
if (key == "encodedNumber")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (key == "identityKey" && deviceObject.identityKey != deviceObject.identityKey)
|
if (map === undefined)
|
||||||
throw new Error("Identity key mismatch");
|
map = { devices: [deviceObject], identityKey: deviceObject.identityKey };
|
||||||
|
else if (map.identityKey != getString(deviceObject.identityKey))
|
||||||
|
throw new Error("Identity key changed");
|
||||||
|
|
||||||
existing[key] = deviceObject[key];
|
textsecure.storage.putEncrypted("devices" + number, map);
|
||||||
}
|
|
||||||
textsecure.storage.putEncrypted("deviceObject" + deviceObject.encodedNumber, existing);
|
|
||||||
addDeviceIdForNumber(textsecure.utils.unencodeNumber(deviceObject.encodedNumber), getDeviceId(deviceObject.encodedNumber));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.getDeviceObjectListFromNumber = function(number) {
|
self.getDeviceObjectsForNumber = function(number) {
|
||||||
var deviceObjectList = [];
|
var map = textsecure.storage.getEncrypted("devices" + number);
|
||||||
var deviceIdList = getDeviceIdListFromNumber(number);
|
return map === undefined ? [] : map.devices;
|
||||||
for (var i = 0; i < deviceIdList.length; i++)
|
}
|
||||||
deviceObjectList[deviceObjectList.length] = self.getDeviceObject(number + "." + deviceIdList[i]);
|
|
||||||
return deviceObjectList;
|
self.removeDeviceIdsForNumber = function(number, deviceIdsToRemove) {
|
||||||
|
var map = textsecure.storage.getEncrypted("devices" + number);
|
||||||
|
if (map === undefined)
|
||||||
|
throw new Error("Tried to remove device for unknown number");
|
||||||
|
|
||||||
|
var newDevices = [];
|
||||||
|
var devicesRemoved = 0;
|
||||||
|
for (device in map.devices) {
|
||||||
|
var keep = true;
|
||||||
|
for (idToRemove in deviceIdsToRemove)
|
||||||
|
if (device.deviceId == idToRemove)
|
||||||
|
keep = false;
|
||||||
|
|
||||||
|
if (keep)
|
||||||
|
newDevices.push(device);
|
||||||
|
else
|
||||||
|
devicesRemoved++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (devicesRemoved != deviceIdsToRemove.length)
|
||||||
|
throw new Error("Tried to remove unknown device");
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -519,18 +507,29 @@ window.textsecure.subscribeToPush = function() {
|
||||||
|
|
||||||
// sendMessage(numbers = [], message = PushMessageContentProto, callback(success/failure map))
|
// sendMessage(numbers = [], message = PushMessageContentProto, callback(success/failure map))
|
||||||
window.textsecure.sendMessage = function() {
|
window.textsecure.sendMessage = function() {
|
||||||
function getKeysForNumber(number) {
|
function getKeysForNumber(number, updateDevices) {
|
||||||
return textsecure.api.getKeysForNumber(number).then(function(response) {
|
return textsecure.api.getKeysForNumber(number).then(function(response) {
|
||||||
for (var i = 0; i < response.length; i++) {
|
var identityKey = getString(response[0].identityKey);
|
||||||
|
for (device in response)
|
||||||
|
if (getString(device.identityKey) != identityKey)
|
||||||
|
throw new Error("Identity key changed");
|
||||||
|
|
||||||
|
for (device in response) {
|
||||||
|
var updateDevice = (updateDevices === undefined);
|
||||||
|
if (!updateDevice)
|
||||||
|
for (deviceId in updateDevices)
|
||||||
|
if (deviceId == device.deviceId)
|
||||||
|
updateDevice = true;
|
||||||
|
|
||||||
|
if (updateDevice)
|
||||||
textsecure.storage.devices.saveDeviceObject({
|
textsecure.storage.devices.saveDeviceObject({
|
||||||
encodedNumber: number + "." + response[i].deviceId,
|
encodedNumber: number + "." + device.deviceId,
|
||||||
identityKey: response[i].identityKey,
|
identityKey: device.identityKey,
|
||||||
publicKey: response[i].publicKey,
|
publicKey: device.publicKey,
|
||||||
preKeyId: response[i].keyId,
|
preKeyId: device.keyId,
|
||||||
registrationId: response[i].registrationId
|
registrationId: device.registrationId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return response[0].identityKey;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,7 +541,7 @@ window.textsecure.sendMessage = function() {
|
||||||
var promises = [];
|
var promises = [];
|
||||||
|
|
||||||
var addEncryptionFor = function(i) {
|
var addEncryptionFor = function(i) {
|
||||||
return new Promise(function(resolve) { // Wrap in a promise for the throws
|
return new Promise(function(resolve) { // Wrap in a promise for the direct throws
|
||||||
if (deviceObjectList[i].relay !== undefined) {
|
if (deviceObjectList[i].relay !== undefined) {
|
||||||
if (relay === undefined)
|
if (relay === undefined)
|
||||||
relay = deviceObjectList[i].relay;
|
relay = deviceObjectList[i].relay;
|
||||||
|
@ -601,19 +600,36 @@ window.textsecure.sendMessage = function() {
|
||||||
numberCompleted();
|
numberCompleted();
|
||||||
}).catch(function(error) {
|
}).catch(function(error) {
|
||||||
if (error instanceof Error && error.name == "HTTPError" && (error.message == 410 || error.message == 409)) {
|
if (error instanceof Error && error.name == "HTTPError" && (error.message == 410 || error.message == 409)) {
|
||||||
//TODO: Re-request keys for number here
|
var resetDevices = ((error.message == 410) ? error.response.staleDevices : error.response.missingDevices);
|
||||||
|
getKeysForNumber(number, resetDevices).then(function() {
|
||||||
|
if (error.message == 409)
|
||||||
|
resetDevices = resetDevices.concat(error.response.extraDevices);
|
||||||
|
|
||||||
|
textsecure.storage.devices.removeDeviceIdsForNumber(number, resetDevices);
|
||||||
|
for (deviceId in resetDevices)
|
||||||
|
textsecure.crypto.forceRemoveAllSessions(number + "." + resetDevices);
|
||||||
|
|
||||||
|
//TODO: Try again
|
||||||
|
}).catch(function(error) {
|
||||||
|
if (error.message !== "Identity key changed")
|
||||||
|
registerError(number, "Failed to reload device keys", error);
|
||||||
|
else {
|
||||||
|
// TODO: Identity key changed, check which devices it changed for and get upset
|
||||||
|
registerError(number, "Identity key changed!!!!", error);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
} else
|
||||||
registerError(number, "Failed to create or send message", error);
|
registerError(number, "Failed to create or send message", error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < numbers.length; i++) {
|
for (var i = 0; i < numbers.length; i++) {
|
||||||
var number = numbers[i];
|
var number = numbers[i];
|
||||||
var devicesForNumber = textsecure.storage.devices.getDeviceObjectListFromNumber(number);
|
var devicesForNumber = textsecure.storage.devices.getDeviceObjectsForNumber(number);
|
||||||
|
|
||||||
if (devicesForNumber.length == 0) {
|
if (devicesForNumber.length == 0) {
|
||||||
getKeysForNumber(number).then(function(identity_key) {
|
getKeysForNumber(number).then(function() {
|
||||||
devicesForNumber = textsecure.storage.devices.getDeviceObjectListFromNumber(number);
|
devicesForNumber = textsecure.storage.devices.getDeviceObjectsForNumber(number);
|
||||||
if (devicesForNumber.length == 0)
|
if (devicesForNumber.length == 0)
|
||||||
registerError(number, "Failed to retreive new device keys for number " + number, null);
|
registerError(number, "Failed to retreive new device keys for number " + number, null);
|
||||||
else
|
else
|
||||||
|
@ -661,8 +677,3 @@ window.textsecure.register = function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
function requestIdentityPrivKeyFromMasterDevice(number, identityKey) {
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue