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 branch32(word): # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 word ^= rotate_left(word, 3, 32) word ^= rotate_left(word, 6, 32) word ^= rotate_left(word, 13, 32) word ^= rotate_left(word, 8, 32) return word
def branch(word): word ^= rotate_left(word, 3, 64) # two bits influence each bit word ^= rotate_left(word, 6, 64) # four bits influence each bit word ^= rotate_left(word, 17, 64) # eight bits influence each bit word ^= rotate_left(word, 5, 64) # sixteen bits influence each bit word ^= rotate_left(word, 27, 64) # thirty-two bits influence each bit return word
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 diffusion_test2(a, b): # 0 1 2 3 4 5 6 7 # a03 a14 a25 a36 a47 a50 a61 a72 # a ^= rotate_left(a, 3) # 0134 0235 0347 0136 0237 # 121 212 313 123 214 # a03 a14 a25 a36 a47 a50 a61 a72 # a61 a72 a03 a14 a25 a36 a47 a50 # a ^= rotate_left(a, 6) # = # a0136 a1247 a0235 a1346 a2457 a0356 a1467 a0257 # a0136 a1247 a0235 a1346 a2457 a0356 a1467 a0257 # b0136 b1247 b0235 b1346 b2457 b0356 b1467 b0257 # a ^= b # = # a0136b0136 a1247b1247 a0235b0235 a1346b1346 a2457b2457 a0356b0356 a1467b1467 a0257b0257 # b0136 b1247 b0235 b1346 b2457 b0356 b1467 b0257 # a0136b0136 a1247b1247 a0235b0235 a1346b1346 a2457b2457 a0356b0356 a1467b1467 a0257b0257 # b023467 b1245 b04 b0347 # 121 313 # = a ^= rotate_left(a, 3) a ^= rotate_left(a, 6) b ^= rotate_left(b, 3) b ^= rotate_left(b, 6) a ^= b b ^= rotate_left(a, 2) return a, b
def shift_rows(b, c, d, r1, r2, r3, wordsize=WORDSIZE): _b = _c = _d = 0 for subsection in range(4): _b |= rotate_left(b >> (subsection * 32), r1, wordsize) << (subsection * 32) _c |= rotate_left(c >> (subsection * 32), r2, wordsize) << (subsection * 32) _d |= rotate_left(d >> (subsection * 32), r3, wordsize) << (subsection * 32) return _b, _c, _d
def nonlinear_mixing(t, y, t2, y2): #t ^= rotate_left(choice(y, t2, y2), 1, bit_width=32) # has problems related to hamming weight #y ^= rotate_left(choice(t2, y2, t), 3, bit_width=32) #t2 ^= rotate_left(choice(y2, t, y), 5, bit_width=32) #y2 ^= rotate_left(choice(t, y, t2), 7, bit_width=32) t ^= mixRow(rotate_left(choice(y, t2, y2), 1, bit_width=32)) # fills out the fastest y ^= mixRow(rotate_left(choice(t2, y2, t), 3, bit_width=32)) t2 ^= mixRow(rotate_left(choice(y2, t, y), 5, bit_width=32)) y2 ^= mixRow(rotate_left(choice(t, y, t2), 7, bit_width=32)) #t ^= rotate_left(mixRow(choice(y, t2, y2)), 1, bit_width=32) #y ^= rotate_left(mixRow(choice(t2, y2, t)), 3, bit_width=32) #t2 ^= rotate_left(mixRow(choice(y2, t, y)), 5, bit_width=32) #y2 ^= rotate_left(mixRow(choice(t, y, t2)), 7, bit_width=32) #t ^= rotate_left(choice(y, t2, y2), 1, bit_width=32) #t = mixRow(t) #y ^= rotate_left(choice(t2, y2, t), 3, bit_width=32) #y = mixRow(y) #t2 ^= rotate_left(choice(y2, t, y), 5, bit_width=32) #t2 = mixRow(t2) #y2 ^= rotate_left(choice(t, y, t2), 7, bit_width=32) #y2 = mixRow(y2) #t ^= mixRow(choice(y, t2, y2)) #y ^= mixRow(choice(t2, y2, t)) #t2 ^= mixRow(choice(y2, t, y)) #y2 ^= mixRow(choice(t, y, t2)) return t, y, t2, y2
def encode8(word): # 0 1 2 3 4 5 6 7 # 03 14 25 36 47 50 61 72 # 61 72 03 14 25 36 47 50 # 0136 1247 0235 1346 2457 0356 1467 0257 word ^= rotate_left(word, 3, 8) word ^= rotate_left(word, 6, 8) return word
def branch64(word): #0 1 2 3|4 5 6 7|8 9 10 11|12 13 14 15|16 17 18 19|20 21 22 23|24 25 26 27|28 29 30 31|32 33 34 35|36 37 38 39|40 41 42 43|44 45 46 47|48 49 50 51|52 53 54 55|56 57 58 59|60 61 62 63 word ^= rotate_left(word, 3, 64) word ^= rotate_left(word, 6, 64) word ^= rotate_left(word, 17, 64) word ^= rotate_left(word, 15, 64) # 5 word ^= rotate_left(word, 24, 64) # 25 26 27 return word
def branch(word): """ Makes each bit in the output word depend on 1/2 the bits from the input word. """ word ^= rotate_left(word, 3, 64) # two bits influence each bit word ^= rotate_left(word, 6, 64) # four bits influence each bit word ^= rotate_left(word, 17, 64) # eight bits influence each bit word ^= rotate_left(word, 15, 64) # sixteen bits influence each bit word ^= rotate_left(word, 24, 64) # thirty-two bits influence each bit return word
def fill(byte): byte ^= rotate_left(byte, 1, 32) byte ^= rotate_left(byte, 2, 32) byte ^= rotate_left(byte, 4, 32) byte ^= rotate_left(byte, 8, 32) byte ^= rotate_left(byte, 16, 32) #byte ^= rotate_left(byte, 32, 64) return byte
def shift_rows(b, c, d, r1, r2, r3, mask=0xFFFFFFFF): _b = _c = _d = 0 for count in range(4): shift_amount = count * 32 _b ^= rotate_left((b >> shift_amount) & mask, r1, 32) << shift_amount _c ^= rotate_left((c >> shift_amount) & mask, r2, 32) << shift_amount _d ^= rotate_left((d >> shift_amount) & mask, r2, 32) << shift_amount return _b, _c, _d
def mix_pair(top, bottom, wordsize=WORDSIZE): top ^= bottom top = rotate_left(top, 1, wordsize) bottom ^= top bottom = rotate_left(bottom, 2, wordsize) top ^= bottom top = rotate_left(top, 4, wordsize) bottom ^= top return top, bottom
def prp(slice1, slice2, key, index, mask=0xFFFFFFFFFFFFFFFF, rotations=41, bit_width=64): key ^= slice1 ^ slice2 slice1 = rotate_left((slice1 + key + index) & mask, rotations, bit_width=bit_width) slice2 = (slice2 + (slice1 >> 32)) & mask slice2 ^= rotate_left(slice1, index, bit_width=bit_width) key ^= slice1 ^ slice2 return slice1, slice2, key
def prp(top, bottom, key, index, mask=0xFFFFFFFFFFFFFFFF, rotations=21): key ^= top ^ bottom top = rotate_left((top + key + index) & mask, rotations, bit_width=64) bottom = (bottom + (top >> 32)) & mask bottom ^= rotate_left(top, index, bit_width=64) key ^= top ^ bottom return top, bottom, key
def keyed_permutation(data, key, rounds=1, modulus=256): data_size = len(data) for round in range(rounds): for index in range(data_size): key_material = key[rotate_left(data[index] ^ index, 1, 8)] xor_subroutine(data, key_material) # instead of branching in the addition loop, subtract the current byte out data[index] ^= key_material[index] data[index] = rotate_left(data[index], round + index, 8)
def round_function(state1, state2): #state = integer_to_bytes(state1, 8) + integer_to_bytes(state2, 8) #temp #x = ((state[7] << 24) & 255) | ((state[6] << 24) ^ 255) | ((state[5] << 16) & 255) | state[4] #y = ((state[3] << 24) & 255) | ((state[2] << 24) ^ 255) | ((state[1] << 16) & 255) | state[0] ## #x = ((state[15] << 24) & 255) | ((state[14] << 24) ^ 255) | ((state[13] << 16) & 255) | state[12] #y2 = ((state[11] << 24) & 255) | ((state[10] << 24) ^ 255) | ((state[9] << 16) & 255) | state[8] # state1 0-7 state2 8-15 # top half # the strange ordering applies shuffle_bytes before the bit permutation #x = ((state[1] << 16) & 255) | ((state[6] << 24) ^ 255) | ((state[5] << 16) & 255) | state[4] #y = ((state[3] << 24) & 255) | ((state[2] << 24) ^ 255) | | state[0] #x = ((state[15] << 24) & 255) | ((state[14] << 24) ^ 255) | ((state[13] << 16) & 255) | state[12] #y2 = ((state[11] << 24) & 255) | ((state[10] << 24) ^ 255) | ((state[9] << 16) & 255) | state[8] x = (((state2 >> 24) & 255) << 24) | (((state1 >> 40) & 255) << 16) | (((state1 >> 32) & 255) << 8) | ((state2 >> 56) & 255) y = (((state2 >> 32) & 255) << 24) | (((state1 >> 48) & 255) << 16) | (((state2 >> 8) & 255) << 8) | (state1 & 255) t = (y ^ (y >> 7)) & 0x00AA00AA; y = y ^ t ^ (t << 7); t = (x ^ (x >>14)) & 0x0000CCCC; x = x ^ t ^ (t <<14); t = (y ^ (y >>14)) & 0x0000CCCC; y = y ^ t ^ (t <<14); t = (x & 0xF0F0F0F0) | ((y >> 4) & 0x0F0F0F0F); y = ((x << 4) & 0xF0F0F0F0) | (y & 0x0F0F0F0F); # bottom half x = (((state2 >> 40) & 255) << 24) | (((state1 >> 24) & 255) << 16) | (((state2 >> 48) & 255) << 8) | (state2 & 255) y2 = (((state1 >> 8) & 255) <<24) | (((state2 >> 16) & 255) << 16) | (((state1 >> 16) & 255) << 8) | ((state1 >> 56) & 255) t2 = (y2 ^ (y2 >> 7)) & 0x00AA00AA; y2 = y2 ^ t2 ^ (t2 << 7); t2 = (x ^ (x >>14)) & 0x0000CCCC; x = x ^ t2 ^ (t2 <<14); t2 = (y2 ^ (y2 >>14)) & 0x0000CCCC; y2 = y2 ^ t2 ^ (t2 <<14); t2 = (x & 0xF0F0F0F0) | ((y2 >> 4) & 0x0F0F0F0F); y2 = ((x << 4) & 0xF0F0F0F0) | (y2 & 0x0F0F0F0F); # end decorrelation layer # non linear layer + mix the rows t ^= micksRow(rotate_left(choice(y, t2, y2), 1, bit_width=32)) y ^= micksRow(rotate_left(choice(t2, y2, t), 3, bit_width=32)) t2 ^= micksRow(rotate_left(choice(y2, t, y), 5, bit_width=32)) y2 ^= micksRow(rotate_left(choice(t, y, t2), 7, bit_width=32)) state1 = (y << 32) | t state2 = (y2 << 32)| t2 return state1, state2
def prng(a, b, c, d, mask=0xFFFFFFFF): a ^= b c ^= mask a &= c a = rotate_left(a, 1) #a, b = weird_addition2(a, b, 1) #a, c = weird_addition2(a, c, 2) #a, d = weird_addition2(a, d, 3) # #c, b = weird_addition2(c, b, 4) #c, d = weird_addition2(c, d, 5) #c, a = weird_addition2(c, a, 6) # #b, a = weird_addition2(b, a, 7) #b, c = weird_addition2(b, c, 8) #b, d = weird_addition2(b, d, 9) # #d, a = weird_addition2(d, a, 10) #d, c = weird_addition2(d, c, 11) #d, b = weird_addition2(d, b, 12) #c, d = weird_addition2(c, d, 2) # #a, c = weird_addition2(a, c, 3) #b, d = weird_addition2(b, d, 4) # #a, d = weird_addition2(a, d, 5) #b, c = weird_addition2(b, c, 6) #a = weird_addition(a, b ^ c ^ d, 1) #b = weird_addition(b, a ^ c ^ d, 2) #c = weird_addition(c, a ^ b ^ d, 3) #d = weird_addition(d, a ^ b ^ c, 4) #a = (a + key) & mask #key ^= a ^ b #b = (b + key) & mask #key ^= b ^ c #c = (c + key) & mask #key ^= c ^ d #d = (d + key) & mask #a, b, c = _nonlinear_function(a, b, c, 1) #b, c, a = _nonlinear_function(b, c, d, 2) #c, a, b = _nonlinear_function(c, a, b, 3) #key ^= a ^ b # #b, key = _nonlinear_function(b, key) #key ^= b ^ c # #c, key = _nonlinear_function(c, key) #key ^= c ^ d # #d, key = _nonlinear_function(d, key) return rotate_left(a, 4, 32), rotate_left(b, 8, 32), rotate_left(c, 16, 32), rotate_left(d, 24, 32)
def bit_transposition(bits, k0, k1, k2, k3, size=32): a, b, c, d = [int(_bits, 2) for _bits in slide(bits, size)] for round in range(4): 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 # key schedule k0, k1, k2, k3 = sbox(k0, k1, k2, k3) return [ int(item) for item in ''.join( format(word, 'b').zfill(32) for word in (a, b, c, d)) ]
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 bit_transposition(bits, k0, k1, k2, k3, size=32): a, b, c, d = [int(_bits, 2) for _bits in slide(bits, size)] for round in range(4): 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 # key schedule k0, k1, k2, k3 = sbox(k0, k1, k2, k3) return [int(item) for item in ''.join(format(word, 'b').zfill(32) for word in (a, b, c, d))]
def test_function(a, b, c, d): for round in range(2): a ^= b c ^= d b ^= c d ^= a b = rotate_left(b, 1, 32) c = rotate_left(c, 2, 32) d = rotate_left(d, 3, 32) a ^= b c ^= d b ^= c d ^= a b = rotate_left(b, 4, 32) c = rotate_left(c, 8, 32) d = rotate_left(d, 12, 32) a ^= b c ^= d b ^= c d ^= a b = rotate_left(b, 8, 32) c = rotate_left(c, 12, 32) d = rotate_left(d, 16, 32) return a, b, c, d
def branch8(word): # 0 1 2 3 4 5 6 7 # 3 4 5 6 7 0 1 2 # 03 14 25 36 47 05 16 27 # 03 14 25 36 47 05 16 27 # 16 27 03 14 25 36 47 05 # 0136 1247 0235 1346 0356 1467 0257 word ^= rotate_left(word, 3) word ^= rotate_left(word, 6) return word
def mix_state(a, b, c, d): #a = diffusion_transformation(a, b) #a = diffusion_transformation(a, c) a = diffusion_transformation(a, d) # b = diffusion_transformation(b, a) # c = diffusion_transformation(c, b) # d = diffusion_transformation(d, c) #c = diffusion_transformation(c, d) #b = diffusion_transformation(b, c) #d = diffusion_transformation(d, a) return a, rotate_left(b, 8, 32), rotate_left(c, 16, 32), rotate_left(d, 24, 32)
def bit_transposition(left, right, key, key_index, wordsize=WORDSIZE): left, right = choice_swap(key[key_index], left, right) left = rotate_left(left, 1, wordsize) left, right = choice_swap(key[key_index + 1], left, right) right = rotate_left(right, 2, wordsize) left, right = choice_swap(key[key_index + 2], left, right) left = rotate_left(left, 4, wordsize) left, right = choice_swap(key[key_index + 3], left, right) return left, right
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 add_constant(round_constants): output = 0 for counter, constant in enumerate(round_constants): t = constant t ^= rotate_left(t, 3, 64); t ^= rotate_left(t, 6, 64); t ^= rotate_left(t, 17, 64); t ^= rotate_left(t, 15, 64); t ^= rotate_left(t, 24, 64); output |= t << (64 * counter) round_constants[0] += 4; round_constants[1] += 4; round_constants[2] += 4; round_constants[3] += 4; return output
def round_function(left, right, key, index, mask=255, rotation_amount=5, bit_width=8): 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 return left, right, key
def mix_pairs(a, b, c, d): for index in range(4): _a, _b, _c, _d = a[index], b[index], c[index], d[index] #_a, _b = _mix_pair(_a, _b) #_c, _d = _mix_pair(_c, _d) _a ^= _b _c ^= _d _b ^= rotate_left(_a, 2) _d ^= rotate_left(_c, 2) #_a ^= rotate_left(_b, 1); _c ^= rotate_left(_d, 1); #_b ^= rotate_left(_a, 2); _d ^= rotate_left(_d, 2); a[index], b[index], c[index], d[index] = _a, _b, _c, _d
def round_function(data, left_index, right_index, key, mask=255, rotation_amount=5, bit_width=8): left, right = data[left_index], data[right_index] key ^= right right = rotate_left((right + key + right_index) & mask, rotation_amount, bit_width) key ^= right key ^= left left = (left + (right >> (bit_width / 2))) & mask left ^= rotate_left(right, (right_index % bit_width) ^ rotation_amount) key ^= left data[left_index], data[right_index] = left, right return key
def _permutation(seed, key, index, index2, wordsize): left, right = seed[index], seed[index2] left = S_BOX256[left] right = S_BOX256[right] key_left, key_right = key[index % KEY_SIZE], key[index2 % KEY_SIZE] left, right = choice_swap(key_left ^ key_right, left, right) left = rotate_left(left, 1, wordsize) left, right = choice_swap(S_BOX256[key_left] ^ key_right, left, right) right = rotate_left(right, 2, wordsize) left, right = choice_swap(key_left ^ S_BOX256[key_right], left, right) left = rotate_left(left, 4, wordsize) left, right = choice_swap(S_BOX256[key_left] ^ S_BOX256[key_right], left, right) seed[index], seed[index2] = left, right
def mix_pair(top, bottom, wordsize=WORDSIZE): # a0 a1 a2 a3 a4 a5 a6 a7 # b0 b1 b2 b3 b4 b5 b6 b7 # a ^= b # a0b0 a1b1 a2b2 a3b3 a4b4 a5b5 a6b6 a7b7 # b0 b1 b2 b3 b4 b5 b6 b7 # rotate a left by 1 # a1b1 a2b2 a3b3 a4b4 a5b5 a6b6 a7b7 a0b0 # b0 b1 b2 b3 b4 b5 b6 b7 # b ^= a # a1b1 a2b2 a3b3 a4b4 a5b5 a6b6 a7b7 a0b0 # b0a1b1 b1a2b2 b2a3b3 b3a4b4 b4a5b5 b5a6b6 b6a7b7 b7a0b0 # rotate b left by 2 # a1b1 a2b2 a3b3 a4b4 a5b5 a6b6 a7b7 a0b0 # b2a3b3 b3a4b4 b4a5b5 b5a6b6 b6a7b7 b7a0b0 b0a1b1 b1a2b2 # a ^= b # a1b1b2a3b3 a2b2b3a4b4 a3b3b4a5b5 a4b4b5a6b6 a5b5b6a7b7 a6b6b7a0b0 a7b7b0a1b1 a0b0b1a2b2 # b2a3b3 b3a4b4 b4a5b5 b5a6b6 b6a7b7 b7a0b0 b0a1b1 b1a2b2 # rotate a left by 4 # a5b5b6a7b7 a6b6b7a0b0 a7b7b0a1b1 a0b0b1a2b2 a1b1b2a3b3 a2b2b3a4b4 a3b3b4a5b5 a4b4b5a6b6 # b2a3b3 b3a4b4 b4a5b5 b5a6b6 b6a7b7 b7a0b0 b0a1b1 b1a2b2 # b ^= a # a5b5b6a7b7 a6b6b7a0b0 a7b7b0a1b1 a0b0b1a2b2 a1b1b2a3b3 a2b2b3a4b4 a3b3b4a5b5 a4b4b5a6b6 # b2a3b3a5b5b6a7b7 b3a4b4a6b6b7a0b0 b4a5b5a7b7b0a1b1 b5a6b6a0b0b1a2b2 b6a7b7a1b1b2a3b3 b7a0b0a2b2b3a4b4 b0a1b1a3b3b4a5b5 b1a2b2a4b4b5a6b6 top ^= bottom top = rotate_left(top, 1, wordsize) bottom ^= top bottom = rotate_left(bottom, 2, wordsize) top ^= bottom top = rotate_left(top, 4, wordsize) bottom ^= top #bottom = rotate_left(bottom, 5, wordsize) # does not really improve active bits; min is 47 without this step, and only 49 with it #top ^= bottom return top, bottom
def weird_addition(a, b, amount): t = a t &= b a ^= b a = rotate_left(a, amount, 32) a ^= t return a
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 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 _permutation(seed, index, index2, wordsize): left, right = seed[index], seed[index2] left = S_BOX256[left] right = S_BOX256[right] left = left ^ right left = rotate_left(left, 1, wordsize) right = right ^ left right = rotate_left(right, 2, wordsize) left = left ^ right left = rotate_left(left, 4, wordsize) right = right ^ left right = rotate_left(right, 7, wordsize) left = left ^ right seed[index], seed[index2] = 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 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 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 weird_addition2(a, b, amount): t = a t &= b a ^= b b = rotate_left(b, amount, 32) b ^= t return a, b