diff --git a/ChaCha20_Poly1305_64/sim/modulo_theory.py b/ChaCha20_Poly1305_64/sim/modulo_theory.py new file mode 100644 index 0000000..b303246 --- /dev/null +++ b/ChaCha20_Poly1305_64/sim/modulo_theory.py @@ -0,0 +1,75 @@ +import random + +PRIME = 2**130-5 + +def modulo_theory_simple(loops: int): + prime = 97 + + for _ in range(loops): + value_a = random.randint(1,97) + value_b = random.randint(1,97) + + value_a_high = value_a // 10 + value_a_low = value_a % 10 # Ignore this modulo, in base 2 it is a mask + + prod_high = value_a_high * value_b + prod_low = value_a_low * value_b + + mod_high = (prod_high*10) % prime + mod_low = prod_low % prime + + mod_sum = (mod_high + mod_low) % prime + + mod_conventional = (value_a * value_b) % prime + + if mod_sum != mod_conventional: + print(f"{value_a}") + print(f"{value_b}") + print(f"{mod_sum=}") + print(f"{mod_conventional=}") + +def modulo_theory_full(loops: int): + for _ in range(loops): + value_a = random.randint(1,PRIME) + value_b = random.randint(1,2**128) + + a_partials = [(value_a >> 26*i) & (2**26-1) for i in range(5)] + + prods = [a_partial * value_b for a_partial in a_partials] + + mods = [friendly_modulo(prod, 26*i) for i, prod in enumerate(prods)] + + + mod_sum = friendly_modulo(sum(mods), 0) + + mod_conventional = (value_a * value_b) % PRIME + + if mod_sum != mod_conventional: + print(f"{value_a}") + print(f"{value_b}") + print(f"{mod_sum=}") + print(f"{mod_conventional=}") + +def friendly_modulo(val: int, shift_amount: int) -> int: + high_part = val >> (130-shift_amount) + low_part = (val << shift_amount) & (2**130-1) + + high_part *= 5 + + val = high_part + low_part + + high_part = val >> 130 + low_part = val & (2**130-1) + + high_part *= 5 + + val = high_part + low_part + + if val >= PRIME: + val -= PRIME + + return val + +if __name__ == "__main__": + #modulo_theory_simple(10000000) + modulo_theory_full(100000)