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 @@ -48,7 +48,12 @@ 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 getNotificationsOneTimeKeys( + jsi::Runtime &rt, + double oneTimeKeysAmount) override; + virtual jsi::Value generateNotificationsPrekey(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 @@ -953,7 +953,27 @@ }); } -jsi::Value CommCoreModule::getUserOneTimeKeys(jsi::Runtime &rt) { +jsi::Object parseOLMOneTimeKeys(jsi::Runtime &rt, std::string oneTimeKeysBlob) { + folly::dynamic parsedOneTimeKeys = folly::parseJson(oneTimeKeysBlob); + + auto jsiOneTimeKeys = jsi::Object(rt); + 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())); + } + + 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]() { @@ -962,14 +982,88 @@ 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::getNotificationsOneTimeKeys( + jsi::Runtime &rt, + double oneTimeKeysAmount) { + return createPromiseAsJSIValue( + rt, [=](jsi::Runtime &innerRt, std::shared_ptr promise) { + taskType job = [=, &innerRt]() { + std::string result; + std::string error; + + try { + result = NotificationsCryptoModule::getNotificationsOneTimeKeys( + oneTimeKeysAmount, "Comm"); + } catch (const std::exception &e) { + error = e.what(); + } + + this->jsInvoker_->invokeAsync([=, &innerRt]() { + if (error.size()) { + promise->reject(error); + return; + } + promise->resolve(parseOLMOneTimeKeys(innerRt, result)); + }); + }; + this->cryptoThread->scheduleTask(job); + }); +} + +jsi::Object parseOLMPrekey(jsi::Runtime &rt, std::string prekeyBlob) { + folly::dynamic parsedPrekey = folly::parseJson(prekeyBlob); + + std::string prekeyId = + parsedPrekey["curve25519"].items().begin()->first.asString(); + std::string prekeyValue = + parsedPrekey["curve25519"].items().begin()->second.asString(); + + auto jsiPrekey = jsi::Object(rt); + auto jsiPrekeyInner = jsi::Object(rt); + + jsiPrekeyInner.setProperty( + rt, "id", jsi::String::createFromUtf8(rt, prekeyId)); + jsiPrekeyInner.setProperty( + rt, "key", jsi::String::createFromUtf8(rt, prekeyValue)); + jsiPrekey.setProperty(rt, "curve25519", jsiPrekeyInner); + + return jsiPrekey; +} + +jsi::Value CommCoreModule::generateNotificationsPrekey(jsi::Runtime &rt) { + return createPromiseAsJSIValue( + rt, [=](jsi::Runtime &innerRt, std::shared_ptr promise) { + taskType job = [=, &innerRt]() { + std::string result; + std::string error; + + try { + result = + NotificationsCryptoModule::generateNotificationsPreKey("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(parseOLMPrekey(innerRt, 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 @@ -56,8 +56,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_getNotificationsOneTimeKeys(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->getNotificationsOneTimeKeys(rt, args[0].asNumber()); +} +static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_generateNotificationsPrekey(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->generateNotificationsPrekey(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); @@ -114,7 +120,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_["getNotificationsOneTimeKeys"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getNotificationsOneTimeKeys}; + methodMap_["generateNotificationsPrekey"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_generateNotificationsPrekey}; 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 @@ -34,7 +34,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 getNotificationsOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0; + virtual jsi::Value generateNotificationsPrekey(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; @@ -180,13 +182,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 getNotificationsOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) override { + static_assert( + bridging::getParameterCount(&T::getNotificationsOneTimeKeys) == 2, + "Expected getNotificationsOneTimeKeys(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::getNotificationsOneTimeKeys, jsInvoker_, instance_, std::move(oneTimeKeysAmount)); + } + jsi::Value generateNotificationsPrekey(jsi::Runtime &rt) override { + static_assert( + bridging::getParameterCount(&T::generateNotificationsPrekey) == 1, + "Expected generateNotificationsPrekey(...) to have 1 parameters"); + + return bridging::callFromJs( + rt, &T::generateNotificationsPrekey, 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 @@ -5,6 +5,7 @@ import { TurboModuleRegistry } from 'react-native'; import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport.js'; +import type { OLMOneTimeKeys, OLMPrekey } from 'lib/types/crypto-types'; import type { ClientDBDraftStoreOperation } from 'lib/types/draft-types.js'; import type { ClientDBMessageInfo, @@ -54,7 +55,13 @@ ) => void; +initializeCryptoAccount: () => Promise; +getUserPublicKey: () => Promise; - +getUserOneTimeKeys: () => Promise; + +getPrimaryOneTimeKeys: ( + oneTimeKeysAmount: number, + ) => Promise; + +getNotificationsOneTimeKeys: ( + oneTimeKeysAmount: number, + ) => Promise; + +generateNotificationsPrekey: () => Promise; +getCodeVersion: () => number; +terminate: () => void; +setNotifyToken: (token: string) => Promise;