diff --git a/lib/types/crypto-types.js b/lib/types/crypto-types.js
--- a/lib/types/crypto-types.js
+++ b/lib/types/crypto-types.js
@@ -123,8 +123,22 @@
   TEXT: 1,
 });
 
+export type ClientPublicKeys = {
+  +primaryIdentityPublicKeys: {
+    +ed25519: string,
+    +curve25519: string,
+  },
+  +notificationIdentityPublicKeys: {
+    +ed25519: string,
+    +curve25519: string,
+  },
+  +blobPayload: string,
+  +signature: string,
+};
+
 export type OlmAPI = {
   +initializeCryptoAccount: () => Promise<void>,
+  +getUserPublicKey: () => Promise<ClientPublicKeys>,
   +encrypt: (content: string, deviceID: string) => Promise<string>,
   +decrypt: (encryptedContent: string, deviceID: string) => Promise<string>,
   +contentInboundSessionCreator: (
diff --git a/lib/utils/__mocks__/config.js b/lib/utils/__mocks__/config.js
--- a/lib/utils/__mocks__/config.js
+++ b/lib/utils/__mocks__/config.js
@@ -14,6 +14,7 @@
   authoritativeKeyserverID: '123',
   olmAPI: {
     initializeCryptoAccount: jest.fn(),
+    getUserPublicKey: jest.fn(),
     encrypt: jest.fn(),
     decrypt: jest.fn(),
     contentInboundSessionCreator: jest.fn(),
diff --git a/native/crypto/olm-api.js b/native/crypto/olm-api.js
--- a/native/crypto/olm-api.js
+++ b/native/crypto/olm-api.js
@@ -6,7 +6,7 @@
   OneTimeKeysResultValues,
   OlmAPI,
   OLMIdentityKeys,
-} from 'lib/types/crypto-types';
+} from 'lib/types/crypto-types.js';
 import type { OlmSessionInitializationInfo } from 'lib/types/request-types.js';
 
 import { commCoreModule } from '../native-modules.js';
@@ -15,6 +15,7 @@
   async initializeCryptoAccount(): Promise<void> {
     await commCoreModule.initializeCryptoAccount();
   },
+  getUserPublicKey: commCoreModule.getUserPublicKey,
   encrypt: commCoreModule.encrypt,
   decrypt: commCoreModule.decrypt,
   async contentInboundSessionCreator(
diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js
--- a/native/schema/CommCoreModuleSchema.js
+++ b/native/schema/CommCoreModuleSchema.js
@@ -12,25 +12,16 @@
 import type { ClientDBReportStoreOperation } from 'lib/ops/report-store-ops.js';
 import type { ClientDBThreadStoreOperation } from 'lib/ops/thread-store-ops.js';
 import type { ClientDBUserStoreOperation } from 'lib/ops/user-store-ops';
-import type { OneTimeKeysResult, SignedPrekeys } from 'lib/types/crypto-types';
+import type {
+  OneTimeKeysResult,
+  SignedPrekeys,
+  ClientPublicKeys,
+} from 'lib/types/crypto-types';
 import type { ClientDBDraftStoreOperation } from 'lib/types/draft-types.js';
 import type { ClientDBMessageInfo } from 'lib/types/message-types.js';
 import type { ClientDBStore } from 'lib/types/store-ops-types';
 import type { ClientDBThreadInfo } from 'lib/types/thread-types.js';
 
-type ClientPublicKeys = {
-  +primaryIdentityPublicKeys: {
-    +ed25519: string,
-    +curve25519: string,
-  },
-  +notificationIdentityPublicKeys: {
-    +ed25519: string,
-    +curve25519: string,
-  },
-  +blobPayload: string,
-  +signature: string,
-};
-
 type CommServicesAuthMetadata = {
   +userID?: ?string,
   +deviceID?: ?string,
diff --git a/web/crypto/olm-api.js b/web/crypto/olm-api.js
--- a/web/crypto/olm-api.js
+++ b/web/crypto/olm-api.js
@@ -51,6 +51,7 @@
       await olm.init();
     }
   },
+  getUserPublicKey: proxyToWorker('getUserPublicKey'),
   encrypt: proxyToWorker('encrypt'),
   decrypt: proxyToWorker('decrypt'),
   contentInboundSessionCreator: proxyToWorker('contentInboundSessionCreator'),
diff --git a/web/shared-worker/worker/worker-crypto.js b/web/shared-worker/worker/worker-crypto.js
--- a/web/shared-worker/worker/worker-crypto.js
+++ b/web/shared-worker/worker/worker-crypto.js
@@ -13,6 +13,7 @@
   type SignedIdentityKeysBlob,
   type OlmAPI,
   type OneTimeKeysResultValues,
+  type ClientPublicKeys,
 } from 'lib/types/crypto-types.js';
 import type {
   IdentityNewDeviceKeyUpload,
@@ -331,6 +332,22 @@
 
     persistCryptoStore();
   },
+  async getUserPublicKey(): Promise<ClientPublicKeys> {
+    if (!cryptoStore) {
+      throw new Error('Crypto account not initialized');
+    }
+    const { contentAccount, notificationAccount } = cryptoStore;
+    const { payload, signature } = getSignedIdentityKeysBlob();
+
+    return {
+      primaryIdentityPublicKeys: JSON.parse(contentAccount.identity_keys()),
+      notificationIdentityPublicKeys: JSON.parse(
+        notificationAccount.identity_keys(),
+      ),
+      blobPayload: payload,
+      signature,
+    };
+  },
   async encrypt(content: string, deviceID: string): Promise<string> {
     if (!cryptoStore) {
       throw new Error('Crypto account not initialized');