Add textsecure.AccountManager
This class should be used for account registration and for refreshing prekeys for your account.
This commit is contained in:
parent
a960acacc6
commit
f465bdddbf
7 changed files with 327 additions and 225 deletions
|
@ -56,6 +56,7 @@ module.exports = function(grunt) {
|
|||
'libtextsecure/helpers.js',
|
||||
'libtextsecure/stringview.js',
|
||||
'libtextsecure/api.js',
|
||||
'libtextsecure/account_manager.js',
|
||||
'libtextsecure/message_receiver.js',
|
||||
'libtextsecure/sendmessage.js',
|
||||
],
|
||||
|
|
|
@ -38913,116 +38913,6 @@ textsecure.processDecrypted = function(decrypted, source) {
|
|||
});
|
||||
};
|
||||
|
||||
window.textsecure.refreshPreKeys = function() {
|
||||
return textsecure.api.getMyKeys().then(function(preKeyCount) {
|
||||
if (preKeyCount < 10) {
|
||||
generateKeys();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function createAccount(number, verificationCode, identityKeyPair, single_device) {
|
||||
textsecure.storage.put('identityKey', identityKeyPair);
|
||||
|
||||
var signalingKey = textsecure.crypto.getRandomBytes(32 + 20);
|
||||
textsecure.storage.put('signaling_key', signalingKey);
|
||||
|
||||
var password = btoa(getString(textsecure.crypto.getRandomBytes(16)));
|
||||
password = password.substring(0, password.length - 2);
|
||||
textsecure.storage.put("password", password);
|
||||
|
||||
var registrationId = axolotl.util.generateRegistrationId();
|
||||
textsecure.storage.put("registrationId", registrationId);
|
||||
|
||||
return textsecure.api.confirmCode(
|
||||
number, verificationCode, password, signalingKey, registrationId, single_device
|
||||
).then(function(response) {
|
||||
textsecure.storage.user.setNumberAndDeviceId(number, response.deviceId || 1);
|
||||
textsecure.storage.put("regionCode", libphonenumber.util.getRegionCodeForNumber(number));
|
||||
|
||||
return textsecure.protocol_wrapper.generateKeys().then(textsecure.registration.done);
|
||||
});
|
||||
}
|
||||
|
||||
function generateKeys(count, progressCallback) {
|
||||
if (count === undefined) {
|
||||
throw TypeError('generateKeys: count is undefined');
|
||||
}
|
||||
if (typeof progressCallback !== 'function') {
|
||||
progressCallback = undefined;
|
||||
}
|
||||
var store = textsecure.storage.axolotl;
|
||||
var identityKey = store.getMyIdentityKey();
|
||||
var result = { preKeys: [], identityKey: identityKey.pubKey };
|
||||
var promises = [];
|
||||
|
||||
var startId = textsecure.storage.get('maxPreKeyId', 1);
|
||||
var signedKeyId = textsecure.storage.get('signedKeyId', 1);
|
||||
|
||||
for (var keyId = startId; keyId < startId+count; ++keyId) {
|
||||
promises.push(
|
||||
axolotl.util.generatePreKey(keyId).then(function(res) {
|
||||
store.putPreKey(res.keyId, res.keyPair);
|
||||
result.preKeys.push({
|
||||
keyId : res.keyId,
|
||||
publicKey : res.keyPair.pubKey
|
||||
});
|
||||
if (progressCallback) { progressCallback(); }
|
||||
})
|
||||
);
|
||||
}
|
||||
promises.push(
|
||||
axolotl.util.generateSignedPreKey(identityKey, signedKeyId).then(function(res) {
|
||||
store.putSignedPreKey(res.keyId, res.keyPair);
|
||||
result.signedPreKey = {
|
||||
keyId : res.keyId,
|
||||
publicKey : res.keyPair.pubKey,
|
||||
signature : res.signature
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
store.removeSignedPreKey(signedKeyId - 2);
|
||||
textsecure.storage.put('maxPreKeyId', startId + count);
|
||||
textsecure.storage.put('signedKeyId', signedKeyId + 1);
|
||||
|
||||
return Promise.all(promises).then(function() {
|
||||
return result;
|
||||
});
|
||||
};
|
||||
|
||||
window.textsecure.registerSecondDevice = function(setProvisioningUrl, confirmNumber, progressCallback) {
|
||||
return textsecure.protocol_wrapper.createIdentityKeyRecvSocket().then(function(cryptoInfo) {
|
||||
return new Promise(function(resolve) {
|
||||
new WebSocketResource(textsecure.api.getTempWebsocket(), function(request) {
|
||||
if (request.path == "/v1/address" && request.verb == "PUT") {
|
||||
var proto = textsecure.protobuf.ProvisioningUuid.decode(request.body);
|
||||
setProvisioningUrl([
|
||||
'tsdevice:/?uuid=', proto.uuid, '&pub_key=',
|
||||
encodeURIComponent(btoa(getString(cryptoInfo.pubKey)))
|
||||
].join(''));
|
||||
request.respond(200, 'OK');
|
||||
} else if (request.path == "/v1/message" && request.verb == "PUT") {
|
||||
var envelope = textsecure.protobuf.ProvisionEnvelope.decode(request.body, 'binary');
|
||||
request.respond(200, 'OK');
|
||||
resolve(cryptoInfo.decryptAndHandleDeviceInit(envelope).then(function(provisionMessage) {
|
||||
return confirmNumber(provisionMessage.number).then(function() {
|
||||
return createAccount(
|
||||
provisionMessage.number,
|
||||
provisionMessage.provisioningCode,
|
||||
provisionMessage.identityKeyPair,
|
||||
false
|
||||
);
|
||||
});
|
||||
}));
|
||||
} else {
|
||||
console.log('Unknown websocket message', request.path);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/* vim: ts=4:sw=4:expandtab
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
@ -39480,6 +39370,167 @@ window.textsecure.api = function () {
|
|||
return self;
|
||||
}();
|
||||
|
||||
/* vim: ts=4:sw=4:expandtab
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
;(function () {
|
||||
'use strict';
|
||||
window.textsecure = window.textsecure || {};
|
||||
|
||||
function AccountManager() {
|
||||
}
|
||||
|
||||
AccountManager.prototype = {
|
||||
constructor: AccountManager,
|
||||
requestVoiceVerification: function(number) {
|
||||
return TextSecureServer.requestVerificationVoice(number);
|
||||
},
|
||||
requestSMSVerification: function(number) {
|
||||
return TextSecureServer.requestVerificationSMS(number);
|
||||
},
|
||||
registerSingleDevice: function(number, verificationCode) {
|
||||
return axolotl.util.generateIdentityKeyPair().then(function(identityKeyPair) {
|
||||
return createAccount(number, verificationCode, identityKeyPair, true).
|
||||
then(function() { return generateKeys(100); }).
|
||||
then(TextSecureServer.registerKeys).
|
||||
then(textsecure.registration.done);
|
||||
});
|
||||
},
|
||||
registerSecondDevice: function(setProvisioningUrl, confirmNumber, progressCallback) {
|
||||
return textsecure.protocol_wrapper.createIdentityKeyRecvSocket().then(function(cryptoInfo) {
|
||||
return new Promise(function(resolve) {
|
||||
new WebSocketResource(textsecure.api.getTempWebsocket(), function(request) {
|
||||
if (request.path == "/v1/address" && request.verb == "PUT") {
|
||||
var proto = textsecure.protobuf.ProvisioningUuid.decode(request.body);
|
||||
setProvisioningUrl([
|
||||
'tsdevice:/?uuid=', proto.uuid, '&pub_key=',
|
||||
encodeURIComponent(btoa(getString(cryptoInfo.pubKey)))
|
||||
].join(''));
|
||||
request.respond(200, 'OK');
|
||||
} else if (request.path == "/v1/message" && request.verb == "PUT") {
|
||||
var envelope = textsecure.protobuf.ProvisionEnvelope.decode(request.body, 'binary');
|
||||
request.respond(200, 'OK');
|
||||
resolve(cryptoInfo.decryptAndHandleDeviceInit(envelope).then(function(provisionMessage) {
|
||||
return confirmNumber(provisionMessage.number).then(function() {
|
||||
return createAccount(
|
||||
provisionMessage.number,
|
||||
provisionMessage.provisioningCode,
|
||||
provisionMessage.identityKeyPair,
|
||||
false
|
||||
);
|
||||
});
|
||||
}));
|
||||
} else {
|
||||
console.log('Unknown websocket message', request.path);
|
||||
}
|
||||
});
|
||||
});
|
||||
}).then(function() {
|
||||
return generateKeys(100, progressCallback);
|
||||
}).then(TextSecureServer.registerKeys).then(textsecure.registration.done);
|
||||
},
|
||||
refreshPreKeys: function() {
|
||||
return textsecure.api.getMyKeys().then(function(preKeyCount) {
|
||||
if (preKeyCount < 10) {
|
||||
return generateKeys(100);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function createAccount(number, verificationCode, identityKeyPair, single_device) {
|
||||
textsecure.storage.put('identityKey', identityKeyPair);
|
||||
|
||||
var signalingKey = textsecure.crypto.getRandomBytes(32 + 20);
|
||||
textsecure.storage.put('signaling_key', signalingKey);
|
||||
|
||||
var password = btoa(getString(textsecure.crypto.getRandomBytes(16)));
|
||||
password = password.substring(0, password.length - 2);
|
||||
textsecure.storage.put("password", password);
|
||||
|
||||
var registrationId = axolotl.util.generateRegistrationId();
|
||||
textsecure.storage.put("registrationId", registrationId);
|
||||
|
||||
return textsecure.api.confirmCode(
|
||||
number, verificationCode, password, signalingKey, registrationId, single_device
|
||||
).then(function(response) {
|
||||
textsecure.storage.user.setNumberAndDeviceId(number, response.deviceId || 1);
|
||||
textsecure.storage.put("regionCode", libphonenumber.util.getRegionCodeForNumber(number));
|
||||
});
|
||||
}
|
||||
|
||||
textsecure.AccountManager = AccountManager;
|
||||
|
||||
}());
|
||||
|
||||
function generateKeys(count, progressCallback) {
|
||||
if (typeof progressCallback !== 'function') {
|
||||
progressCallback = undefined;
|
||||
}
|
||||
var startId = textsecure.storage.get('maxPreKeyId', 1);
|
||||
var signedKeyId = textsecure.storage.get('signedKeyId', 1);
|
||||
|
||||
if (typeof startId != 'number') {
|
||||
throw new Error('Invalid maxPreKeyId');
|
||||
}
|
||||
if (typeof signedKeyId != 'number') {
|
||||
throw new Error('Invalid signedKeyId');
|
||||
}
|
||||
|
||||
textsecure.protocol_wrapper.startWorker();
|
||||
|
||||
var store = textsecure.storage.axolotl;
|
||||
var identityKey = store.getMyIdentityKey();
|
||||
var result = { preKeys: [], identityKey: identityKey.pubKey };
|
||||
var promises = [];
|
||||
|
||||
for (var keyId = startId; keyId < startId+count; ++keyId) {
|
||||
promises.push(
|
||||
axolotl.util.generatePreKey(keyId).then(function(res) {
|
||||
store.putPreKey(res.keyId, res.keyPair);
|
||||
result.preKeys.push({
|
||||
keyId : res.keyId,
|
||||
publicKey : res.keyPair.pubKey
|
||||
});
|
||||
if (progressCallback) { progressCallback(); }
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
promises.push(
|
||||
axolotl.util.generateSignedPreKey(identityKey, signedKeyId).then(function(res) {
|
||||
store.putSignedPreKey(res.keyId, res.keyPair);
|
||||
result.signedPreKey = {
|
||||
keyId : res.keyId,
|
||||
publicKey : res.keyPair.pubKey,
|
||||
signature : res.signature
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
store.removeSignedPreKey(signedKeyId - 2);
|
||||
textsecure.storage.put('maxPreKeyId', startId + count);
|
||||
textsecure.storage.put('signedKeyId', signedKeyId + 1);
|
||||
return Promise.all(promises).then(function() {
|
||||
textsecure.protocol_wrapper.stopWorker();
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
/* vim: ts=4:sw=4:expandtab
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
e.stopPropagation();
|
||||
$('.confirmation-dialog').hide();
|
||||
$('.progress-dialog').show();
|
||||
$('.progress-dialog .status').text('Registering new device...');
|
||||
$('.progress-dialog .status').text('Generating Keys');
|
||||
resolve();
|
||||
});
|
||||
$('.modal-container').show();
|
||||
|
@ -78,7 +78,8 @@
|
|||
$('#init-setup').show().addClass('in');
|
||||
$('#status').text("Connecting...");
|
||||
|
||||
bg.textsecure.registerSecondDevice(setProvisioningUrl, confirmNumber, incrementCounter).then(function() {
|
||||
var accountManager = new bg.textsecure.AccountManager();
|
||||
accountManager.registerSecondDevice(setProvisioningUrl, confirmNumber, incrementCounter).then(function() {
|
||||
$('.modal-container').hide();
|
||||
$('#init-setup').hide();
|
||||
$('#setup-complete').show().addClass('in');
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
;(function() {
|
||||
'use strict';
|
||||
var bg = extension.windows.getBackground();
|
||||
var accountManager = new bg.textsecure.AccountManager();
|
||||
|
||||
function log(s) {
|
||||
console.log(s);
|
||||
|
@ -61,7 +62,7 @@
|
|||
$('#error').hide();
|
||||
var number = phoneView.validateNumber();
|
||||
if (number) {
|
||||
bg.textsecure.api.requestVerificationVoice(number).catch(displayError);
|
||||
accountManager.requestVoiceVerification(number).catch(displayError);
|
||||
$('#step2').addClass('in').fadeIn();
|
||||
} else {
|
||||
$('#number-container').addClass('invalid');
|
||||
|
@ -72,7 +73,7 @@
|
|||
$('#error').hide();
|
||||
var number = phoneView.validateNumber();
|
||||
if (number) {
|
||||
bg.textsecure.api.requestVerificationSMS(number).catch(displayError);
|
||||
accountManager.requestSMSVerification(number).catch(displayError);
|
||||
$('#step2').addClass('in').fadeIn();
|
||||
} else {
|
||||
$('#number-container').addClass('invalid');
|
||||
|
@ -86,7 +87,7 @@
|
|||
|
||||
localStorage.clear();
|
||||
localStorage.setItem('first_install_ran', 1);
|
||||
bg.textsecure.registerSingleDevice(number, verificationCode).then(function() {
|
||||
accountManager.registerSingleDevice(number, verificationCode).then(function() {
|
||||
extension.navigator.tabs.create("options.html");
|
||||
window.close();
|
||||
}).catch(function(e) {
|
||||
|
|
157
libtextsecure/account_manager.js
Normal file
157
libtextsecure/account_manager.js
Normal file
|
@ -0,0 +1,157 @@
|
|||
/* vim: ts=4:sw=4:expandtab
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
;(function () {
|
||||
'use strict';
|
||||
window.textsecure = window.textsecure || {};
|
||||
|
||||
function AccountManager() {
|
||||
}
|
||||
|
||||
AccountManager.prototype = {
|
||||
constructor: AccountManager,
|
||||
requestVoiceVerification: function(number) {
|
||||
return TextSecureServer.requestVerificationVoice(number);
|
||||
},
|
||||
requestSMSVerification: function(number) {
|
||||
return TextSecureServer.requestVerificationSMS(number);
|
||||
},
|
||||
registerSingleDevice: function(number, verificationCode) {
|
||||
return axolotl.util.generateIdentityKeyPair().then(function(identityKeyPair) {
|
||||
return createAccount(number, verificationCode, identityKeyPair, true).
|
||||
then(function() { return generateKeys(100); }).
|
||||
then(TextSecureServer.registerKeys).
|
||||
then(textsecure.registration.done);
|
||||
});
|
||||
},
|
||||
registerSecondDevice: function(setProvisioningUrl, confirmNumber, progressCallback) {
|
||||
return textsecure.protocol_wrapper.createIdentityKeyRecvSocket().then(function(cryptoInfo) {
|
||||
return new Promise(function(resolve) {
|
||||
new WebSocketResource(textsecure.api.getTempWebsocket(), function(request) {
|
||||
if (request.path == "/v1/address" && request.verb == "PUT") {
|
||||
var proto = textsecure.protobuf.ProvisioningUuid.decode(request.body);
|
||||
setProvisioningUrl([
|
||||
'tsdevice:/?uuid=', proto.uuid, '&pub_key=',
|
||||
encodeURIComponent(btoa(getString(cryptoInfo.pubKey)))
|
||||
].join(''));
|
||||
request.respond(200, 'OK');
|
||||
} else if (request.path == "/v1/message" && request.verb == "PUT") {
|
||||
var envelope = textsecure.protobuf.ProvisionEnvelope.decode(request.body, 'binary');
|
||||
request.respond(200, 'OK');
|
||||
resolve(cryptoInfo.decryptAndHandleDeviceInit(envelope).then(function(provisionMessage) {
|
||||
return confirmNumber(provisionMessage.number).then(function() {
|
||||
return createAccount(
|
||||
provisionMessage.number,
|
||||
provisionMessage.provisioningCode,
|
||||
provisionMessage.identityKeyPair,
|
||||
false
|
||||
);
|
||||
});
|
||||
}));
|
||||
} else {
|
||||
console.log('Unknown websocket message', request.path);
|
||||
}
|
||||
});
|
||||
});
|
||||
}).then(function() {
|
||||
return generateKeys(100, progressCallback);
|
||||
}).then(TextSecureServer.registerKeys).then(textsecure.registration.done);
|
||||
},
|
||||
refreshPreKeys: function() {
|
||||
return textsecure.api.getMyKeys().then(function(preKeyCount) {
|
||||
if (preKeyCount < 10) {
|
||||
return generateKeys(100);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function createAccount(number, verificationCode, identityKeyPair, single_device) {
|
||||
textsecure.storage.put('identityKey', identityKeyPair);
|
||||
|
||||
var signalingKey = textsecure.crypto.getRandomBytes(32 + 20);
|
||||
textsecure.storage.put('signaling_key', signalingKey);
|
||||
|
||||
var password = btoa(getString(textsecure.crypto.getRandomBytes(16)));
|
||||
password = password.substring(0, password.length - 2);
|
||||
textsecure.storage.put("password", password);
|
||||
|
||||
var registrationId = axolotl.util.generateRegistrationId();
|
||||
textsecure.storage.put("registrationId", registrationId);
|
||||
|
||||
return textsecure.api.confirmCode(
|
||||
number, verificationCode, password, signalingKey, registrationId, single_device
|
||||
).then(function(response) {
|
||||
textsecure.storage.user.setNumberAndDeviceId(number, response.deviceId || 1);
|
||||
textsecure.storage.put("regionCode", libphonenumber.util.getRegionCodeForNumber(number));
|
||||
});
|
||||
}
|
||||
|
||||
textsecure.AccountManager = AccountManager;
|
||||
|
||||
}());
|
||||
|
||||
function generateKeys(count, progressCallback) {
|
||||
if (typeof progressCallback !== 'function') {
|
||||
progressCallback = undefined;
|
||||
}
|
||||
var startId = textsecure.storage.get('maxPreKeyId', 1);
|
||||
var signedKeyId = textsecure.storage.get('signedKeyId', 1);
|
||||
|
||||
if (typeof startId != 'number') {
|
||||
throw new Error('Invalid maxPreKeyId');
|
||||
}
|
||||
if (typeof signedKeyId != 'number') {
|
||||
throw new Error('Invalid signedKeyId');
|
||||
}
|
||||
|
||||
var store = textsecure.storage.axolotl;
|
||||
var identityKey = store.getMyIdentityKey();
|
||||
var result = { preKeys: [], identityKey: identityKey.pubKey };
|
||||
var promises = [];
|
||||
|
||||
for (var keyId = startId; keyId < startId+count; ++keyId) {
|
||||
promises.push(
|
||||
axolotl.util.generatePreKey(keyId).then(function(res) {
|
||||
store.putPreKey(res.keyId, res.keyPair);
|
||||
result.preKeys.push({
|
||||
keyId : res.keyId,
|
||||
publicKey : res.keyPair.pubKey
|
||||
});
|
||||
if (progressCallback) { progressCallback(); }
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
promises.push(
|
||||
axolotl.util.generateSignedPreKey(identityKey, signedKeyId).then(function(res) {
|
||||
store.putSignedPreKey(res.keyId, res.keyPair);
|
||||
result.signedPreKey = {
|
||||
keyId : res.keyId,
|
||||
publicKey : res.keyPair.pubKey,
|
||||
signature : res.signature
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
store.removeSignedPreKey(signedKeyId - 2);
|
||||
textsecure.storage.put('maxPreKeyId', startId + count);
|
||||
textsecure.storage.put('signedKeyId', signedKeyId + 1);
|
||||
return Promise.all(promises).then(function() {
|
||||
return result;
|
||||
});
|
||||
}
|
|
@ -247,113 +247,3 @@ textsecure.processDecrypted = function(decrypted, source) {
|
|||
return decrypted;
|
||||
});
|
||||
};
|
||||
|
||||
window.textsecure.refreshPreKeys = function() {
|
||||
return textsecure.api.getMyKeys().then(function(preKeyCount) {
|
||||
if (preKeyCount < 10) {
|
||||
generateKeys();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function createAccount(number, verificationCode, identityKeyPair, single_device) {
|
||||
textsecure.storage.put('identityKey', identityKeyPair);
|
||||
|
||||
var signalingKey = textsecure.crypto.getRandomBytes(32 + 20);
|
||||
textsecure.storage.put('signaling_key', signalingKey);
|
||||
|
||||
var password = btoa(getString(textsecure.crypto.getRandomBytes(16)));
|
||||
password = password.substring(0, password.length - 2);
|
||||
textsecure.storage.put("password", password);
|
||||
|
||||
var registrationId = axolotl.util.generateRegistrationId();
|
||||
textsecure.storage.put("registrationId", registrationId);
|
||||
|
||||
return textsecure.api.confirmCode(
|
||||
number, verificationCode, password, signalingKey, registrationId, single_device
|
||||
).then(function(response) {
|
||||
textsecure.storage.user.setNumberAndDeviceId(number, response.deviceId || 1);
|
||||
textsecure.storage.put("regionCode", libphonenumber.util.getRegionCodeForNumber(number));
|
||||
|
||||
return textsecure.protocol_wrapper.generateKeys().then(textsecure.registration.done);
|
||||
});
|
||||
}
|
||||
|
||||
function generateKeys(count, progressCallback) {
|
||||
if (count === undefined) {
|
||||
throw TypeError('generateKeys: count is undefined');
|
||||
}
|
||||
if (typeof progressCallback !== 'function') {
|
||||
progressCallback = undefined;
|
||||
}
|
||||
var store = textsecure.storage.axolotl;
|
||||
var identityKey = store.getMyIdentityKey();
|
||||
var result = { preKeys: [], identityKey: identityKey.pubKey };
|
||||
var promises = [];
|
||||
|
||||
var startId = textsecure.storage.get('maxPreKeyId', 1);
|
||||
var signedKeyId = textsecure.storage.get('signedKeyId', 1);
|
||||
|
||||
for (var keyId = startId; keyId < startId+count; ++keyId) {
|
||||
promises.push(
|
||||
axolotl.util.generatePreKey(keyId).then(function(res) {
|
||||
store.putPreKey(res.keyId, res.keyPair);
|
||||
result.preKeys.push({
|
||||
keyId : res.keyId,
|
||||
publicKey : res.keyPair.pubKey
|
||||
});
|
||||
if (progressCallback) { progressCallback(); }
|
||||
})
|
||||
);
|
||||
}
|
||||
promises.push(
|
||||
axolotl.util.generateSignedPreKey(identityKey, signedKeyId).then(function(res) {
|
||||
store.putSignedPreKey(res.keyId, res.keyPair);
|
||||
result.signedPreKey = {
|
||||
keyId : res.keyId,
|
||||
publicKey : res.keyPair.pubKey,
|
||||
signature : res.signature
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
store.removeSignedPreKey(signedKeyId - 2);
|
||||
textsecure.storage.put('maxPreKeyId', startId + count);
|
||||
textsecure.storage.put('signedKeyId', signedKeyId + 1);
|
||||
|
||||
return Promise.all(promises).then(function() {
|
||||
return result;
|
||||
});
|
||||
};
|
||||
|
||||
window.textsecure.registerSecondDevice = function(setProvisioningUrl, confirmNumber, progressCallback) {
|
||||
return textsecure.protocol_wrapper.createIdentityKeyRecvSocket().then(function(cryptoInfo) {
|
||||
return new Promise(function(resolve) {
|
||||
new WebSocketResource(textsecure.api.getTempWebsocket(), function(request) {
|
||||
if (request.path == "/v1/address" && request.verb == "PUT") {
|
||||
var proto = textsecure.protobuf.ProvisioningUuid.decode(request.body);
|
||||
setProvisioningUrl([
|
||||
'tsdevice:/?uuid=', proto.uuid, '&pub_key=',
|
||||
encodeURIComponent(btoa(getString(cryptoInfo.pubKey)))
|
||||
].join(''));
|
||||
request.respond(200, 'OK');
|
||||
} else if (request.path == "/v1/message" && request.verb == "PUT") {
|
||||
var envelope = textsecure.protobuf.ProvisionEnvelope.decode(request.body, 'binary');
|
||||
request.respond(200, 'OK');
|
||||
resolve(cryptoInfo.decryptAndHandleDeviceInit(envelope).then(function(provisionMessage) {
|
||||
return confirmNumber(provisionMessage.number).then(function() {
|
||||
return createAccount(
|
||||
provisionMessage.number,
|
||||
provisionMessage.provisioningCode,
|
||||
provisionMessage.identityKeyPair,
|
||||
false
|
||||
);
|
||||
});
|
||||
}));
|
||||
} else {
|
||||
console.log('Unknown websocket message', request.path);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
<script type="text/javascript" src="../storage/devices.js" data-cover></script>
|
||||
<script type="text/javascript" src="../api.js"></script>
|
||||
<script type="text/javascript" src="../sendmessage.js" data-cover></script>
|
||||
<script type="text/javascript" src="../account_manager.js" data-></script>
|
||||
|
||||
<script type="text/javascript" src="fake_api.js"></script>
|
||||
<script type="text/javascript" src="helpers_test.js"></script>
|
||||
|
|
Loading…
Reference in a new issue