diff --git a/native/cpp/CommonCpp/CryptoTools/CryptoModule.h b/native/cpp/CommonCpp/CryptoTools/CryptoModule.h --- a/native/cpp/CommonCpp/CryptoTools/CryptoModule.h +++ b/native/cpp/CommonCpp/CryptoTools/CryptoModule.h @@ -44,6 +44,7 @@ // Prekey rotation methods for X3DH std::uint8_t getNumPrekeys(); std::string getPrekey(); + std::string getPrekeySignature(); folly::Optional getUnpublishedPrekey(); std::string generateAndGetPrekey(); void markPrekeyAsPublished(); diff --git a/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp b/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp --- a/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp +++ b/native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp @@ -139,6 +139,22 @@ return std::string{std::string{prekey.begin(), prekey.end()}}; } +std::string CryptoModule::getPrekeySignature() { + size_t signatureSize = ::olm_account_signature_length(this->account); + + OlmBuffer signatureBuffer; + signatureBuffer.resize(signatureSize); + + if (-1 == + ::olm_account_prekey_signature(this->account, signatureBuffer.data())) { + throw std::runtime_error{ + "error getPrekeySignature => " + + std::string{::olm_account_last_error(this->account)}}; + } + + return std::string{signatureBuffer.begin(), signatureBuffer.end()}; +} + folly::Optional CryptoModule::getUnpublishedPrekey() { OlmBuffer prekey; prekey.resize(::olm_account_prekey_length(this->account)); 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 @@ -63,7 +63,7 @@ virtual jsi::Value getUserPublicKey(jsi::Runtime &rt) override; virtual jsi::Value getPrimaryOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) override; - virtual jsi::Value generateAndGetPrekey(jsi::Runtime &rt) override; + virtual jsi::Value generateAndGetPrekeys(jsi::Runtime &rt) override; virtual jsi::Value initializeNotificationsSession( jsi::Runtime &rt, jsi::String identityKeys, 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 @@ -528,26 +528,59 @@ }); } -jsi::Value CommCoreModule::generateAndGetPrekey(jsi::Runtime &rt) { +jsi::Value CommCoreModule::generateAndGetPrekeys(jsi::Runtime &rt) { return createPromiseAsJSIValue( rt, [=](jsi::Runtime &innerRt, std::shared_ptr promise) { taskType job = [=, &innerRt]() { std::string error; - std::string prekey; + std::string contentPrekey, contentPrekeySignature, notifPrekey, + notifPrekeySignature; + if (this->cryptoModule == nullptr) { error = "user has not been initialized"; } else { - prekey = this->cryptoModule->generateAndGetPrekey(); + contentPrekey = this->cryptoModule->generateAndGetPrekey(); + contentPrekeySignature = this->cryptoModule->getPrekeySignature(); + try { + notifPrekey = + NotificationsCryptoModule::generateAndGetNotificationsPrekey( + "Comm"); + notifPrekeySignature = + NotificationsCryptoModule::getNotificationsPrekeySignature( + "Comm"); + } catch (const std::exception &e) { + error = e.what(); + } } + this->jsInvoker_->invokeAsync([=, &innerRt]() { if (error.size()) { promise->reject(error); return; } - auto prekeyJSI = jsi::String::createFromUtf8(innerRt, prekey); - promise->resolve(std::move(prekeyJSI)); + auto contentPrekeyJSI = + jsi::String::createFromUtf8(innerRt, contentPrekey); + auto contentPrekeySignatureJSI = + jsi::String::createFromUtf8(innerRt, contentPrekeySignature); + auto notifPrekeyJSI = + jsi::String::createFromUtf8(innerRt, notifPrekey); + auto notifPrekeySignatureJSI = + jsi::String::createFromUtf8(innerRt, notifPrekeySignature); + + auto signedPrekeysJSI = jsi::Object(innerRt); + signedPrekeysJSI.setProperty( + innerRt, "contentPrekey", contentPrekeyJSI); + signedPrekeysJSI.setProperty( + innerRt, "contentPrekeySignature", contentPrekeySignatureJSI); + signedPrekeysJSI.setProperty( + innerRt, "notifPrekey", notifPrekeyJSI); + signedPrekeysJSI.setProperty( + innerRt, "notifPrekeySignature", notifPrekeySignatureJSI); + + promise->resolve(std::move(signedPrekeysJSI)); }); }; + this->cryptoThread->scheduleTask(job); }); } diff --git a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h --- a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h +++ b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.h @@ -32,6 +32,8 @@ getNotificationsIdentityKeys(const std::string &callingProcessName); static std::string generateAndGetNotificationsPrekey(const std::string &callingProcessName); + static std::string + getNotificationsPrekeySignature(const std::string &callingProcessName); static crypto::EncryptedData initializeNotificationsSession( const std::string &identityKeys, const std::string &prekey, diff --git a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp --- a/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp +++ b/native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp @@ -202,6 +202,16 @@ return prekey; } +std::string NotificationsCryptoModule::getNotificationsPrekeySignature( + const std::string &callingProcessName) { + std::string prekeySignature; + auto caller = [&prekeySignature](crypto::CryptoModule cryptoModule) { + prekeySignature = cryptoModule.getPrekeySignature(); + }; + NotificationsCryptoModule::callCryptoModule(caller, callingProcessName); + return prekeySignature; +} + crypto::EncryptedData NotificationsCryptoModule::initializeNotificationsSession( const std::string &identityKeys, const std::string &prekey, 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 @@ -66,8 +66,8 @@ 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_generateAndGetPrekey(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - return static_cast(&turboModule)->generateAndGetPrekey(rt); +static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_generateAndGetPrekeys(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->generateAndGetPrekeys(rt); } 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)); @@ -136,7 +136,7 @@ methodMap_["initializeCryptoAccount"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeCryptoAccount}; methodMap_["getUserPublicKey"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getUserPublicKey}; methodMap_["getPrimaryOneTimeKeys"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getPrimaryOneTimeKeys}; - methodMap_["generateAndGetPrekey"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_generateAndGetPrekey}; + methodMap_["generateAndGetPrekeys"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_generateAndGetPrekeys}; methodMap_["initializeNotificationsSession"] = MethodMetadata {4, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsSession}; methodMap_["isNotificationsSessionInitialized"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isNotificationsSessionInitialized}; methodMap_["getCodeVersion"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getCodeVersion}; 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 @@ -37,7 +37,7 @@ virtual jsi::Value initializeCryptoAccount(jsi::Runtime &rt) = 0; virtual jsi::Value getUserPublicKey(jsi::Runtime &rt) = 0; virtual jsi::Value getPrimaryOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0; - virtual jsi::Value generateAndGetPrekey(jsi::Runtime &rt) = 0; + virtual jsi::Value generateAndGetPrekeys(jsi::Runtime &rt) = 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; @@ -210,13 +210,13 @@ return bridging::callFromJs( rt, &T::getPrimaryOneTimeKeys, jsInvoker_, instance_, std::move(oneTimeKeysAmount)); } - jsi::Value generateAndGetPrekey(jsi::Runtime &rt) override { + jsi::Value generateAndGetPrekeys(jsi::Runtime &rt) override { static_assert( - bridging::getParameterCount(&T::generateAndGetPrekey) == 1, - "Expected generateAndGetPrekey(...) to have 1 parameters"); + bridging::getParameterCount(&T::generateAndGetPrekeys) == 1, + "Expected generateAndGetPrekeys(...) to have 1 parameters"); return bridging::callFromJs( - rt, &T::generateAndGetPrekey, jsInvoker_, instance_); + rt, &T::generateAndGetPrekeys, jsInvoker_, instance_); } jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKeys) 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 @@ -27,6 +27,13 @@ +signature: string, }; +type SignedPrekeys = { + +contentPrekey: string, + +contentPrekeySignature: string, + +notifPrekey: string, + +notifPrekeySignature: string, +}; + interface Spec extends TurboModule { +getDraft: (key: string) => Promise; +updateDraft: (key: string, text: string) => Promise; @@ -61,7 +68,7 @@ +getPrimaryOneTimeKeys: ( oneTimeKeysAmount: number, ) => Promise; - +generateAndGetPrekey: () => Promise; + +generateAndGetPrekeys: () => Promise; +initializeNotificationsSession: ( identityKeys: string, prekey: string,