def bit_permutation(a, b, c, d, k0, k1, k2, k3, size=32): # this uses all reversible gates - invert, choice swap (fredkin), and rotate # low weight keys are weak # data does not cause avalanche effect for round in range(4): #a ^= 0xFFFFFFFF #d ^= 0xFFFFFFFF a, b, c, d = shuffle_columns(a, b, c, d, k0, k1, k2, k3) b = rotate_left(b, 1, size) c = rotate_left(c, 2, size) d = rotate_left(d, 3, size) a, b, c, d = shuffle_columns(a, b, c, d, k0, k1, k2, k3) b = rotate_left(b, 4, size) c = rotate_left(c, 8, size) d = rotate_left(d, 12, size) a, b, c, d = shuffle_columns(a, b, c, d, k0, k1, k2, k3) b = rotate_left(b, 8, size) c = rotate_left(c, 12, size) d = rotate_left(d, 16, size) a, b, c, d = shuffle_columns(a, b, c, d, k0, k1, k2, k3) a, b, c, d = b, c, d, a # a, b, c, d, k0, k1, k2, k3 = k0, k1, k2, k3, a, b, c, d # print # print '\n'.join(format(word, 'b').zfill(32) for word in (a, b, c, d)) return a, b, c, d, k0, k1, k2, k3
def bit_permutation128(inputs, key, wordsize=32): """ Transpose the bits of the supplied inputs according to key. Selects one of 128! permutations of bits. """ a, b, c, d = inputs k0, k1, k2, k3 = key for round in range(1): a, b, c, d = shuffle_columns(a, b, c, d, k0, k1, k2, k3) # each 4 bit tall column is now active b = rotate_left(b, 1, wordsize) c = rotate_left(c, 2, wordsize) d = rotate_left(d, 3, wordsize) a, b, c, d = shuffle_columns(a, b, c, d, k0, k1, k2, k3) # each 4x4 bit subsection is now active b = rotate_left(b, 4, wordsize) c = rotate_left(c, 8, wordsize) d = rotate_left(d, 12, wordsize) a, b, c, d = shuffle_columns(a, b, c, d, k0, k1, k2, k3) # each 16x4 bit subsection is now active b = rotate_left(b, 8, wordsize) c = rotate_left(c, 12, wordsize) d = rotate_left(d, 16, wordsize) a, b, c, d = shuffle_columns(a, b, c, d, k0, k1, k2, k3) # each 32x4 bit subsection is now active return a, b, c, d
def invert_mix_columns(a, b, c, d, key): key ^= d d ^= a ^ rotate_left(key, 4) key ^= b ^ d b ^= c ^ rotate_left(key, 3) key ^= c ^ b c ^= d ^ rotate_left(key, 2) key ^= a ^ c a ^= b ^ rotate_left(key, 1) key ^= a return a, b, c, d, key
def mix_columns(a, b, c, d, key): key ^= a a ^= b ^ rotate_left(key, 1) key ^= a ^ c c ^= d ^ rotate_left(key, 2) key ^= c ^ b b ^= c ^ rotate_left(key, 3) key ^= b ^ d d ^= a ^ rotate_left(key, 4) key ^= d return a, b, c, d, key
def invert_permutation(state): for round in range(2): total = 0 for byte in state: total ^= byte state_size = len(state) for index, byte in reversed(list(enumerate(state))): total ^= byte byte ^= rotate_left(total, 1) ^ rotate_left(state[(index - 1) % state_size], 2) ^ rotate_left(state[(index + 1) % state_size], 3) state[index] = byte total ^= byte
def permutation(state): """ A diffusing permutation that preserves homomorphic properties. This is applied to the padding, after it has been combined with the message, but before it is concatenated.""" for round in range(2): total = 0 for byte in state: total ^= byte state_size = len(state) for index, byte in enumerate(state): total ^= byte byte ^= rotate_left(total, 1) ^ rotate_left(state[(index - 1) % state_size], 2) ^ rotate_left(state[(index + 1) % state_size], 3) state[index] = byte total ^= byte
def permutation2(state): key = 0 for byte in state: key ^= byte a, b, c, d = bytes_to_words(state, 4) a, b, c, d = mix_columns(a, b, c, d)#, key) b = rotate_left(b, 1) c = rotate_left(c, 2) d = rotate_left(d, 3) a, b, c, d = mix_columns(a, b, c, d)#, key) b = rotate_left(b, 4) c = rotate_left(c, 8) d = rotate_left(d, 12) a, b, c, d = mix_columns(a, b, c, d)#, key) b = rotate_left(b, 8) c = rotate_left(c, 12) d = rotate_left(d, 16) a, b, c, d = mix_columns(a, b, c, d)#, key) state[:16] = words_to_bytes((a, b, c, d), 4)
def rotl16(word, amount): return rotate_left(word, amount, bit_width=16)
def rotl16(word, amount): return rotate_left(word, amount, bit_width=16)