diff --git a/lib/types/identity-service-types.js b/lib/types/identity-service-types.js --- a/lib/types/identity-service-types.js +++ b/lib/types/identity-service-types.js @@ -90,4 +90,15 @@ +username: string, }; +export type IdentityDeviceKeyUpload = { + +keyPayload: string, + +keyPayloadSignature: string, + +contentPrekey: string, + +contentPrekeySignature: string, + +notifPrekey: string, + +notifPrekeySignature: string, + +contentOneTimeKeys: $ReadOnlyArray, + +notifOneTimeKeys: $ReadOnlyArray, +}; + export const ONE_TIME_KEYS_NUMBER = 10; diff --git a/web/account/account-hooks.js b/web/account/account-hooks.js --- a/web/account/account-hooks.js +++ b/web/account/account-hooks.js @@ -20,7 +20,9 @@ OLMIdentityKeys, NotificationsOlmDataType, } from 'lib/types/crypto-types.js'; +import { type IdentityDeviceKeyUpload } from 'lib/types/identity-service-types.js'; import type { OlmSessionInitializationInfo } from 'lib/types/request-types.js'; +import { retrieveAccountKeysSet } from 'lib/utils/olm-utils.js'; import { useDispatch } from 'lib/utils/redux-utils.js'; import { @@ -149,10 +151,8 @@ const getOrCreateCryptoStore = useGetOrCreateCryptoStore(); return React.useCallback(async () => { - const { primaryAccount, primaryIdentityKeys, notificationIdentityKeys } = - await getOrCreateCryptoStore(); - - await initOlm(); + const [{ primaryAccount, primaryIdentityKeys, notificationIdentityKeys }] = + await Promise.all([getOrCreateCryptoStore(), initOlm()]); const primaryOLMAccount = new olm.Account(); primaryOLMAccount.unpickle( primaryAccount.picklingKey, @@ -174,6 +174,70 @@ }, [getOrCreateCryptoStore]); } +function useGetDeviceKeyUpload(): () => Promise { + const getOrCreateCryptoStore = useGetOrCreateCryptoStore(); + // `getSignedIdentityKeysBlob()` will initialize OLM, so no need to do it + // again + const getSignedIdentityKeysBlob = useGetSignedIdentityKeysBlob(); + const dispatch = useDispatch(); + + return React.useCallback(async () => { + const [signedIdentityKeysBlob, cryptoStore] = await Promise.all([ + getSignedIdentityKeysBlob(), + getOrCreateCryptoStore(), + ]); + + const primaryOLMAccount = new olm.Account(); + const notificationOLMAccount = new olm.Account(); + primaryOLMAccount.unpickle( + cryptoStore.primaryAccount.picklingKey, + cryptoStore.primaryAccount.pickledAccount, + ); + notificationOLMAccount.unpickle( + cryptoStore.notificationAccount.picklingKey, + cryptoStore.notificationAccount.pickledAccount, + ); + + const primaryAccountKeysSet = retrieveAccountKeysSet(primaryOLMAccount); + const notificationAccountKeysSet = retrieveAccountKeysSet( + notificationOLMAccount, + ); + + const pickledPrimaryAccount = primaryOLMAccount.pickle( + cryptoStore.primaryAccount.picklingKey, + ); + const pickledNotificationAccount = notificationOLMAccount.pickle( + cryptoStore.notificationAccount.picklingKey, + ); + + const updatedCryptoStore = { + primaryAccount: { + picklingKey: cryptoStore.primaryAccount.picklingKey, + pickledAccount: pickledPrimaryAccount, + }, + primaryIdentityKeys: cryptoStore.primaryIdentityKeys, + notificationAccount: { + picklingKey: cryptoStore.notificationAccount.picklingKey, + pickledAccount: pickledNotificationAccount, + }, + notificationIdentityKeys: cryptoStore.notificationIdentityKeys, + }; + + dispatch({ type: setCryptoStore, payload: updatedCryptoStore }); + + return { + keyPayload: signedIdentityKeysBlob.payload, + keyPayloadSignature: signedIdentityKeysBlob.signature, + contentPrekey: primaryAccountKeysSet.prekey, + contentPrekeySignature: primaryAccountKeysSet.prekeySignature, + notifPrekey: notificationAccountKeysSet.prekey, + notifPrekeySignature: notificationAccountKeysSet.prekeySignature, + contentOneTimeKeys: primaryAccountKeysSet.oneTimeKeys, + notifOneTimeKeys: notificationAccountKeysSet.oneTimeKeys, + }; + }, [dispatch, getOrCreateCryptoStore, getSignedIdentityKeysBlob]); +} + function OlmSessionCreatorProvider(props: Props): React.Node { const getOrCreateCryptoStore = useGetOrCreateCryptoStore(); const currentCryptoStore = useSelector(state => state.cryptoStore); @@ -370,4 +434,5 @@ OlmSessionCreatorProvider, useWebNotificationsSessionCreator, GetOrCreateCryptoStoreProvider, + useGetDeviceKeyUpload, };