check checksum when getting e2ee metadata

Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
This commit is contained in:
Matthieu Gallien 2023-03-28 00:45:28 +02:00
parent 1b0a93eabc
commit 1b14c127a4
No known key found for this signature in database
GPG key ID: 7D0F74F05C22F553
2 changed files with 36 additions and 13 deletions

View file

@ -33,6 +33,7 @@
#include <QUuid> #include <QUuid>
#include <QScopeGuard> #include <QScopeGuard>
#include <QRandomGenerator> #include <QRandomGenerator>
#include <QCryptographicHash>
#include <qt5keychain/keychain.h> #include <qt5keychain/keychain.h>
#include <common/utility.h> #include <common/utility.h>
@ -1555,10 +1556,10 @@ void FolderMetadata::setupExistingMetadata(const QByteArray& metadata)
} }
} }
if (_metadataKey.isEmpty()) { const auto sharing = metadataObj["sharing"].toString().toLocal8Bit();
qCDebug(lcCse()) << "Could not setup existing metadata with missing metadataKeys!"; const auto files = metaDataDoc.object()["files"].toObject();
return; const auto metadataKey = metaDataDoc.object()["metadata"].toObject()["metadataKey"].toString().toUtf8();
} const auto metadataKeyChecksum = metaDataDoc.object()["metadata"].toObject()["checksum"].toString().toUtf8();
QByteArray sharing = metadataObj["sharing"].toString().toLocal8Bit(); QByteArray sharing = metadataObj["sharing"].toString().toLocal8Bit();
QJsonObject files = metaDataDoc.object()["files"].toObject(); QJsonObject files = metaDataDoc.object()["files"].toObject();
@ -1609,17 +1610,15 @@ void FolderMetadata::setupExistingMetadata(const QByteArray& metadata)
file.encryptionKey = QByteArray::fromBase64(decryptedFileObj["key"].toString().toLocal8Bit()); file.encryptionKey = QByteArray::fromBase64(decryptedFileObj["key"].toString().toLocal8Bit());
file.mimetype = decryptedFileObj["mimetype"].toString().toLocal8Bit(); file.mimetype = decryptedFileObj["mimetype"].toString().toLocal8Bit();
// In case we wrongly stored "inode/directory" we try to recover from it if (!checkMetadataKeyChecksum(metadataKey, metadataKeyChecksum)) {
if (file.mimetype == QByteArrayLiteral("inode/directory")) { _metadataKey.clear();
file.mimetype = QByteArrayLiteral("httpd/unix-directory"); _files.clear();
return;
} }
_files.push_back(file); // decryption finished, create new metadata key to be used for encryption
} _metadataKey = EncryptionHelper::generateRandom(metadataKeySize);
_isMetadataSetup = true;
// decryption finished, create new metadata key to be used for encryption
_metadataKey = EncryptionHelper::generateRandom(metadataKeySize);
_isMetadataSetup = true;
} }
// RSA/ECB/OAEPWithSHA-256AndMGF1Padding using private / public key. // RSA/ECB/OAEPWithSHA-256AndMGF1Padding using private / public key.
@ -1663,6 +1662,26 @@ QByteArray FolderMetadata::decryptJsonObject(const QByteArray& encryptedMetadata
return EncryptionHelper::decryptStringSymmetric(pass, encryptedMetadata); return EncryptionHelper::decryptStringSymmetric(pass, encryptedMetadata);
} }
bool FolderMetadata::checkMetadataKeyChecksum(const QByteArray &metadataKey,
const QByteArray &metadataKeyChecksum) const
{
const auto referenceMetadataKeyValue = computeMetadataKeyChecksum(metadataKey);
return referenceMetadataKeyValue == metadataKeyChecksum;
}
QByteArray FolderMetadata::computeMetadataKeyChecksum(const QByteArray &metadataKey) const
{
auto checksumData = _account->e2e()->_mnemonic.remove(' ');
for (const auto &singleFile : _files) {
checksumData += singleFile.encryptedFilename;
}
checksumData += metadataKey;
auto hashAlgorithm = QCryptographicHash{QCryptographicHash::Sha256};
hashAlgorithm.addData(checksumData.toUtf8());
return hashAlgorithm.result().toHex();
}
bool FolderMetadata::isMetadataSetup() const bool FolderMetadata::isMetadataSetup() const
{ {
return _isMetadataSetup; return _isMetadataSetup;

View file

@ -213,6 +213,10 @@ private:
[[nodiscard]] QByteArray encryptJsonObject(const QByteArray& obj, const QByteArray pass) const; [[nodiscard]] QByteArray encryptJsonObject(const QByteArray& obj, const QByteArray pass) const;
[[nodiscard]] QByteArray decryptJsonObject(const QByteArray& encryptedJsonBlob, const QByteArray& pass) const; [[nodiscard]] QByteArray decryptJsonObject(const QByteArray& encryptedJsonBlob, const QByteArray& pass) const;
[[nodiscard]] bool checkMetadataKeyChecksum(const QByteArray &metadataKey, const QByteArray &metadataKeyChecksum) const;
[[nodiscard]] QByteArray computeMetadataKeyChecksum(const QByteArray &metadataKey) const;
QByteArray _metadataKey; QByteArray _metadataKey;
QVector<EncryptedFile> _files; QVector<EncryptedFile> _files;