Page MenuHomePhorge

D11341.1765364559.diff
No OneTemporary

Size
18 KB
Referenced Files
None
Subscribers
None

D11341.1765364559.diff

diff --git a/lib/utils/crypto-utils.js b/lib/utils/crypto-utils.js
--- a/lib/utils/crypto-utils.js
+++ b/lib/utils/crypto-utils.js
@@ -3,13 +3,21 @@
import t from 'tcomb';
import { type TInterface } from 'tcomb';
+import { getConfig } from './config.js';
import { primaryIdentityPublicKeyRegex } from './siwe-utils.js';
import { tRegex, tShape } from './validation-utils.js';
+import type { AuthMetadata } from '../shared/identity-client-context.js';
+import type { ClientMessageToDevice } from '../tunnelbroker/tunnelbroker-context.js';
import type {
IdentityKeysBlob,
OLMIdentityKeys,
SignedIdentityKeysBlob,
} from '../types/crypto-types';
+import type { IdentityServiceClient } from '../types/identity-service-types';
+import {
+ type OutboundSessionCreation,
+ peerToPeerMessageTypes,
+} from '../types/tunnelbroker/peer-to-peer-message-types.js';
const signedIdentityKeysBlobValidator: TInterface<SignedIdentityKeysBlob> =
tShape({
@@ -27,4 +35,82 @@
notificationIdentityPublicKeys: olmIdentityKeysValidator,
});
-export { signedIdentityKeysBlobValidator, identityKeysBlobValidator };
+async function getContentSigningKey(): Promise<string> {
+ const { olmAPI } = getConfig();
+ await olmAPI.initializeCryptoAccount();
+ const {
+ primaryIdentityPublicKeys: { ed25519 },
+ } = await olmAPI.getUserPublicKey();
+ return ed25519;
+}
+
+async function createOlmSessionsWithOwnDevices(
+ authMetadata: AuthMetadata,
+ identityClient: IdentityServiceClient,
+ sendMessage: (message: ClientMessageToDevice) => Promise<void>,
+): Promise<void> {
+ const { olmAPI } = getConfig();
+ const { userID, deviceID, accessToken } = authMetadata;
+ await olmAPI.initializeCryptoAccount();
+
+ if (!userID || !deviceID || !accessToken) {
+ throw new Error('CommServicesAuthMetadata is missing');
+ }
+
+ const keysResponse = await identityClient.getOutboundKeysForUser(userID);
+
+ for (const deviceKeys of keysResponse) {
+ const { keys } = deviceKeys;
+ if (!keys) {
+ console.log(`Keys missing for device ${deviceKeys.deviceID}`);
+ continue;
+ }
+
+ const { primaryIdentityPublicKeys } = keys.identityKeysBlob;
+
+ if (primaryIdentityPublicKeys.ed25519 === deviceID) {
+ continue;
+ }
+ const recipientDeviceID = primaryIdentityPublicKeys.ed25519;
+
+ if (!keys.contentInitializationInfo.oneTimeKey) {
+ console.log(`One-time key is missing for device ${recipientDeviceID}`);
+ continue;
+ }
+ try {
+ const encryptedContent = await olmAPI.contentOutboundSessionCreator(
+ primaryIdentityPublicKeys,
+ keys.contentInitializationInfo,
+ );
+
+ const sessionCreationMessage: OutboundSessionCreation = {
+ type: peerToPeerMessageTypes.OUTBOUND_SESSION_CREATION,
+ senderInfo: {
+ userID,
+ deviceID,
+ },
+ encryptedContent,
+ };
+
+ await sendMessage({
+ deviceID: recipientDeviceID,
+ payload: JSON.stringify(sessionCreationMessage),
+ });
+ console.log(
+ `Request to create a session with device ${recipientDeviceID} sent.`,
+ );
+ } catch (e) {
+ console.log(
+ 'Error creating outbound session with ' +
+ `device ${recipientDeviceID}: ${e.message}`,
+ );
+ }
+ }
+}
+
+export {
+ signedIdentityKeysBlobValidator,
+ identityKeysBlobValidator,
+ getContentSigningKey,
+ createOlmSessionsWithOwnDevices,
+};
diff --git a/native/account/siwe-panel.react.js b/native/account/siwe-panel.react.js
--- a/native/account/siwe-panel.react.js
+++ b/native/account/siwe-panel.react.js
@@ -18,6 +18,7 @@
import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
import type { SIWEWebViewMessage, SIWEResult } from 'lib/types/siwe-types.js';
import { useLegacyAshoatKeyserverCall } from 'lib/utils/action-utils.js';
+import { getContentSigningKey } from 'lib/utils/crypto-utils.js';
import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js';
import { usingCommServicesAccessToken } from 'lib/utils/services-utils.js';
@@ -26,7 +27,6 @@
import type { BottomSheetRef } from '../types/bottom-sheet.js';
import { UnknownErrorAlertDetails } from '../utils/alert-messages.js';
import Alert from '../utils/alert.js';
-import { getContentSigningKey } from '../utils/crypto-utils.js';
import { defaultLandingURLPrefix } from '../utils/url-utils.js';
const commSIWE = `${defaultLandingURLPrefix}/siwe`;
diff --git a/native/backup/use-client-backup.js b/native/backup/use-client-backup.js
--- a/native/backup/use-client-backup.js
+++ b/native/backup/use-client-backup.js
@@ -3,11 +3,11 @@
import * as React from 'react';
import { isLoggedIn } from 'lib/selectors/user-selectors.js';
+import { getContentSigningKey } from 'lib/utils/crypto-utils.js';
import { fetchNativeKeychainCredentials } from '../account/native-credentials.js';
import { commCoreModule } from '../native-modules.js';
import { useSelector } from '../redux/redux-utils.js';
-import { getContentSigningKey } from '../utils/crypto-utils.js';
type ClientBackup = {
+uploadBackupProtocol: () => Promise<void>,
diff --git a/native/identity-service/identity-service-context-provider.react.js b/native/identity-service/identity-service-context-provider.react.js
--- a/native/identity-service/identity-service-context-provider.react.js
+++ b/native/identity-service/identity-service-context-provider.react.js
@@ -25,12 +25,12 @@
deviceOlmInboundKeysValidator,
userDeviceOlmInboundKeysValidator,
} from 'lib/types/identity-service-types.js';
+import { getContentSigningKey } from 'lib/utils/crypto-utils.js';
import { assertWithValidator } from 'lib/utils/validation-utils.js';
import { getCommServicesAuthMetadataEmitter } from '../event-emitters/csa-auth-metadata-emitter.js';
import { commCoreModule, commRustModule } from '../native-modules.js';
import { useSelector } from '../redux/redux-utils.js';
-import { getContentSigningKey } from '../utils/crypto-utils.js';
type Props = {
+children: React.Node,
diff --git a/native/profile/tunnelbroker-menu.react.js b/native/profile/tunnelbroker-menu.react.js
--- a/native/profile/tunnelbroker-menu.react.js
+++ b/native/profile/tunnelbroker-menu.react.js
@@ -5,24 +5,25 @@
import { Text, View } from 'react-native';
import { ScrollView } from 'react-native-gesture-handler';
+import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
import { useTunnelbroker } from 'lib/tunnelbroker/tunnelbroker-context.js';
import type { TunnelbrokerMessage } from 'lib/types/tunnelbroker/messages.js';
import {
type EncryptedMessage,
peerToPeerMessageTypes,
} from 'lib/types/tunnelbroker/peer-to-peer-message-types.js';
+import {
+ createOlmSessionsWithOwnDevices,
+ getContentSigningKey,
+} from 'lib/utils/crypto-utils.js';
import type { ProfileNavigationProp } from './profile.react.js';
import Button from '../components/button.react.js';
import TextInput from '../components/text-input.react.js';
-import { commCoreModule } from '../native-modules.js';
+import { olmAPI } from '../crypto/olm-api.js';
import type { NavigationRoute } from '../navigation/route-names.js';
import { useSelector } from '../redux/redux-utils.js';
import { useColors, useStyles } from '../themes/colors.js';
-import {
- createOlmSessionsWithOwnDevices,
- getContentSigningKey,
-} from '../utils/crypto-utils.js';
type Props = {
+navigation: ProfileNavigationProp<'TunnelbrokerMenu'>,
@@ -35,6 +36,7 @@
const currentUserID = useSelector(
state => state.currentUserInfo && state.currentUserInfo.id,
);
+ const identityContext = React.useContext(IdentityClientContext);
const { connected, addListener, sendMessage, removeListener } =
useTunnelbroker();
@@ -61,20 +63,28 @@
}, [message, recipient, sendMessage]);
const onCreateSessions = React.useCallback(async () => {
+ if (!identityContext) {
+ return;
+ }
+ const authMetadata = await identityContext.getAuthMetadata();
try {
- await createOlmSessionsWithOwnDevices(sendMessage);
+ await createOlmSessionsWithOwnDevices(
+ authMetadata,
+ identityContext.identityClient,
+ sendMessage,
+ );
} catch (e) {
console.log(`Error creating olm sessions with own devices: ${e.message}`);
}
- }, [sendMessage]);
+ }, [identityContext, sendMessage]);
const onSendEncryptedMessage = React.useCallback(async () => {
try {
if (!currentUserID) {
return;
}
- await commCoreModule.initializeCryptoAccount();
- const encrypted = await commCoreModule.encrypt(
+ await olmAPI.initializeCryptoAccount();
+ const encrypted = await olmAPI.encrypt(
`Encrypted message to ${recipient}`,
recipient,
);
diff --git a/native/qr-code/qr-code-screen.react.js b/native/qr-code/qr-code-screen.react.js
--- a/native/qr-code/qr-code-screen.react.js
+++ b/native/qr-code/qr-code-screen.react.js
@@ -15,6 +15,7 @@
NonceChallenge,
SignedMessage,
} from 'lib/types/identity-service-types.js';
+import { getContentSigningKey } from 'lib/utils/crypto-utils.js';
import type { QRCodeSignInNavigationProp } from './qr-code-sign-in-navigator.react.js';
import {
@@ -26,7 +27,6 @@
import { useStyles } from '../themes/colors.js';
import * as AES from '../utils/aes-crypto-module.js';
import Alert from '../utils/alert.js';
-import { getContentSigningKey } from '../utils/crypto-utils.js';
type QRCodeScreenProps = {
+navigation: QRCodeSignInNavigationProp<'QRCodeScreen'>,
diff --git a/native/utils/crypto-utils.js b/native/utils/crypto-utils.js
--- a/native/utils/crypto-utils.js
+++ b/native/utils/crypto-utils.js
@@ -1,18 +1,9 @@
// @flow
-import { type ClientMessageToDevice } from 'lib/tunnelbroker/tunnelbroker-context.js';
-import type {
- IdentityKeysBlob,
- OLMIdentityKeys,
-} from 'lib/types/crypto-types.js';
-import type { OutboundKeyInfoResponse } from 'lib/types/identity-service-types';
+import type { OLMIdentityKeys } from 'lib/types/crypto-types.js';
import type { OlmSessionInitializationInfo } from 'lib/types/request-types.js';
-import {
- type OutboundSessionCreation,
- peerToPeerMessageTypes,
-} from 'lib/types/tunnelbroker/peer-to-peer-message-types.js';
-import { commCoreModule, commRustModule } from '../native-modules.js';
+import { commCoreModule } from '../native-modules.js';
function nativeNotificationsSessionCreator(
notificationsIdentityKeys: OLMIdentityKeys,
@@ -30,14 +21,6 @@
);
}
-async function getContentSigningKey(): Promise<string> {
- await commCoreModule.initializeCryptoAccount();
- const {
- primaryIdentityPublicKeys: { ed25519 },
- } = await commCoreModule.getUserPublicKey();
- return ed25519;
-}
-
function nativeOutboundContentSessionCreator(
contentIdentityKeys: OLMIdentityKeys,
contentInitializationInfo: OlmSessionInitializationInfo,
@@ -58,75 +41,7 @@
);
}
-async function createOlmSessionsWithOwnDevices(
- sendMessage: (message: ClientMessageToDevice) => Promise<void>,
-): Promise<void> {
- const authMetadata = await commCoreModule.getCommServicesAuthMetadata();
- const { userID, deviceID, accessToken } = authMetadata;
- if (!userID || !deviceID || !accessToken) {
- throw new Error('CommServicesAuthMetadata is missing');
- }
-
- await commCoreModule.initializeCryptoAccount();
- const keysResponse = await commRustModule.getOutboundKeysForUser(
- userID,
- deviceID,
- accessToken,
- userID,
- );
-
- const outboundKeys: OutboundKeyInfoResponse[] = JSON.parse(keysResponse);
-
- for (const deviceKeys: OutboundKeyInfoResponse of outboundKeys) {
- const keysPayload: IdentityKeysBlob = JSON.parse(deviceKeys.payload);
-
- if (keysPayload.primaryIdentityPublicKeys.ed25519 === deviceID) {
- continue;
- }
- const recipientDeviceID = keysPayload.primaryIdentityPublicKeys.ed25519;
- if (!deviceKeys.oneTimeContentPrekey) {
- console.log(`One-time key is missing for device ${recipientDeviceID}`);
- continue;
- }
- try {
- const encryptedContent = await nativeOutboundContentSessionCreator(
- keysPayload.primaryIdentityPublicKeys,
- {
- prekey: deviceKeys.contentPrekey,
- prekeySignature: deviceKeys.contentPrekeySignature,
- oneTimeKey: deviceKeys.oneTimeContentPrekey,
- },
- recipientDeviceID,
- );
-
- const sessionCreationMessage: OutboundSessionCreation = {
- type: peerToPeerMessageTypes.OUTBOUND_SESSION_CREATION,
- senderInfo: {
- userID,
- deviceID,
- },
- encryptedContent,
- };
-
- await sendMessage({
- deviceID: recipientDeviceID,
- payload: JSON.stringify(sessionCreationMessage),
- });
- console.log(
- `Request to create a session with device ${recipientDeviceID} sent.`,
- );
- } catch (e) {
- console.log(
- 'Error creating outbound session with ' +
- `device ${recipientDeviceID}: ${e.message}`,
- );
- }
- }
-}
-
export {
- getContentSigningKey,
nativeNotificationsSessionCreator,
- createOlmSessionsWithOwnDevices,
nativeOutboundContentSessionCreator,
};
diff --git a/web/settings/account-settings.react.js b/web/settings/account-settings.react.js
--- a/web/settings/account-settings.react.js
+++ b/web/settings/account-settings.react.js
@@ -7,7 +7,9 @@
import SWMansionIcon from 'lib/components/swmansion-icon.react.js';
import { useStringForUser } from 'lib/hooks/ens-cache.js';
import { accountHasPassword } from 'lib/shared/account-utils.js';
+import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
import { useTunnelbroker } from 'lib/tunnelbroker/tunnelbroker-context.js';
+import { createOlmSessionsWithOwnDevices } from 'lib/utils/crypto-utils.js';
import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js';
import css from './account-settings.css';
@@ -30,6 +32,7 @@
() => dispatchActionPromise(logOutActionTypes, sendLogoutRequest()),
[dispatchActionPromise, sendLogoutRequest],
);
+ const identityContext = React.useContext(IdentityClientContext);
const { pushModal, popModal } = useModalContext();
const showPasswordChangeModal = React.useCallback(
@@ -77,6 +80,22 @@
[addListener, popModal, pushModal, removeListener],
);
+ const onCreateOlmSessions = React.useCallback(async () => {
+ if (!identityContext) {
+ return;
+ }
+ const authMetadata = await identityContext.getAuthMetadata();
+ try {
+ await createOlmSessionsWithOwnDevices(
+ authMetadata,
+ identityContext.identityClient,
+ sendMessage,
+ );
+ } catch (e) {
+ console.log(`Error creating olm sessions with own devices: ${e.message}`);
+ }
+ }, [identityContext, sendMessage]);
+
const openBackupTestRestoreModal = React.useCallback(
() => pushModal(<BackupTestRestoreModal onClose={popModal} />),
[popModal, pushModal],
@@ -147,6 +166,12 @@
<p className={css.buttonText}>Show list</p>
</Button>
</li>
+ <li>
+ <span>Create session with own devices</span>
+ <Button variant="text" onClick={onCreateOlmSessions}>
+ <p className={css.buttonText}>Create</p>
+ </Button>
+ </li>
</ul>
</div>
</div>
diff --git a/web/settings/tunnelbroker-test.react.js b/web/settings/tunnelbroker-test.react.js
--- a/web/settings/tunnelbroker-test.react.js
+++ b/web/settings/tunnelbroker-test.react.js
@@ -4,11 +4,18 @@
import * as React from 'react';
import { type ClientMessageToDevice } from 'lib/tunnelbroker/tunnelbroker-context.js';
+import {
+ type EncryptedMessage,
+ peerToPeerMessageTypes,
+} from 'lib/types/tunnelbroker/peer-to-peer-message-types.js';
+import { getContentSigningKey } from 'lib/utils/crypto-utils.js';
import css from './tunnelbroker-test.css';
import Button from '../components/button.react.js';
+import { olmAPI } from '../crypto/olm-api.js';
import Input from '../modals/input.react.js';
import Modal from '../modals/modal.react.js';
+import { useSelector } from '../redux/redux-utils.js';
type Props = {
+sendMessage: (message: ClientMessageToDevice) => Promise<void>,
@@ -24,6 +31,10 @@
const recipientInput = React.useRef<?HTMLInputElement>(null);
const messageInput = React.useRef<?HTMLInputElement>(null);
+ const currentUserID = useSelector(
+ state => state.currentUserInfo && state.currentUserInfo.id,
+ );
+
const onSubmit = React.useCallback(
async (event: SyntheticEvent<HTMLButtonElement>) => {
event.preventDefault();
@@ -39,6 +50,42 @@
[message, recipient, sendMessage],
);
+ const onSubmitEncrypted = React.useCallback(
+ async (event: SyntheticEvent<HTMLButtonElement>) => {
+ event.preventDefault();
+
+ if (!currentUserID) {
+ return;
+ }
+
+ setLoading(true);
+ try {
+ await olmAPI.initializeCryptoAccount();
+ const encrypted = await olmAPI.encrypt(
+ `Encrypted message to ${recipient}`,
+ recipient,
+ );
+ const deviceID = await getContentSigningKey();
+ const encryptedMessage: EncryptedMessage = {
+ type: peerToPeerMessageTypes.ENCRYPTED_MESSAGE,
+ senderInfo: {
+ deviceID,
+ userID: currentUserID,
+ },
+ encryptedContent: encrypted,
+ };
+ await sendMessage({
+ deviceID: recipient,
+ payload: JSON.stringify(encryptedMessage),
+ });
+ } catch (e) {
+ setErrorMessage(e.message);
+ }
+ setLoading(false);
+ },
+ [currentUserID, recipient, sendMessage],
+ );
+
let errorMsg;
if (errorMessage) {
errorMsg = <div className={css.modalError}>{errorMessage}</div>;
@@ -86,6 +133,17 @@
</Button>
{errorMsg}
</div>
+ <div className={css.footer}>
+ <Button
+ type="submit"
+ variant="filled"
+ onClick={onSubmitEncrypted}
+ disabled={!recipient || loading}
+ >
+ Send Encrypted Message
+ </Button>
+ {errorMsg}
+ </div>
</div>
</Modal>
);

File Metadata

Mime Type
text/plain
Expires
Wed, Dec 10, 11:02 AM (17 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5863399
Default Alt Text
D11341.1765364559.diff (18 KB)

Event Timeline