def prp(data, key, mask=255, rotation_amount=5, bit_width=8, key_slice=slice(16, 32), data_slice=slice(0, 16), transpose=True): if transpose: if key_slice is not None: shuffle_bytes(data, key_slice) shuffle_bytes(data, data_slice) for index in reversed(range(len(data) - 1)): left, right = data[index], data[index + 1] key ^= right right = rotate_left((right + key + index) & mask, rotation_amount, bit_width) key ^= right key ^= left left = (left + (right >> (bit_width / 2))) & mask left ^= rotate_left(right, (index % bit_width) ^ rotation_amount) key ^= left data[index], data[index + 1] = left, right right = data[0] key ^= right right = (right + key) & mask key ^= right left = data[1] key ^= left left = (left + (right >> (bit_width / 2))) & mask left ^= rotate_left(right, (index % bit_width) ^ rotation_amount) key ^= left data[1] = left return key
def prp(data, key, mask=255, rotation_amount=5, bit_width=8, key_slice=slice(16, 32), data_slice=slice(0, 16), transpose=True): shuffle_bytes(data, slice(0, 16)) new_key = 0 _key = key for index in reversed(range(len(data) - 1)): key = _key left, right = data[index], data[index + 1] key ^= right right = rotate_left((right + key + index) & mask, rotation_amount, bit_width) key ^= right key ^= left left = (left + (right >> (bit_width / 2))) & mask left ^= rotate_left(right, (index % bit_width) ^ rotation_amount) key ^= left data[index], data[index + 1] = left, right new_key ^= key key = _key key ^= data[0] data[0] = (data[0] + key) & mask key ^= data[0] new_key ^= key return new_key
def prp(data, mask=255, rotation_amount=5, bit_width=8): shuffle_bytes(data) key = xor_sum(data) key ^= data[0] data[0] = (data[0] + key) & mask key ^= data[0] for index in range(len(data)): left, right = data[index], data[(index + 1) % 16] key ^= right right = rotate_left((right + key + index) & mask, rotation_amount, bit_width) key ^= right key ^= left left = (left + (right >> (bit_width / 2))) & mask left ^= rotate_left(right, rotation_amount) key ^= left #print "\nSet left:", index, left #print "Set right: ", (index + 1) % 16, right data[index], data[(index + 1) % 16] = left, right return key
def bit_permutation(inputs, key, wordsize=32): """ Transpose the bits of the supplied inputs according to key. Selects one of 128! permutations of bits. (not evenly distributed because they key is not large enough) """ 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 keyed_homomorphic_permutation(state, key, rounds=4): """ Ultimately, xors together random groups of state bits, such that each bit is made up of bit_i XOR bit_j XOR bit_k ... for a large enough number of random terms. """ a, b, c, d = bytes_to_words(state, 4) key = key[:] for i in range(rounds): key_schedule(key) # randomize the position of bits a, b, c, d = bit_permutation((a, b, c, d), bytes_to_words(key, 4)) # stack lots of bits on top of each other a, b, c, d = mix_columns(a, b, c, d) b = rotate_left(b, 1, 32) c = rotate_left(c, 2, 32) d = rotate_left(d, 3, 32) a, b, c, d = mix_columns(a, b, c, d) b = rotate_left(b, 4, 32) c = rotate_left(c, 8, 32) d = rotate_left(d, 12, 32) a, b, c, d = mix_columns(a, b, c, d) b = rotate_left(b, 8, 32) c = rotate_left(c, 12, 32) d = rotate_left(d, 16, 32) a, b, c, d = mix_columns(a, b, c, d) key_schedule(key) a, b, c, d = bit_permutation((a, b, c, d), bytes_to_words(key, 4)) state[:] = words_to_bytes((a, b, c, d), 4)
def invert_key_schedule(state): total = 0 for byte in state: total ^= byte for round in range(2): 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) ^ index state[index] = byte total ^= byte
def nonlinear_function4(byte): state = 0 for bit in range(8): state ^= rotate_right(byte & rotate_left(1, bit), bit) for bit in range(4): byte ^= rotate_left(state, bit) state ^= rotate_right(byte & rotate_left(1, bit), bit) byte = rotate_left(byte, 6) return byte
def key_schedule(state): """ Generates sufficiently different keys """ total = 0 for byte in state: total ^= byte for round in range(2): 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) ^ index state[index] = byte total ^= byte
def invert_speck_round(left, right, key, modulus): right ^= left right = rotate_right(right, 3) left ^= key left = (modulus + (left - right)) % modulus left = rotate_left(left, 7) return left, right
def speck_round(left, right, key, modulus): left = rotate_right(left, 7) left = (left + right) % modulus left ^= key right = rotate_left(right, 3) right ^= left return left, right
def encrypt(state, key, rounds=1): xor_subroutine(state, key) p_box_half(state) # makes halves orthogonal - 8 bytes vertical, 8 bytes horizontal for round in range(rounds): p_box(state) shuffle_bytes(state) round_key = xor_sum(state) # print "State at round start: ", round, round_key, state for index in reversed(range(16)): left, right = state[index - 1], state[index] round_key ^= left ^ right # print "\nIndex: ", index # print "Left: ", left # print "Right: ", right # print "Round key: ", round_key # print "Key: ", key[index] right = (right + round_key + key[index]) & 255 left = (left + (right >> 4)) & 255 left ^= rotate_left(right, 5) round_key ^= left ^ right state[index - 1], state[index] = left, right
def prp(data, key, mask=255, rotation_amount=5, bit_width=8): for index in range(len(data)): byte = data[index] key ^= byte data[index] = rotate_left((byte + key + index) & mask, rotation_amount, bit_width) key ^= data[index] return key
def bit_mixing(data, start=0, direction=1, bit_width=8): size = len(data) index = start key = 0 for counter in range(size): data[(index + 1) % size] ^= rotate_left(data[index], (index % bit_width), bit_width) key ^= data[(index + 1) % size] index += direction return key
def speck_round(left, right, key, mask=(2 ** 64) - 1): for round in range(20): left = key ^ ((rotate_right(left, 7) + right) & mask) #left = (left + right) & mask #left ^= key right = rotate_left(right, 3) ^ left #right = rotate_left(right, 3) #right ^= left return left, right
def bit_mixing(data, start=0, direction=1): size = len(data) index = start for counter in range(size): left, right = data[index], data[(index + 1) % size] right ^= rotate_left(left, ((index + index + 1) % 256)) data[index], data[(index + 1) % size] = left, right index += direction
def nonlinear_function6(byte, keys): left = byte >> 4 right = byte & 15 for round in range(4): key = keys[round] right = (right + key) & 255 left = (left + (right >> 4)) & 15 left ^= rotate_left(right, 3) right, left = left, (right & 255) return ((left ^ right) ^ ((left + right) & 255) + right) & 255
def bit_transposition(self): output = bytearray(16) for index in range(8): output[index] = 0 for index2 in range(8): byte = state[index2] output[index] |= ((byte & 1) << index2) & 255 state[index2] = rotate_right(byte, 1) output[index + 8] = rotate_left(state[index + 8], 1) state[:] = output[:]
def invert_prp(data, key, mask=255, rotation_amount=5, bit_width=8, transpose=False): key ^= data[0] data[0] = (256 + (data[0] - key)) & mask key ^= data[0] for index in range(len(data) - 1): right = data[index + 1] left = data[index] key ^= left left ^= rotate_left(right, (index % bit_width) ^ rotation_amount) left = (256 + (left - (right >> bit_width / 2))) & mask key ^= left; key ^= right; right = (256 + (rotate_right(right, rotation_amount, bit_width) - key - index)) & mask key ^= right; data[index + 1] = right; data[index] = left; return key;
def decrypt(state, key, rounds=1): for round in range(rounds): # print "\nBeginning of round:\n", state round_key = xor_sum(state) for index in range(16): left, right = state[index - 1], state[index] round_key ^= left ^ right left ^= rotate_left(right, 5) left = (255 + 1 + (left - (right >> 4))) & 255 right = (255 + 1 + (right - round_key - key[index])) & 255 # print left, right, round_key, key[index] round_key ^= left ^ right state[index - 1], state[index] = left, right # print "Before invert shuffle: ", state invert_shuffle_bytes(state) # print "After invert shuffle: ", state p_box(state) # print "After invert pbox: ", state p_box_half(state) xor_subroutine(state, key)
def prf(data, key, mask=255, rotation_amount=5, bit_width=8): for index in range(len(data)): new_byte = rotate_left((data[index] + key + index) & mask, rotation_amount, bit_width) key ^= new_byte data[index] = new_byte
def encrypt_unrolled(state, key, rounds=1, temp=bytearray(16)): xor_subroutine(state, key) p_box_half(state) round_key = xor_sum(state) print "Beginning unrolled" for round in range(rounds): print "Before: ", state p_box(state) print "After: ", state left, right = state[2], state[7] round_key ^= left ^ right right = (right + round_key + key[15]) & 255 temp[15] = right round_key ^= right left, right = state[10], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[14]) & 255 temp[14] = right round_key ^= right left, right = state[1], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[13]) & 255 temp[13] = right round_key ^= right left, right = state[8], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[12]) & 255 temp[12] = right round_key ^= right left, right = state[14], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[11]) & 255 temp[11] = right round_key ^= right left, right = state[3], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[10]) & 255 temp[10] = right round_key ^= right left, right = state[13], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[9]) & 255 temp[9] = right round_key ^= right left, right = state[0], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[8]) & 255 temp[8] = right round_key ^= right left, right = state[9], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[7]) & 255 temp[7] = right round_key ^= right left, right = state[6], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[6]) & 255 temp[6] = right round_key ^= right left, right = state[12], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[5]) & 255 temp[5] = right round_key ^= right left, right = state[15], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[4]) & 255 temp[4] = right round_key ^= right left, right = state[4], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[3]) & 255 temp[3] = right round_key ^= right left, right = state[5], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[2]) & 255 temp[2] = right round_key ^= right left, right = state[11], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[1]) & 255 temp[1] = right round_key ^= right left, right = temp[15], ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) round_key ^= left right = (right + round_key + key[0]) & 255 temp[0] = right round_key ^= right left = ((left + (right >> 4)) & 255) ^ rotate_left(right, 5) temp[15] = left round_key ^= left state[:] = temp[:]