try different permutation to try to recover the broken checksum

will only accept a checksum that can be computed from proper data

should still be safe

Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
This commit is contained in:
Matthieu Gallien 2023-04-04 17:27:24 +02:00
parent 27f46eb242
commit b0c69481f2
No known key found for this signature in database
GPG key ID: 7D0F74F05C22F553
2 changed files with 35 additions and 0 deletions

View file

@ -1714,6 +1714,14 @@ bool FolderMetadata::checkMetadataKeyChecksum(const QByteArray &metadataKey,
const QByteArray &metadataKeyChecksum) const
{
const auto referenceMetadataKeyValue = computeMetadataKeyChecksum(metadataKey);
if (referenceMetadataKeyValue != metadataKeyChecksum) {
if (recoverMetadataKeyChecksum(metadataKeyChecksum, metadataKey)) {
qCInfo(lcCseMetadata) << "Checksum recovery done";
return true;
}
}
return referenceMetadataKeyValue == metadataKeyChecksum;
}
@ -1734,6 +1742,31 @@ QByteArray FolderMetadata::computeMetadataKeyChecksum(const QByteArray &metadata
return hashAlgorithm.result().toHex();
}
bool FolderMetadata::recoverMetadataKeyChecksum(const QByteArray &expectedChecksum,
const QByteArray &metadataKey) const
{
const auto sortLambda = [] (const auto &first, const auto &second) {
return first.encryptedFilename < second.encryptedFilename;
};
auto sortedFiles = _files;
std::sort(sortedFiles.begin(), sortedFiles.end(), sortLambda);
do {
auto hashAlgorithm = QCryptographicHash{QCryptographicHash::Sha256};
hashAlgorithm.addData(_account->e2e()->_mnemonic.remove(' ').toUtf8());
for (const auto &singleFile : sortedFiles) {
hashAlgorithm.addData(singleFile.encryptedFilename.toUtf8());
}
hashAlgorithm.addData(metadataKey);
if (hashAlgorithm.result().toHex() == expectedChecksum) {
break;
}
} while (std::next_permutation(sortedFiles.begin(), sortedFiles.end(), sortLambda));
return expectedChecksum;
}
bool FolderMetadata::isMetadataSetup() const
{
return _isMetadataSetup;

View file

@ -233,6 +233,8 @@ private:
[[nodiscard]] bool checkMetadataKeyChecksum(const QByteArray &metadataKey, const QByteArray &metadataKeyChecksum) const;
[[nodiscard]] QByteArray computeMetadataKeyChecksum(const QByteArray &metadataKey) const;
[[nodiscard]] bool recoverMetadataKeyChecksum(const QByteArray &expectedChecksum,
const QByteArray &metadataKey) const;
QByteArray _metadataKey;