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 @@ -5,6 +5,17 @@ +curve25519: string, }; +export type OLMPrekey = { + +curve25519: { + +id: string, + +key: string, + }, +}; + +export type OLMOneTimeKeys = { + +curve25519: { +[string]: string }, +}; + export type PickledOLMAccount = { +picklingKey: string, +pickledAccount: string, diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h @@ -53,7 +53,16 @@ jsi::Array operations) override; virtual jsi::Value initializeCryptoAccount(jsi::Runtime &rt) override; virtual jsi::Value getUserPublicKey(jsi::Runtime &rt) override; - virtual jsi::Value getUserOneTimeKeys(jsi::Runtime &rt) override; + virtual jsi::Value + getPrimaryOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) override; + virtual jsi::Value initializeNotificationsSession( + jsi::Runtime &rt, + jsi::String identityKeys, + jsi::String prekey, + jsi::String prekeySignature, + jsi::String oneTimeKeys) override; + virtual jsi::Value + isNotificationsSessionInitialized(jsi::Runtime &rt) override; virtual void terminate(jsi::Runtime &rt) override; virtual double getCodeVersion(jsi::Runtime &rt) override; virtual jsi::Value diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp @@ -1104,7 +1104,27 @@ }); } -jsi::Value CommCoreModule::getUserOneTimeKeys(jsi::Runtime &rt) { +jsi::Object parseOLMOneTimeKeys(jsi::Runtime &rt, std::string oneTimeKeysBlob) { + folly::dynamic parsedOneTimeKeys = folly::parseJson(oneTimeKeysBlob); + + auto jsiOneTimeKeysInner = jsi::Object(rt); + + for (auto &kvPair : parsedOneTimeKeys["curve25519"].items()) { + jsiOneTimeKeysInner.setProperty( + rt, + kvPair.first.asString().c_str(), + jsi::String::createFromUtf8(rt, kvPair.second.asString())); + } + + auto jsiOneTimeKeys = jsi::Object(rt); + jsiOneTimeKeys.setProperty(rt, "curve25519", jsiOneTimeKeysInner); + + return jsiOneTimeKeys; +} + +jsi::Value CommCoreModule::getPrimaryOneTimeKeys( + jsi::Runtime &rt, + double oneTimeKeysAmount) { return createPromiseAsJSIValue( rt, [=](jsi::Runtime &innerRt, std::shared_ptr promise) { taskType job = [=, &innerRt]() { @@ -1113,14 +1133,78 @@ if (this->cryptoModule == nullptr) { error = "user has not been initialized"; } else { - result = this->cryptoModule->getOneTimeKeys(); + result = this->cryptoModule->getOneTimeKeys(oneTimeKeysAmount); + } + this->jsInvoker_->invokeAsync([=, &innerRt]() { + if (error.size()) { + promise->reject(error); + return; + } + promise->resolve(parseOLMOneTimeKeys(innerRt, result)); + }); + }; + this->cryptoThread->scheduleTask(job); + }); +} + +jsi::Value CommCoreModule::initializeNotificationsSession( + jsi::Runtime &rt, + jsi::String identityKeys, + jsi::String prekey, + jsi::String prekeySignature, + jsi::String oneTimeKeys) { + auto identityKeysCpp{identityKeys.utf8(rt)}; + auto prekeyCpp{prekey.utf8(rt)}; + auto prekeySignatureCpp{prekeySignature.utf8(rt)}; + auto oneTimeKeysCpp{oneTimeKeys.utf8(rt)}; + return createPromiseAsJSIValue( + rt, [=](jsi::Runtime &innerRt, std::shared_ptr promise) { + taskType job = [=, &innerRt]() { + std::string error; + crypto::EncryptedData result; + try { + result = NotificationsCryptoModule::initializeNotificationsSession( + identityKeysCpp, + prekeyCpp, + prekeySignatureCpp, + oneTimeKeysCpp, + "Comm"); + } catch (const std::exception &e) { + error = e.what(); + } + this->jsInvoker_->invokeAsync([=, &innerRt]() { + if (error.size()) { + promise->reject(error); + return; + } + promise->resolve(jsi::String::createFromUtf8( + innerRt, + std::string{result.message.begin(), result.message.end()})); + }); + }; + this->cryptoThread->scheduleTask(job); + }); +} + +jsi::Value CommCoreModule::isNotificationsSessionInitialized(jsi::Runtime &rt) { + return createPromiseAsJSIValue( + rt, [=](jsi::Runtime &innerRt, std::shared_ptr promise) { + taskType job = [=, &innerRt]() { + std::string error; + bool result; + try { + result = + NotificationsCryptoModule::isNotificationsSessionInitialized( + "Comm"); + } catch (const std::exception &e) { + error = e.what(); } this->jsInvoker_->invokeAsync([=, &innerRt]() { if (error.size()) { promise->reject(error); return; } - promise->resolve(jsi::String::createFromUtf8(innerRt, result)); + promise->resolve(result); }); }; this->cryptoThread->scheduleTask(job); diff --git a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp --- a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp +++ b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp @@ -59,8 +59,14 @@ static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getUserPublicKey(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getUserPublicKey(rt); } -static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getUserOneTimeKeys(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - return static_cast(&turboModule)->getUserOneTimeKeys(rt); +static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getPrimaryOneTimeKeys(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->getPrimaryOneTimeKeys(rt, args[0].asNumber()); +} +static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsSession(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->initializeNotificationsSession(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt)); +} +static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isNotificationsSessionInitialized(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->isNotificationsSessionInitialized(rt); } static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getCodeVersion(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getCodeVersion(rt); @@ -124,7 +130,9 @@ methodMap_["processThreadStoreOperationsSync"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processThreadStoreOperationsSync}; methodMap_["initializeCryptoAccount"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeCryptoAccount}; methodMap_["getUserPublicKey"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getUserPublicKey}; - methodMap_["getUserOneTimeKeys"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getUserOneTimeKeys}; + methodMap_["getPrimaryOneTimeKeys"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getPrimaryOneTimeKeys}; + methodMap_["initializeNotificationsSession"] = MethodMetadata {4, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsSession}; + methodMap_["isNotificationsSessionInitialized"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isNotificationsSessionInitialized}; methodMap_["getCodeVersion"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getCodeVersion}; methodMap_["terminate"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_terminate}; methodMap_["setNotifyToken"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_setNotifyToken}; diff --git a/native/cpp/CommonCpp/_generated/commJSI.h b/native/cpp/CommonCpp/_generated/commJSI.h --- a/native/cpp/CommonCpp/_generated/commJSI.h +++ b/native/cpp/CommonCpp/_generated/commJSI.h @@ -35,7 +35,9 @@ virtual void processThreadStoreOperationsSync(jsi::Runtime &rt, jsi::Array operations) = 0; virtual jsi::Value initializeCryptoAccount(jsi::Runtime &rt) = 0; virtual jsi::Value getUserPublicKey(jsi::Runtime &rt) = 0; - virtual jsi::Value getUserOneTimeKeys(jsi::Runtime &rt) = 0; + virtual jsi::Value getPrimaryOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0; + virtual jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKeys) = 0; + virtual jsi::Value isNotificationsSessionInitialized(jsi::Runtime &rt) = 0; virtual double getCodeVersion(jsi::Runtime &rt) = 0; virtual void terminate(jsi::Runtime &rt) = 0; virtual jsi::Value setNotifyToken(jsi::Runtime &rt, jsi::String token) = 0; @@ -191,13 +193,29 @@ return bridging::callFromJs( rt, &T::getUserPublicKey, jsInvoker_, instance_); } - jsi::Value getUserOneTimeKeys(jsi::Runtime &rt) override { + jsi::Value getPrimaryOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) override { static_assert( - bridging::getParameterCount(&T::getUserOneTimeKeys) == 1, - "Expected getUserOneTimeKeys(...) to have 1 parameters"); + bridging::getParameterCount(&T::getPrimaryOneTimeKeys) == 2, + "Expected getPrimaryOneTimeKeys(...) to have 2 parameters"); return bridging::callFromJs( - rt, &T::getUserOneTimeKeys, jsInvoker_, instance_); + rt, &T::getPrimaryOneTimeKeys, jsInvoker_, instance_, std::move(oneTimeKeysAmount)); + } + jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKeys) override { + static_assert( + bridging::getParameterCount(&T::initializeNotificationsSession) == 5, + "Expected initializeNotificationsSession(...) to have 5 parameters"); + + return bridging::callFromJs( + rt, &T::initializeNotificationsSession, jsInvoker_, instance_, std::move(identityKeys), std::move(prekey), std::move(prekeySignature), std::move(oneTimeKeys)); + } + jsi::Value isNotificationsSessionInitialized(jsi::Runtime &rt) override { + static_assert( + bridging::getParameterCount(&T::isNotificationsSessionInitialized) == 1, + "Expected isNotificationsSessionInitialized(...) to have 1 parameters"); + + return bridging::callFromJs( + rt, &T::isNotificationsSessionInitialized, jsInvoker_, instance_); } double getCodeVersion(jsi::Runtime &rt) override { static_assert( diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js --- a/native/schema/CommCoreModuleSchema.js +++ b/native/schema/CommCoreModuleSchema.js @@ -6,6 +6,7 @@ import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport.js'; import type { ClientDBReportStoreOperation } from 'lib/ops/report-store-ops.js'; +import type { OLMOneTimeKeys } from 'lib/types/crypto-types'; import type { ClientDBDraftStoreOperation } from 'lib/types/draft-types.js'; import type { ClientDBMessageInfo, @@ -58,7 +59,16 @@ ) => void; +initializeCryptoAccount: () => Promise; +getUserPublicKey: () => Promise; - +getUserOneTimeKeys: () => Promise; + +getPrimaryOneTimeKeys: ( + oneTimeKeysAmount: number, + ) => Promise; + +initializeNotificationsSession: ( + identityKeys: string, + prekey: string, + prekeySignature: string, + oneTimeKeys: string, + ) => Promise; + +isNotificationsSessionInitialized: () => Promise; +getCodeVersion: () => number; +terminate: () => void; +setNotifyToken: (token: string) => Promise;