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 @@ -77,6 +77,9 @@ encrypt(const std::string &targetDeviceId, const std::string &content); std::string decrypt(const std::string &targetDeviceId, EncryptedData &encryptedData); + std::string decryptSequential( + const std::string &targetDeviceId, + EncryptedData &encryptedData); std::string signMessage(const std::string &message); static void verifySignature( 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 @@ -414,6 +414,16 @@ return this->sessions.at(targetDeviceId)->decrypt(encryptedData); } +std::string CryptoModule::decryptSequential( + const std::string &targetDeviceId, + EncryptedData &encryptedData) { + if (!this->hasSessionFor(targetDeviceId)) { + throw std::runtime_error{ + "error decrypt sequential => uninitialized session"}; + } + return this->sessions.at(targetDeviceId)->decryptSequential(encryptedData); +} + std::string CryptoModule::signMessage(const std::string &message) { OlmBuffer signature; signature.resize(::olm_account_signature_length(this->getOlmAccount())); diff --git a/native/cpp/CommonCpp/CryptoTools/Session.h b/native/cpp/CommonCpp/CryptoTools/Session.h --- a/native/cpp/CommonCpp/CryptoTools/Session.h +++ b/native/cpp/CommonCpp/CryptoTools/Session.h @@ -32,6 +32,7 @@ restoreFromB64(const std::string &secretKey, OlmBuffer &b64); OlmSession *getOlmSession(); std::string decrypt(EncryptedData &encryptedData); + std::string decryptSequential(EncryptedData &encryptedData); int getVersion(); void setVersion(int newVersion); }; diff --git a/native/cpp/CommonCpp/CryptoTools/Session.cpp b/native/cpp/CommonCpp/CryptoTools/Session.cpp --- a/native/cpp/CommonCpp/CryptoTools/Session.cpp +++ b/native/cpp/CommonCpp/CryptoTools/Session.cpp @@ -157,6 +157,51 @@ return std::string{(char *)decryptedMessage.data(), decryptedSize}; } +std::string Session::decryptSequential(EncryptedData &encryptedData) { + OlmSession *session = this->getOlmSession(); + + OlmBuffer utilityBuffer(::olm_utility_size()); + OlmUtility *olmUtility = ::olm_utility(utilityBuffer.data()); + + OlmBuffer messageHashBuffer(::olm_sha256_length(olmUtility)); + ::olm_sha256( + olmUtility, + encryptedData.message.data(), + encryptedData.message.size(), + messageHashBuffer.data(), + messageHashBuffer.size()); + + OlmBuffer tmpEncryptedMessage(encryptedData.message); + size_t maxSize = ::olm_decrypt_max_plaintext_length( + session, + encryptedData.messageType, + tmpEncryptedMessage.data(), + tmpEncryptedMessage.size()); + + if (maxSize == -1) { + throw std::runtime_error{ + "error decrypt_max_plaintext_length => " + + std::string{::olm_session_last_error(session)} + ". Hash: " + + std::string{messageHashBuffer.begin(), messageHashBuffer.end()}}; + } + + OlmBuffer decryptedMessage(maxSize); + size_t decryptedSize = ::olm_decrypt_sequential( + session, + encryptedData.messageType, + encryptedData.message.data(), + encryptedData.message.size(), + decryptedMessage.data(), + decryptedMessage.size()); + if (decryptedSize == -1) { + throw std::runtime_error{ + "error decrypt_sequential => " + + std::string{::olm_session_last_error(session)} + ". Hash: " + + std::string{messageHashBuffer.begin(), messageHashBuffer.end()}}; + } + return std::string{(char *)decryptedMessage.data(), decryptedSize}; +} + int Session::getVersion() { return this->version; }