Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32449164
D11341.1765364559.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
18 KB
Referenced Files
None
Subscribers
None
D11341.1765364559.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D11341: [web] Olm session creation between own devices
Attached
Detach File
Event Timeline
Log In to Comment