aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/connection.cpp10
-rw-r--r--lib/e2ee/e2ee.h62
-rw-r--r--lib/e2ee/qolmaccount.cpp12
3 files changed, 48 insertions, 36 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp
index 13a35684..690b3f6a 100644
--- a/lib/connection.cpp
+++ b/lib/connection.cpp
@@ -2303,14 +2303,10 @@ bool Connection::Private::createOlmSession(const QString& targetUserId,
// Verify contents of signedOneTimeKey - for that, drop `signatures` and
// `unsigned` and then verify the object against the respective signature
const auto signature =
- signedOneTimeKey
- ->signatures[targetUserId]["ed25519:"_ls % targetDeviceId]
- .toLatin1();
- const auto payloadObject =
- toJson(SignedOneTimeKey { signedOneTimeKey->key, {} });
+ signedOneTimeKey->signature(targetUserId, targetDeviceId);
if (!verifier.ed25519Verify(
edKeyForUserDevice(targetUserId, targetDeviceId).toLatin1(),
- QJsonDocument(payloadObject).toJson(QJsonDocument::Compact),
+ signedOneTimeKey->toJsonForVerification(),
signature)) {
qWarning(E2EE) << "Failed to verify one-time-key signature for" << targetUserId
<< targetDeviceId << ". Skipping this device.";
@@ -2320,7 +2316,7 @@ bool Connection::Private::createOlmSession(const QString& targetUserId,
curveKeyForUserDevice(targetUserId, targetDeviceId);
auto session =
QOlmSession::createOutboundSession(olmAccount.get(), recipientCurveKey,
- signedOneTimeKey->key);
+ signedOneTimeKey->key());
if (!session) {
qCWarning(E2EE) << "Failed to create olm session for "
<< recipientCurveKey << session.error();
diff --git a/lib/e2ee/e2ee.h b/lib/e2ee/e2ee.h
index 17c87f53..7b9b5820 100644
--- a/lib/e2ee/e2ee.h
+++ b/lib/e2ee/e2ee.h
@@ -10,8 +10,10 @@
#include "qolmerrors.h"
#include <QtCore/QMetaType>
-#include <variant>
+#include <QtCore/QStringBuilder>
+
#include <array>
+#include <variant>
namespace Quotient {
@@ -79,35 +81,53 @@ struct UnsignedOneTimeKeys
QHash<QString, QString> curve25519() const { return keys[Curve25519Key]; }
};
-//! Struct representing the signed one-time keys.
-class SignedOneTimeKey
-{
+class SignedOneTimeKey {
public:
- //! Required. The unpadded Base64-encoded 32-byte Curve25519 public key.
- QString key;
+ explicit SignedOneTimeKey(const QString& unsignedKey, const QString& userId,
+ const QString& deviceId, const QString& signature)
+ : payload { { "key"_ls, unsignedKey },
+ { "signatures"_ls,
+ QJsonObject {
+ { userId, QJsonObject { { "ed25519:"_ls % deviceId,
+ signature } } } } } }
+ {}
+ explicit SignedOneTimeKey(const QJsonObject& jo = {})
+ : payload(jo)
+ {}
- //! Required. Signatures of the key object.
- //! The signature is calculated using the process described at Signing JSON.
- QHash<QString, QHash<QString, QString>> signatures;
+ //! Unpadded Base64-encoded 32-byte Curve25519 public key
+ QString key() const { return payload["key"_ls].toString(); }
- bool fallback = false;
-};
+ //! \brief Signatures of the key object
+ //!
+ //! The signature is calculated using the process described at
+ //! https://spec.matrix.org/v1.3/appendices/#signing-json
+ auto signatures() const
+ {
+ return fromJson<QHash<QString, QHash<QString, QString>>>(
+ payload["signatures"_ls]);
+ }
-template <>
-struct JsonObjectConverter<SignedOneTimeKey> {
- static void fillFrom(const QJsonObject& jo, SignedOneTimeKey& result)
+ QByteArray signature(QStringView userId, QStringView deviceId) const
{
- fromJson(jo.value("key"_ls), result.key);
- fromJson(jo.value("signatures"_ls), result.signatures);
- fromJson(jo.value("fallback"_ls), result.fallback);
+ return payload["signatures"_ls][userId]["ed25519:"_ls % deviceId]
+ .toString()
+ .toLatin1();
}
- static void dumpTo(QJsonObject &jo, const SignedOneTimeKey &result)
+ //! Whether the key is a fallback key
+ bool isFallback() const { return payload["fallback"_ls].toBool(); }
+ auto toJson() const { return payload; }
+ auto toJsonForVerification() const
{
- addParam<>(jo, "key"_ls, result.key);
- addParam<IfNotEmpty>(jo, "signatures"_ls, result.signatures);
- addParam<IfNotEmpty>(jo, "fallback"_ls, result.fallback);
+ auto json = payload;
+ json.remove("signatures"_ls);
+ json.remove("unsigned"_ls);
+ return QJsonDocument(json).toJson(QJsonDocument::Compact);
}
+
+private:
+ QJsonObject payload;
};
using OneTimeKeys = QHash<QString, std::variant<QString, SignedOneTimeKey>>;
diff --git a/lib/e2ee/qolmaccount.cpp b/lib/e2ee/qolmaccount.cpp
index 241ae750..c3714363 100644
--- a/lib/e2ee/qolmaccount.cpp
+++ b/lib/e2ee/qolmaccount.cpp
@@ -162,17 +162,13 @@ OneTimeKeys QOlmAccount::signOneTimeKeys(const UnsignedOneTimeKeys &keys) const
OneTimeKeys signedOneTimeKeys;
for (const auto& curveKeys = keys.curve25519();
const auto& [keyId, key] : asKeyValueRange(curveKeys))
- signedOneTimeKeys["signed_curve25519:" % keyId] =
- signedOneTimeKey(key.toUtf8(), sign(QJsonObject{{"key", key}}));
+ signedOneTimeKeys.insert("signed_curve25519:" % keyId,
+ SignedOneTimeKey {
+ key, m_userId, m_deviceId,
+ sign(QJsonObject { { "key", key } }) });
return signedOneTimeKeys;
}
-SignedOneTimeKey QOlmAccount::signedOneTimeKey(const QByteArray& key,
- const QString& signature) const
-{
- return { key, { { m_userId, { { "ed25519:" + m_deviceId, signature } } } } };
-}
-
std::optional<QOlmError> QOlmAccount::removeOneTimeKeys(
const QOlmSession& session)
{