40 lines
1.4 KiB
Python
40 lines
1.4 KiB
Python
|
|
from modes.hash_mode import HashMode
|
||
|
|
|
||
|
|
|
||
|
|
class AvalancheTest:
|
||
|
|
"""
|
||
|
|
Проверка эффекта лавины:
|
||
|
|
небольшое изменение во входном сообщении должно сильно менять хэш.
|
||
|
|
"""
|
||
|
|
|
||
|
|
def run(self, variant: str, message: str, salt: str = "", bytes: int = 16) -> dict:
|
||
|
|
hasher = HashMode()
|
||
|
|
|
||
|
|
# базовый хэш
|
||
|
|
h1 = hasher.run(variant, message, salt=salt, bytes=bytes)
|
||
|
|
|
||
|
|
# изменяем один символ (если пусто — подставим "a")
|
||
|
|
if message:
|
||
|
|
i = 0 # всегда первый символ для простоты
|
||
|
|
flipped_char = chr((ord(message[i]) + 1) % 128)
|
||
|
|
mod_msg = flipped_char + message[1:]
|
||
|
|
else:
|
||
|
|
mod_msg = "a"
|
||
|
|
|
||
|
|
h2 = hasher.run(variant, mod_msg, salt=salt, bytes=bytes)
|
||
|
|
|
||
|
|
# сравнение побитово
|
||
|
|
diff_bits = sum(c1 != c2 for c1, c2 in zip(
|
||
|
|
bin(int(h1, 16))[2:], bin(int(h2, 16))[2:]))
|
||
|
|
total_bits = len(h1) * 4 # HEX -> биты
|
||
|
|
|
||
|
|
return {
|
||
|
|
"original": message,
|
||
|
|
"modified": mod_msg,
|
||
|
|
"hash1": h1,
|
||
|
|
"hash2": h2,
|
||
|
|
"diff_bits": diff_bits,
|
||
|
|
"total_bits": total_bits,
|
||
|
|
"diff_percent": round(100 * diff_bits / total_bits, 2),
|
||
|
|
}
|