def encryption_mode(state, rate, output_size, mixing_subroutine, absorb_mode): input_block = yield None while input_block is not None: xor_subroutine(state, bytearray(input_block)) input_block = yield bytes(state[:len(input_block)]) mixing_subroutine(state) yield bytes(state[rate])
def upfront_keyschedule(data, key, constants, rounds, counter, state): round_keys = generate_round_keys(key, rounds, constants) for round_key_index in rounds: round_key = round_keys[round_key_index] xor_subroutine(data, round_key) state = _crypt_block(round_key, constants, data, counter, state) xor_subroutine(data, round_key)
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 stream_cipher(data, seed, key, size=(8, 255, 5), mode="encrypt"): if mode == "encrypt": data_prp_function = prp else: data_prp_function = invert_prp key = list(key) seed = list(seed) state = seed + key key_material = list() bit_width, mask, rotation_amount = size block_count, extra = divmod(len(data), 16) prf_state_xor = 0 state_xor = xor_sum(state) for block in range(block_count + 1 if extra else block_count): state_xor = prp(state, state_xor, mask, rotation_amount, bit_width) prf_state_xor ^= state_xor key_material.extend(state[0:16]) prf(key_material, prf_state_xor, mask, rotation_amount, bit_width) data_xor = xor_with_key(data, key_material) data_xor = data_prp_function(data, data_xor, mask, rotation_amount, bit_width, transpose=False) xor_subroutine(data, key_material)
def test_hash(data): output = bytearray(16) key = xor_sum(bytearray(data[:16])) for block in slide(bytearray(data), 16): prf(block, xor_sum(block)) xor_subroutine(output, block) return bytes(output)
def test_encrypt_decrypt(): data = bytearray(8) data[0] = 1 _data = data[:] key = bytearray(32) encrypt(data, key) ciphertext = data[:] decrypt(data, key) assert data == _data, (data, _data) data2 = bytearray(8) data2[0] = 2 _data2 = data2[:] encrypt(data2, key) ciphertext2 = data2[:] decrypt(data2, key) assert data2 == _data2, (data2, _data2) answer = _data[:] xor_subroutine(answer, _data2) xor_subroutine(ciphertext, ciphertext2) decrypt(ciphertext, key) assert ciphertext == answer, (ciphertext, answer) print "Passed secretkey encrypt/decrypt unit test"
def online_keyschedule_embedded_decryption_key(data, key, constants, rounds, counter, state): reverse_constants = bytearray(reversed(constants)) for round_number in rounds: xor_subroutine(data, key) state = _crypt_block(key, constants, data, counter, state) xor_subroutine(data, key) generate_round_key(key, reverse_constants)
def decrypt(data, key): """ Decrypt 64 bits of data from 128-bit ciphertext using key. """ xor_subroutine(data, key[16:]) invert_keyed_homomorphic_permutation(data, key[:16]) xor_subroutine(data, key[16:]) #padding = data[8:] #xor_subroutine(data, padding) del data[8:] return data[:8]
def decrypt(data, key, conversion_key, conversion_key2): xor_subroutine(data, key) converted = convert(bytes(data), bytes(conversion_key2), bytes(conversion_key)) replacement_subroutine(data, converted) invert_diffusion_transformation(data) xor_subroutine(data, key) return bytes(data)
def encrypt(data, key, padding=None): """ Encrypt 64 bits of data using key. Produces 128-bit ciphertext. Ciphertexts are partially homomorphic. """ padding = bytearray(urandom(8)) if padding is None else padding[:8] #xor_subroutine(data, padding) # not sure if this is actually necessary data.extend(padding) xor_subroutine(data, key[16:]) assert len(data) == 16 keyed_homomorphic_permutation(data, key[:16]) xor_subroutine(data, key[16:]) return data
def decryption_mode(state, rate, output_size, mode_of_operation, absorb_mode): input_block = yield None while input_block is not None: last_block = state[:len(input_block)] xor_subroutine(state, bytearray(input_block)) input_block = yield bytes(state[:len(input_block)]) xor_subroutine(state, last_block) mixing_subroutine(state) authentication_code = yield bytes(state[rate]) if authentication_code != state[rate]: raise ValueError("Invalid tag")
def test_hash(data): size = len(data) data = data + ("\x00" * (16 - size)) if size == 16: output = bytearray(data) for round in range(1): prp(output, xor_sum(output)) else: output = bytearray(16) for block in slide(bytearray(data), 16): prp(block, xor_sum(block)) xor_subroutine(output, block) return bytes(output)
def nonlinear_function9(data, key, mask=((2 ** 8) - 1)): xor_subroutine(data, key) for index, byte in enumerate(p_box(data[:8]) + (p_box(data[8:]))): data[index] = byte shuffle(data) round_key = xor_sum(data) for index in reversed(range(16)): next_index = index - 1 round_key ^= data[index] ^ data[next_index] right = (data[index] + round_key + key[index]) & mask left = (data[next_index] + (right >> 4)) & mask left ^= rotate_right(right, 5) data[next_index], data[index] = left, right round_key ^= data[index] ^ data[next_index] return bytes(data)
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 encrypt(data, key): """ Encrypt 64 bits of data using key. Produces 128-bit ciphertext. Ciphertexts are partially homomorphic. """ padding = bytearray(urandom(8)) xor_subroutine(data, padding) data.extend(padding) xor_subroutine(data, key[16:]) keyed_homomorphic_permutation(data, key[:16]) xor_subroutine(data, key[16:]) return data
def stream_cipher(data, seed, key, size=(8, 255, 5)): key = list(key) seed = list(seed) key_material = list() key_xor = xor_sum(key) bit_width, mask, rotation_amount = size block_count, extra = divmod(len(data), 16) for block in range(block_count + 1 if extra else block_count): key_xor = prp(key, mask, rotation_amount, bit_width) round_key = key[:] prf(round_key, key_xor, mask, rotation_amount, bit_width) xor_subroutine(seed, round_key) prp(seed, mask, rotation_amount, bit_width) xor_subroutine(seed, round_key) prf(seed, xor_sum(seed), mask, rotation_amount, bit_width) key_material.extend(seed) xor_subroutine(data, key_material)
def cbc_decrypt(block, iv, key, cipher, tag=None, tweak=None): next_iv = block[:] cipher(block, key, tag, tweak) xor_subroutine(block, iv) replacement_subroutine(iv, next_iv)
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[:]
def ofb_mode(block, iv, key, cipher, tag=None, tweak=None): cipher(iv, key, tag, twak) xor_subroutine(block, iv)
def block_to_stream_decrypt(data, key, seed, blocksize=32): key_material = stream_cipher(len(data), seed, key) for block in reversed(list(slide(data, blocksize))): xor_subroutine(data, key_material) invert_prp(data, xor_sum(data)) xor_subroutine(data, key_material)
def stream_to_block_encrypt(data, key, seed, blocksize=32): key_material = stream_cipher(len(data), seed, key) for block in slide(data, blocksize): xor_subroutine(data, key_material) prp(data, xor_sum(data)) xor_subroutine(data, key_material)
def ctr_mode(block, iv, key, cipher, tag=None, tweak=None): cipher(iv, key, tag, tweak) xor_subroutine(block, iv) replacement_subroutine(iv, bytearray(cast(cast(cast(bytes(iv), "binary"), "integer") + 1, "bytes")))
def cbc_encrypt(block, iv, key, cipher, tag=None, tweak=None): xor_subroutine(block, iv) cipher(block, key, tag, tweak) replacement_subroutine(iv, block)
def online_keyschedule(data, key, constants, rounds, counter, state): for round_number in rounds: generate_round_key(key, constants) xor_subroutine(data, key) state = _crypt_block(key, constants, data, counter, state) xor_subroutine(data, key)