diff --git a/download_sharepoint.py b/download_sharepoint.py index d0cd55c..e3ce989 100644 --- a/download_sharepoint.py +++ b/download_sharepoint.py @@ -80,8 +80,8 @@ def safe_get(url, headers, stream=False, timeout=60, params=None): # --- Punkt 4: Integrity Validation (QuickXorHash) --- def quickxorhash(file_path): """Compute Microsoft QuickXorHash for a file. Returns base64-encoded string. - Follows the official Microsoft/Rclone implementation: - 160-bit circular XOR with a final length XOR.""" + Follows the official Microsoft implementation: 160-bit circular XOR + with the file length XORed into the LAST 64 bits.""" h = 0 length = 0 mask = (1 << 160) - 1 @@ -93,16 +93,14 @@ def quickxorhash(file_path): break for b in chunk: shift = (length * 11) % 160 - # Circular shift left: the byte is XORed into the 160-bit state - # at a position that rotates 11 bits for every byte. shifted = b << shift wrapped = (shifted & mask) | (shifted >> 160) h ^= wrapped length += 1 - # Finalize: XOR the 64-bit length into the 160-bit state. - # This affects the first 8 bytes of the little-endian representation. - h ^= length + # Finalize: XOR the 64-bit length into the LAST 64 bits of the 160-bit state. + # Bits 96 to 159. + h ^= (length << (160 - 64)) # Convert to 20 bytes (160 bits) in little-endian format result = h.to_bytes(20, byteorder='little')