diff --git a/libtextsecure/account_manager.js b/libtextsecure/account_manager.js index c0e081087..80c53c824 100644 --- a/libtextsecure/account_manager.js +++ b/libtextsecure/account_manager.js @@ -60,11 +60,11 @@ // handle shorter than 32 bytes seeds const privKeyHexLength = 32 * 2; if (seedHex.length !== privKeyHexLength) { - seedHex = seedHex.concat(seedHex); + seedHex = seedHex.concat('0'.repeat(32)); seedHex = seedHex.substring(0, privKeyHexLength); } const seed = dcodeIO.ByteBuffer.wrap(seedHex, 'hex').toArrayBuffer(); - return libsignal.Curve.async.createKeyPair(seed); + return window.sessionGenerateKeyPair(seed); }; } else { generateKeypair = libsignal.KeyHelper.generateIdentityKeyPair; diff --git a/main.js b/main.js index f6f33a645..b3b7009c6 100644 --- a/main.js +++ b/main.js @@ -1178,6 +1178,42 @@ ipc.on('decrypt-lns-entry', (event, lnsName, ciphertext) => { decryptLns(event, lnsName, ciphertext); }); +async function sessionGenerateKeyPair(event, seed) { + const sodium = await getSodium(); + + try { + const ed25519KeyPair = sodium.crypto_sign_seed_keypair( + new Uint8Array(seed) + ); + const x25519PublicKey = sodium.crypto_sign_ed25519_pk_to_curve25519( + ed25519KeyPair.publicKey + ); + // prepend version byte (coming from `processKeys(raw_keys)`) + const origPub = new Uint8Array(x25519PublicKey); + const prependedX25519PublicKey = new Uint8Array(33); + prependedX25519PublicKey.set(origPub, 1); + prependedX25519PublicKey[0] = 5; + const x25519SecretKey = sodium.crypto_sign_ed25519_sk_to_curve25519( + ed25519KeyPair.privateKey + ); + + // prepend with 05 the public key + const x25519KeyPair = { + pubKey: prependedX25519PublicKey.buffer, + privKey: x25519SecretKey.buffer, + }; + + // null as first parameter to indivate no error + event.reply('generate-keypair-seed-response', null, x25519KeyPair); + } catch (err) { + event.reply('generate-keypair-seed-response', err); + } +} + +ipc.on('generate-keypair-seed', (event, seed) => { + sessionGenerateKeyPair(event, seed); +}); + ipc.on('set-auto-update-setting', (event, enabled) => { userConfig.set('autoUpdate', !!enabled); diff --git a/preload.js b/preload.js index 107430240..52779f149 100644 --- a/preload.js +++ b/preload.js @@ -118,7 +118,7 @@ const localeMessages = ipc.sendSync('locale-data'); window.blake2b = input => new Promise((resolve, reject) => { - ipc.once('blake2b-digest-response', (event, error, res) => { + ipc.once('blake2b-digest-response', (_, error, res) => { // eslint-disable-next-line no-unused-expressions error ? reject(error) : resolve(res); }); @@ -128,7 +128,7 @@ window.blake2b = input => window.decryptLnsEntry = (key, value) => new Promise((resolve, reject) => { - ipc.once('decrypt-lns-response', (event, error, res) => { + ipc.once('decrypt-lns-response', (_, error, res) => { // eslint-disable-next-line no-unused-expressions error ? reject(error) : resolve(res); }); @@ -136,6 +136,16 @@ window.decryptLnsEntry = (key, value) => ipc.send('decrypt-lns-entry', key, value); }); +window.sessionGenerateKeyPair = seed => + new Promise((resolve, reject) => { + ipc.once('generate-keypair-seed-response', (_, error, res) => { + // eslint-disable-next-line no-unused-expressions + error ? reject(error) : resolve(res); + }); + + ipc.send('generate-keypair-seed', seed); + }); + window.updateZoomFactor = () => { const zoomFactor = window.getSettingValue('zoom-factor-setting') || 100; window.setZoomFactor(zoomFactor / 100); diff --git a/ts/components/session/RegistrationTabs.tsx b/ts/components/session/RegistrationTabs.tsx index ec81b6605..e688f2bde 100644 --- a/ts/components/session/RegistrationTabs.tsx +++ b/ts/components/session/RegistrationTabs.tsx @@ -174,14 +174,14 @@ export class RegistrationTabs extends React.Component<{}, State> { // handle shorter than 32 bytes seeds const privKeyHexLength = 32 * 2; if (seedHex.length !== privKeyHexLength) { - seedHex = seedHex.concat(seedHex); + seedHex = seedHex.concat('0'.repeat(32)); seedHex = seedHex.substring(0, privKeyHexLength); } const seed = window.dcodeIO.ByteBuffer.wrap( seedHex, 'hex' ).toArrayBuffer(); - const keyPair = await window.libsignal.Curve.async.createKeyPair(seed); + const keyPair = await window.sessionGenerateKeyPair(seed); const hexGeneratedPubKey = StringUtils.decode(keyPair.pubKey, 'hex'); this.setState({ @@ -297,9 +297,7 @@ export class RegistrationTabs extends React.Component<{}, State> { {this.renderRegistrationContent()} { - this.onCompleteSignUpClick(); - }} + onClick={this.onCompleteSignUpClick} buttonType={SessionButtonType.Brand} buttonColor={SessionButtonColor.Green} text={window.i18n('getStarted')} diff --git a/ts/window.d.ts b/ts/window.d.ts index 44c5f8be7..adf623f13 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -99,5 +99,6 @@ declare global { GroupBuffer: any; SwarmPolling: SwarmPolling; owsDesktopApp: any; + sessionGenerateKeyPair: (seed: ArrayBuffer) => Promise<{ pubKey: ArrayBufferLike; privKey: ArrayBufferLike; }>; } }