try different permutation to try to recover the broken checksum
authorMatthieu Gallien <matthieu.gallien@nextcloud.com>
Tue, 4 Apr 2023 15:27:24 +0000 (17:27 +0200)
committerMatthieu Gallien <matthieu.gallien@nextcloud.com>
Tue, 4 Apr 2023 15:41:17 +0000 (17:41 +0200)
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>
src/libsync/clientsideencryption.cpp
src/libsync/clientsideencryption.h

index 4dfc3c6d3a7fc87347e981e9daab7a52fba14bdb..5e5633b28d3fa46d03dabeba8c789c1d0eee1618 100644 (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;
index c4517379df17967e62be87731987aada50a48522..1f9504d6fa9866f4ef4cb11384c4cfaf2d184cd1 100644 (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;