Fix QuickXorHash: XOR længde ind i de sidste 64 bit (bits 96-159)
- Korrigerer finaliseringslogikken så filstørrelsen XOR'es ind i de mest betydende 64 bit af 160-bit staten - Tidligere version XOR'ede i de mindst betydende bit, hvilket gav forkerte hashes - Dette matcher nu præcis Microsofts specifikation og fjerner falske hash-mismatches
This commit is contained in:
@@ -80,8 +80,8 @@ def safe_get(url, headers, stream=False, timeout=60, params=None):
|
|||||||
# --- Punkt 4: Integrity Validation (QuickXorHash) ---
|
# --- Punkt 4: Integrity Validation (QuickXorHash) ---
|
||||||
def quickxorhash(file_path):
|
def quickxorhash(file_path):
|
||||||
"""Compute Microsoft QuickXorHash for a file. Returns base64-encoded string.
|
"""Compute Microsoft QuickXorHash for a file. Returns base64-encoded string.
|
||||||
Follows the official Microsoft/Rclone implementation:
|
Follows the official Microsoft implementation: 160-bit circular XOR
|
||||||
160-bit circular XOR with a final length XOR."""
|
with the file length XORed into the LAST 64 bits."""
|
||||||
h = 0
|
h = 0
|
||||||
length = 0
|
length = 0
|
||||||
mask = (1 << 160) - 1
|
mask = (1 << 160) - 1
|
||||||
@@ -93,16 +93,14 @@ def quickxorhash(file_path):
|
|||||||
break
|
break
|
||||||
for b in chunk:
|
for b in chunk:
|
||||||
shift = (length * 11) % 160
|
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
|
shifted = b << shift
|
||||||
wrapped = (shifted & mask) | (shifted >> 160)
|
wrapped = (shifted & mask) | (shifted >> 160)
|
||||||
h ^= wrapped
|
h ^= wrapped
|
||||||
length += 1
|
length += 1
|
||||||
|
|
||||||
# Finalize: XOR the 64-bit length into the 160-bit state.
|
# Finalize: XOR the 64-bit length into the LAST 64 bits of the 160-bit state.
|
||||||
# This affects the first 8 bytes of the little-endian representation.
|
# Bits 96 to 159.
|
||||||
h ^= length
|
h ^= (length << (160 - 64))
|
||||||
|
|
||||||
# Convert to 20 bytes (160 bits) in little-endian format
|
# Convert to 20 bytes (160 bits) in little-endian format
|
||||||
result = h.to_bytes(20, byteorder='little')
|
result = h.to_bytes(20, byteorder='little')
|
||||||
|
|||||||
Reference in New Issue
Block a user