From bde27d94811b223657d1d7f381c634028d9eae70 Mon Sep 17 00:00:00 2001 From: Mikunj Date: Fri, 5 Jun 2020 12:06:18 +1000 Subject: [PATCH 01/10] Fix create closed group overflow on small screen --- stylesheets/_session.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/stylesheets/_session.scss b/stylesheets/_session.scss index 150ffb7ee..49e979638 100644 --- a/stylesheets/_session.scss +++ b/stylesheets/_session.scss @@ -1589,6 +1589,7 @@ input { @media (max-height: 804px) { &__container { overflow-y: visible; + max-height: none; } } } From 1076c5545fb3bb8b7e216faec7c4f8375e311886 Mon Sep 17 00:00:00 2001 From: Mikunj Date: Thu, 16 Jul 2020 16:14:21 +1000 Subject: [PATCH 02/10] Change version to 1.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5d40d6722..06f52c276 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "session-messenger-desktop", "productName": "Session", "description": "Private messaging from your desktop", - "version": "2.0.0", + "version": "1.1.0", "license": "GPL-3.0", "author": { "name": "Loki Project", From 0c7cc7d24f0c19cd2229328406618d0697c99266 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 29 Oct 2020 13:33:26 +1100 Subject: [PATCH 03/10] cleanup account_manager unused code --- js/background.js | 4 - libtextsecure/account_manager.js | 114 --------------------- libtextsecure/test/account_manager_test.js | 16 --- test/crypto_test.js | 37 ------- 4 files changed, 171 deletions(-) diff --git a/js/background.js b/js/background.js index b89561c0e..1fc6005ac 100644 --- a/js/background.js +++ b/js/background.js @@ -221,10 +221,6 @@ // start a background worker for ecc textsecure.startWorker('js/libsignal-protocol-worker.js'); Whisper.KeyChangeListener.init(textsecure.storage.protocol); - textsecure.storage.protocol.on('removePreKey', () => { - getAccountManager().refreshPreKeys(); - }); - let messageReceiver; window.getSocketStatus = () => { if (messageReceiver) { diff --git a/libtextsecure/account_manager.js b/libtextsecure/account_manager.js index b30778621..c0e081087 100644 --- a/libtextsecure/account_manager.js +++ b/libtextsecure/account_manager.js @@ -7,7 +7,6 @@ lokiFileServerAPI, mnemonic, btoa, - Signal, getString, Event, dcodeIO, @@ -48,60 +47,6 @@ AccountManager.prototype = new textsecure.EventTarget(); AccountManager.prototype.extend({ constructor: AccountManager, - requestVoiceVerification(number) {}, - requestSMSVerification(number) {}, - async encryptDeviceName(name, providedIdentityKey) { - if (!name) { - return null; - } - const identityKey = - providedIdentityKey || - (await textsecure.storage.protocol.getIdentityKeyPair()); - if (!identityKey) { - throw new Error( - 'Identity key was not provided and is not in database!' - ); - } - const encrypted = await Signal.Crypto.encryptDeviceName( - name, - identityKey.pubKey - ); - - const proto = new textsecure.protobuf.DeviceName(); - proto.ephemeralPublic = encrypted.ephemeralPublic; - proto.syntheticIv = encrypted.syntheticIv; - proto.ciphertext = encrypted.ciphertext; - - const arrayBuffer = proto.encode().toArrayBuffer(); - return Signal.Crypto.arrayBufferToBase64(arrayBuffer); - }, - async decryptDeviceName(base64) { - const identityKey = await textsecure.storage.protocol.getIdentityKeyPair(); - - const arrayBuffer = Signal.Crypto.base64ToArrayBuffer(base64); - const proto = textsecure.protobuf.DeviceName.decode(arrayBuffer); - const encrypted = { - ephemeralPublic: proto.ephemeralPublic.toArrayBuffer(), - syntheticIv: proto.syntheticIv.toArrayBuffer(), - ciphertext: proto.ciphertext.toArrayBuffer(), - }; - - const name = await Signal.Crypto.decryptDeviceName( - encrypted, - identityKey.privKey - ); - - return name; - }, - async maybeUpdateDeviceName() { - throw new Error('Signal method called: maybeUpdateDeviceName'); - }, - async deviceNameIsEncrypted() { - await textsecure.storage.user.setDeviceNameEncrypted(); - }, - async maybeDeleteSignalingKey() { - throw new Error('Signal method called: maybeDeleteSignalingKey'); - }, registerSingleDevice(mnemonic, mnemonicLanguage, profileName) { const createAccount = this.createAccount.bind(this); const clearSessionsAndPreKeys = this.clearSessionsAndPreKeys.bind(this); @@ -140,65 +85,6 @@ ) ); }, - async addMockContact(doSave) { - if (doSave === undefined) { - // eslint-disable-next-line no-param-reassign - doSave = true; - } - const keyPair = await libsignal.KeyHelper.generateIdentityKeyPair(); - const pubKey = StringView.arrayBufferToHex(keyPair.pubKey); - const privKey = StringView.arrayBufferToHex(keyPair.privKey); - log.info(`contact pubkey ${pubKey}`); - log.info(`contact privkey ${privKey}`); - const signedKeyId = Math.floor(Math.random() * 1000 + 1); - - const signedPreKey = await libsignal.KeyHelper.generateSignedPreKey( - keyPair, - signedKeyId - ); - const contactSignedPreKey = { - publicKey: signedPreKey.keyPair.pubKey, - signature: signedPreKey.signature, - keyId: signedPreKey.keyId, - }; - if (doSave) { - await textsecure.storage.protocol.storeContactSignedPreKey( - pubKey, - contactSignedPreKey - ); - } else { - log.info( - `signed prekey: - ${StringView.arrayBufferToHex(contactSignedPreKey.publicKey)}` - ); - log.info( - `signature: - ${StringView.arrayBufferToHex(contactSignedPreKey.signature)}` - ); - } - - for (let keyId = 0; keyId < 10; keyId += 1) { - const preKey = await libsignal.KeyHelper.generatePreKey(keyId); - if (doSave) { - await textsecure.storage.protocol.storeContactPreKey(pubKey, { - publicKey: preKey.keyPair.pubKey, - keyId, - }); - } else { - log.info( - `signed prekey: - ${StringView.arrayBufferToHex(preKey.keyPair.pubKey)}` - ); - } - } - log.info('Added mock contact'); - }, - registerSecondDevice(setProvisioningUrl, confirmNumber, progressCallback) { - throw new Error( - 'account_manager: registerSecondDevice has not been implemented!' - ); - }, - refreshPreKeys() {}, rotateSignedPreKey() { return this.queueTask(() => { const signedKeyId = textsecure.storage.get('signedKeyId', 1); diff --git a/libtextsecure/test/account_manager_test.js b/libtextsecure/test/account_manager_test.js index 7f70ea08d..f73425db6 100644 --- a/libtextsecure/test/account_manager_test.js +++ b/libtextsecure/test/account_manager_test.js @@ -29,22 +29,6 @@ describe('AccountManager', () => { window.textsecure.storage.protocol = originalProtocolStorage; }); - describe('encrypted device name', () => { - it('roundtrips', async () => { - const deviceName = 'v2.5.0 on Ubunto 20.04'; - const encrypted = await accountManager.encryptDeviceName(deviceName); - assert.strictEqual(typeof encrypted, 'string'); - const decrypted = await accountManager.decryptDeviceName(encrypted); - - assert.strictEqual(decrypted, deviceName); - }); - - it('handles null deviceName', async () => { - const encrypted = await accountManager.encryptDeviceName(null); - assert.strictEqual(encrypted, null); - }); - }); - it('keeps three confirmed keys even if over a week old', () => { const now = Date.now(); signedPreKeys = [ diff --git a/test/crypto_test.js b/test/crypto_test.js index 44eb42877..a5a6b0ac1 100644 --- a/test/crypto_test.js +++ b/test/crypto_test.js @@ -110,43 +110,6 @@ describe('Crypto', () => { }); }); - describe('encrypted device name', () => { - it('roundtrips', async () => { - const deviceName = 'v1.19.0 on Windows 10'; - const identityKey = await libsignal.KeyHelper.generateIdentityKeyPair(); - - const encrypted = await Signal.Crypto.encryptDeviceName( - deviceName, - identityKey.pubKey - ); - const decrypted = await Signal.Crypto.decryptDeviceName( - encrypted, - identityKey.privKey - ); - - assert.strictEqual(decrypted, deviceName); - }); - - it('fails if iv is changed', async () => { - const deviceName = 'v1.19.0 on Windows 10'; - const identityKey = await libsignal.KeyHelper.generateIdentityKeyPair(); - - const encrypted = await Signal.Crypto.encryptDeviceName( - deviceName, - identityKey.pubKey - ); - encrypted.syntheticIv = Signal.Crypto.getRandomBytes(16); - try { - await Signal.Crypto.decryptDeviceName(encrypted, identityKey.privKey); - } catch (error) { - assert.strictEqual( - error.message, - 'decryptDeviceName: synthetic IV did not match' - ); - } - }); - }); - describe('attachment encryption', () => { it('roundtrips', async () => { const staticKeyPair = await libsignal.KeyHelper.generateIdentityKeyPair(); From 6dc3582a1d60b147eeac88ddd01b0056dbe578ba Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 29 Oct 2020 13:33:51 +1100 Subject: [PATCH 04/10] move to new identity key mechanism MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit now we do as followed: • Generate 16 bytes of random data • Add 16 bytes of zeros • Use the 16 bytes of random + 16 bytes of zeros to generate an ED25519 key pair • Convert the ED25519 key pair to an X25519 key pair All of this is happening with libsodiumm called over IPC --- libtextsecure/account_manager.js | 4 +-- main.js | 36 ++++++++++++++++++++++ preload.js | 14 +++++++-- ts/components/session/RegistrationTabs.tsx | 8 ++--- ts/window.d.ts | 1 + 5 files changed, 54 insertions(+), 9 deletions(-) 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 4bebeafc9..6ee2f53fb 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 86eca4ccc..e2e5d2e3c 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 51387b0d3..9e9429512 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; }>; } } From 43b335406f77a06c3fe42820d460470a4a97c607 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 30 Oct 2020 09:38:27 +1100 Subject: [PATCH 05/10] store the ed25519KeyPair temp key too on storage under 'identityKey' --- main.js | 1 + ts/window.d.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/main.js b/main.js index 6ee2f53fb..2c94986f5 100644 --- a/main.js +++ b/main.js @@ -1201,6 +1201,7 @@ async function sessionGenerateKeyPair(event, seed) { const x25519KeyPair = { pubKey: prependedX25519PublicKey.buffer, privKey: x25519SecretKey.buffer, + ed25519KeyPair, }; // null as first parameter to indivate no error diff --git a/ts/window.d.ts b/ts/window.d.ts index 9e9429512..b0e549396 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -99,6 +99,8 @@ declare global { GroupBuffer: any; SwarmPolling: SwarmPolling; owsDesktopApp: any; - sessionGenerateKeyPair: (seed: ArrayBuffer) => Promise<{ pubKey: ArrayBufferLike; privKey: ArrayBufferLike; }>; + sessionGenerateKeyPair: ( + seed: ArrayBuffer + ) => Promise<{ pubKey: ArrayBufferLike; privKey: ArrayBufferLike }>; } } From e5ef8dc2547e75ab0d38a32091351874cf1110c6 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 10 Nov 2020 15:17:03 +1100 Subject: [PATCH 06/10] Bump to v1.4.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4626af6d0..0f19dade5 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "session-messenger-desktop", "productName": "Session", "description": "Private messaging from your desktop", - "version": "1.4.0", + "version": "1.4.1", "license": "GPL-3.0", "author": { "name": "Loki Project", From c736023c883cf49449c33b9ad30737d7c1d4849a Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 24 Nov 2020 09:05:45 +1100 Subject: [PATCH 07/10] enable file onion request v2 in lokiFeatureFlags --- preload.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/preload.js b/preload.js index 69595f605..3b0ecd328 100644 --- a/preload.js +++ b/preload.js @@ -461,7 +461,7 @@ window.lokiFeatureFlags = { useOnionRequests: true, useOnionRequestsV2: true, useFileOnionRequests: true, - useFileOnionRequestsV2: false, // more compact encoding of files in response + useFileOnionRequestsV2: true, // more compact encoding of files in response enableSenderKeys: true, onionRequestHops: 3, debugMessageLogs: process.env.ENABLE_MESSAGE_LOGS, From b845b90e80ea4c84b184f9933b9b4522942b4052 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 24 Nov 2020 09:08:34 +1100 Subject: [PATCH 08/10] Bump to v1.4.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f19dade5..7f63f48ff 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "session-messenger-desktop", "productName": "Session", "description": "Private messaging from your desktop", - "version": "1.4.1", + "version": "1.4.2", "license": "GPL-3.0", "author": { "name": "Loki Project", From cc049065daf664da85bf98333284a53926a663b9 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 24 Nov 2020 11:46:58 +1100 Subject: [PATCH 09/10] do not use v3 for live.apns.getsession.org PN calls --- ts/session/snode_api/onions.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ts/session/snode_api/onions.ts b/ts/session/snode_api/onions.ts index 7adfc7964..35f72633b 100644 --- a/ts/session/snode_api/onions.ts +++ b/ts/session/snode_api/onions.ts @@ -142,7 +142,8 @@ async function buildOnionCtxs( if (relayingToFinalDestination && fileServerOptions) { let target = useV2 ? '/loki/v2/lsrpc' : '/loki/v1/lsrpc'; - if (window.lokiFeatureFlags.useFileOnionRequestsV2) { + const isCallToPn = fileServerOptions?.host === 'live.apns.getsession.org'; + if (!isCallToPn && window.lokiFeatureFlags.useFileOnionRequestsV2) { target = '/loki/v3/lsrpc'; } From 155ba35d00d89bc792a0da7305dcf7c5420ae426 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 24 Nov 2020 14:13:43 +1100 Subject: [PATCH 10/10] allow set-end for DISPLAY and LANG call on pull request --- .github/workflows/pull-request.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index c03f7a22d..2fe2119e0 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -75,8 +75,10 @@ jobs: sudo apt-get install -y hunspell-en-us sudo locale-gen en_US.UTF-8 sudo dpkg-reconfigure locales + echo "::stop-commands::`echo -n ${{ github.token }} | sha256sum | head -c 64`" echo ::set-env name=DISPLAY:::9.0 echo ::set-env name=LANG::en_US.UTF-8 + echo "::`echo -n ${{ github.token }} | sha256sum | head -c 64`::" - name: Test uses: GabrielBB/xvfb-action@v1.0