More untested stuff :)

This commit is contained in:
Tobias Fella
2024-06-26 22:56:33 +02:00
parent eda2881d6e
commit 3ede6b4526
2 changed files with 165 additions and 111 deletions

View File

@@ -607,17 +607,27 @@ void NeoChatConnection::setupCrossSigningKeys(const QString &password)
QJsonObject{{"ed25519:"_ls + QString::fromLatin1(masterKeyPublic), QJsonObject{{"ed25519:"_ls + QString::fromLatin1(masterKeyPublic),
QString::fromLatin1(sign(masterKeyPrivate.viewAsByteArray(), QJsonDocument(userSigningKeyJson).toJson(QJsonDocument::Compact)))}}}}; QString::fromLatin1(sign(masterKeyPrivate.viewAsByteArray(), QJsonDocument(userSigningKeyJson).toJson(QJsonDocument::Compact)))}}}};
auto job = callApi<UploadCrossSigningKeysJob>(masterKey, selfSigningKey, userSigningKey, std::nullopt); const auto encodedMasterKeyPrivate = viewAsByteArray(masterKeyPrivate).toBase64();
const auto encodedSelfSigningKeyPrivate = viewAsByteArray(selfSigningKeyPrivate).toBase64();
const auto encodedUserSigningKeyPrivate = viewAsByteArray(userSigningKeyPrivate).toBase64();
auto encodedMasterKeyPrivate = viewAsByteArray(masterKeyPrivate).toBase64(); callApi<UploadCrossSigningKeysJob>(masterKey, selfSigningKey, userSigningKey, std::nullopt)
auto encodedSelfSigningKeyPrivate = viewAsByteArray(selfSigningKeyPrivate).toBase64(); .then(
auto encodedUserSigningKeyPrivate = viewAsByteArray(userSigningKeyPrivate).toBase64(); [this, encodedMasterKeyPrivate, encodedSelfSigningKeyPrivate, encodedUserSigningKeyPrivate, masterKeyPublic]() {
finishCrossSigningSetup(encodedMasterKeyPrivate,
connect(job, encodedSelfSigningKeyPrivate,
&BaseJob::failure, encodedUserSigningKeyPrivate,
this, QString::fromLatin1(masterKeyPublic));
[this, masterKey, selfSigningKey, userSigningKey, password, encodedMasterKeyPrivate, encodedSelfSigningKeyPrivate, encodedUserSigningKeyPrivate]( },
const auto &job) { [this,
password,
masterKey,
selfSigningKey,
userSigningKey,
encodedMasterKeyPrivate,
encodedSelfSigningKeyPrivate,
encodedUserSigningKeyPrivate,
masterKeyPublic](const auto &job) {
callApi<UploadCrossSigningKeysJob>(masterKey, callApi<UploadCrossSigningKeysJob>(masterKey,
selfSigningKey, selfSigningKey,
userSigningKey, userSigningKey,
@@ -633,11 +643,25 @@ void NeoChatConnection::setupCrossSigningKeys(const QString &password)
{"user"_ls, userId()}, {"user"_ls, userId()},
}}, }},
}, },
}) })
.then([this, encodedMasterKeyPrivate, encodedSelfSigningKeyPrivate, encodedUserSigningKeyPrivate](const auto &job) { .then(
// TODO: check job result? [this, encodedMasterKeyPrivate, encodedSelfSigningKeyPrivate, encodedUserSigningKeyPrivate, masterKeyPublic]() {
Q_UNUSED(job); finishCrossSigningSetup(encodedMasterKeyPrivate,
encodedSelfSigningKeyPrivate,
encodedUserSigningKeyPrivate,
QString::fromLatin1(masterKeyPublic));
},
[]() {
qWarning() << "Failed to setup cross-signing keys";
});
});
}
void NeoChatConnection::finishCrossSigningSetup(const QByteArray &encodedMasterKeyPrivate,
const QByteArray &encodedSelfSigningKeyPrivate,
const QByteArray &encodedUserSigningKeyPrivate,
const QString &masterKeyPublic)
{
auto key = getRandom(32); auto key = getRandom(32);
QByteArray data = QByteArrayLiteral("\x8B\x01") + viewAsByteArray(key); QByteArray data = QByteArrayLiteral("\x8B\x01") + viewAsByteArray(key);
data[8] &= ~(1 << 7); // Byte 63 needs to be set to 0 data[8] &= ~(1 << 7); // Byte 63 needs to be set to 0
@@ -649,8 +673,9 @@ void NeoChatConnection::setupCrossSigningKeys(const QString &password)
} }
// The key to be shown to the user // The key to be shown to the user
auto formatted = groups.join(QStringLiteral(" ")); const auto formatted = groups.join(QStringLiteral(" "));
auto identifier = QString::fromLatin1(QCryptographicHash::hash(QUuid::createUuid().toString().toLatin1(), QCryptographicHash::Sha256)); Q_EMIT showSecurityKey(formatted);
const auto identifier = QString::fromLatin1(QCryptographicHash::hash(QUuid::createUuid().toString().toLatin1(), QCryptographicHash::Sha256));
setAccountData("m.secret_storage.default_key"_ls, setAccountData("m.secret_storage.default_key"_ls,
{ {
@@ -663,15 +688,15 @@ void NeoChatConnection::setupCrossSigningKeys(const QString &password)
QString mac; QString mac;
}; };
auto encryptAccountData = [this, &key, identifier](QLatin1String info, const QByteArray &data) { auto encryptAccountData = [this, &key, identifier](QLatin1String info, const QByteArray &plainText) {
auto iv = getRandom(16); const auto iv = getRandom(16);
const auto &kdfKeys = hkdfSha256(byte_view_t<>(key).subspan<0, DefaultPbkdf2KeyLength>(), zeroes<32>(), asCBytes<>(info)); const auto &kdfKeys = hkdfSha256(byte_view_t<>(key).subspan<0, DefaultPbkdf2KeyLength>(), zeroes<32>(), asCBytes<>(info));
if (!kdfKeys.has_value()) { if (!kdfKeys.has_value()) {
qWarning() << "Key Setup: Failed to calculate HKDF" << info; qWarning() << "Key Setup: Failed to calculate HKDF" << info;
// Q_EMIT error(DecryptionError); // Q_EMIT error(DecryptionError);
return EncryptionData{}; return EncryptionData{};
} }
const auto &encrypted = aesCtr256Encrypt(data, kdfKeys.value().aes(), asCBytes<AesBlockSize>(iv)); const auto &encrypted = aesCtr256Encrypt(plainText, kdfKeys.value().aes(), asCBytes<AesBlockSize>(iv));
if (!encrypted.has_value()) { if (!encrypted.has_value()) {
qWarning() << "Key Setup: Failed to encrypt test keys" << info; qWarning() << "Key Setup: Failed to encrypt test keys" << info;
// emit error(DecryptionError); // emit error(DecryptionError);
@@ -728,14 +753,38 @@ void NeoChatConnection::setupCrossSigningKeys(const QString &password)
{"mac"_ls, userSigningData.mac}, {"mac"_ls, userSigningData.mac},
}}}}}); }}}}});
// TODO make sure masterKeyForUser already works at this point; // Adding the verified master key manually so that we don't have to wait until we receive it from the server
database()->setMasterKeyVerified(masterKeyForUser(userId())); auto query = database()->prepareQuery(QStringLiteral("INSERT INTO master_keys(userId, key, verified) VALUES (:userId, :key, :verified);"));
query.bindValue(":userId"_ls, userId());
query.bindValue(":key"_ls, masterKeyPublic);
query.bindValue(":verified"_ls, true);
database()->execute(query);
const auto selfSigningKey = database()->loadEncrypted("m.cross_signing.self_signing"_ls);
QHash<QString, QHash<QString, QJsonObject>> signatures;
auto json = QJsonObject{
{"keys"_ls,
QJsonObject{
{"ed25519:"_ls + deviceId(), edKeyForUserDevice(userId(), deviceId())},
{"curve25519:"_ls + deviceId(), curveKeyForUserDevice(userId(), deviceId())},
}},
{"algorithms"_ls, QJsonArray{"m.olm.v1.curve25519-aes-sha2"_ls, "m.megolm.v1.aes-sha2"_ls}},
{"device_id"_ls, deviceId()},
{"user_id"_ls, userId()},
};
auto signature = sign(selfSigningKey, QJsonDocument(json).toJson(QJsonDocument::Compact));
json["signatures"_ls] = QJsonObject{
{userId(),
QJsonObject{
{"ed25519:"_ls + database()->selfSigningPublicKey(), QString::fromLatin1(signature)},
}},
};
signatures[userId()][deviceId()] = json;
callApi<UploadCrossSigningSignaturesJob>(signatures).onFailure([](const auto &job) {
qWarning() << "Failed to upload self-signing signature" << job->error() << job->errorString();
});
// TODO start a key backup and store in account data // TODO start a key backup and store in account data
qWarning() << "Finished creating keys";
});
});
} }
#include "moc_neochatconnection.cpp" #include "moc_neochatconnection.cpp"

View File

@@ -198,6 +198,7 @@ Q_SIGNALS:
void passwordStatus(NeoChatConnection::PasswordStatus status); void passwordStatus(NeoChatConnection::PasswordStatus status);
void userConsentRequired(QUrl url); void userConsentRequired(QUrl url);
void badgeNotificationCountChanged(NeoChatConnection *connection, int count); void badgeNotificationCountChanged(NeoChatConnection *connection, int count);
void showSecurityKey(const QString &securityKey);
private: private:
bool m_isOnline = true; bool m_isOnline = true;
@@ -206,6 +207,10 @@ private:
ThreePIdModel *m_threePIdModel; ThreePIdModel *m_threePIdModel;
void connectSignals(); void connectSignals();
void finishCrossSigningSetup(const QByteArray &encodedMasterKeyPrivate,
const QByteArray &encodedSelfSigningKeyPrivate,
const QByteArray &encodedUserSigningKeyPrivate,
const QString &masterKeyPublic);
int m_badgeNotificationCount = 0; int m_badgeNotificationCount = 0;