def encrypt(data, key, rounds=2): k1, k2, k3, k4 = bytes_to_longs(key) s1, s2, s3, s4 = bytes_to_longs(data) for round in range(1, rounds + 1): s1, s2, s3, s4 = nonlinear_mixing(round ^ s1 ^ k1, round ^ s2 ^ k2, round ^ s3 ^ k3, round ^ s4 ^ k4) k1, k2, k3, k4 = nonlinear_mixing(k1, k2, k3, k4) return longs_to_bytes(s1 ^ k1, s2 ^ k2, s3 ^ k3, s4 ^ k4)
def permutation_256_32(state, rounds=1): (a, b, c, d, e, f, g, h) = bytes_to_longs(state) for round in range(rounds): a, b, c, d = nonlinear_mixing_step(*branching_step( a, b, c, d)) # could be done in parallel in hardware e, f, g, h = nonlinear_mixing_step(*branching_step( e, f, g, h)) # could be done in parallel in hardware a, b, e, f = nonlinear_mixing_step(*branching_step(a, b, e, f)) c, d, g, h = nonlinear_mixing_step(*branching_step(c, d, g, h)) a, b, g, h = nonlinear_mixing_step(*branching_step(a, b, g, h)) c, d, a, b = nonlinear_mixing_step(*branching_step(c, d, a, b)) state[:] = longs_to_bytes(a, b, c, d, e, f, g, h)
def decrypt(data, key, rounds=2): k1, k2, k3, k4 = bytes_to_longs(key) s1, s2, s3, s4 = bytes_to_longs(data) keys = [] for round in range(1, rounds + 1): keys.append((k1, k2, k3, k4)) k1, k2, k3, k4 = nonlinear_mixing(k1, k2, k3, k4) s1 ^= k1 s2 ^= k2 s3 ^= k3 s4 ^= k4 for round in reversed(range(1, rounds + 1)): k1, k2, k3, k4 = keys.pop(-1) s1, s2, s3, s4 = invert_nonlinear_mixing(s1, s2, s3, s4) s1 ^= k1 ^ round s2 ^= k2 ^ round s3 ^= k3 ^ round s4 ^= k4 ^ round return longs_to_bytes(s1, s2, s3, s4)
def invert_permutation_subroutine(data, mask=0xFFFFFFFFFFFFFFFF): a, b, c, d = bytes_to_longs(bytearray(data)) a, b, c, d = invert_permutation(a, b, c, d) data[:] = bytes(longs_to_bytes(a, b, c, d))
def permutation_on_state(data, mask=0xFFFFFFFFFFFFFFFF): a, b, c, d = bytes_to_longs(bytearray(data)) a, b, c, d = permutation(a, b, c, d) return bytes(longs_to_bytes(a, b, c, d))