def stream_cipher(data, key, seed, modulus=2 ** 32, wordsize=32): #assert isinstance(data, bytearray) state = bytes_to_words(bytearray(data), 4) prng_key, seed_key = key xor_subroutine(seed, seed_key) assert len(seed) == 4, len(seed) a, b, c, d = seed k0, k1, k2, k3 = prng_key a, b, c, d = add_key(a, b, c, d, k0, k1, k2, k3) a, b, c, d = permutation(a, b, c, d, modulus) assert len(state) for index in range(len(state) - 1): a, b, c, d = add_key(a, b, c, d, k0, k1, k2, k3) a, b, c, d = add_key(a, b, c, d, index, index + 1, index + 2, index + 3) b, c, d, a = permutation(a, b, c, d) state[index] ^= (a + b) % modulus state[(index + 1)] ^= (c + d) % modulus _data = words_to_bytes(state, 4) try: data[:] = _data except (ValueError, TypeError): pass return _data
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 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 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(): from os import urandom data = bytearray(32) data[0] = 1 _data = data[:] key = bytearray(urandom(64)) #range(64)#[0] * 64 encrypt(data, key) ciphertext = data[:] decrypt(data, key) assert data == _data, (data, _data) data2 = bytearray(32) data2[0] = 2 _data2 = data2[:] encrypt(data2, key) ciphertext2 = data2[:] decrypt(data2, key) assert data2 == _data2, (data2, _data2) parity = 1 # defaults to 1 xor_subroutine(_data, _data2) xor_subroutine(ciphertext, ciphertext2) parity ^= 1 # flip to 0 decrypt(ciphertext, key, parity) assert ciphertext == _data, ([byte for byte in ciphertext], [byte for byte in _data]) print "Passed secretkey encrypt/decrypt Unit Test"
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 decrypt(data, tag, iv, key, associated_data='', hash_function=hash_function, invert_permutation=arxcalibur512.invert_permutation, rounds=ROUNDS): block_key = tag[:] xor_subroutine(block_key, key) blocks = (block for block in reversed(list(slide(data, 8)))) for block_count, ciphertext in enumerate(blocks): state = ciphertext + block_key for round in reversed(range(rounds)): state = invert_permutation(*[ round, ] + state) _store_block(data, block_count, state[:8]) block_key = list(state[8:]) if list(data[8:16]) == iv and hash_function(associated_data) == data[-8:]: remove_padding(data, 32) return True else: return False
def test_encrypt_decrypt(): data = bytearray(8 * WORDSIZE) data[0] = 1 _data = data[:] key = bytearray(8 * WORDSIZE) encrypt(data, key) ciphertext = data[:] decrypt(data, key) assert data == _data, (data, _data) data2 = bytearray(8 * WORDSIZE) data2[0] = 2 _data2 = data2[:] encrypt(data2, key) ciphertext2 = data2[:] decrypt(data2, key) assert data2 == _data2, (data2, _data2) xor_subroutine(_data, _data2) xor_subroutine(ciphertext, ciphertext2) decrypt(ciphertext, key) assert ciphertext == _data, (ciphertext, _data) print "Passed secretkey encrypt/decrypt unit test"
def encrypt(data, key): random_mask = bytearray(32) xor_subroutine(data, random_mask) xor_subroutine(random_mask, key[:32]) state = bytes_to_words(data, 4) keyed_bit_transposition(state, bytes_to_words(key[32:64], 4)) data[:] = words_to_bytes(state, 4) + random_mask
def test_encrypt_decrypt(): from os import urandom data = bytearray(32) data[0] = 1 _data = data[:] key = bytearray(urandom(64))#range(64)#[0] * 64 encrypt(data, key) ciphertext = data[:] decrypt(data, key) assert data == _data, (data, _data) data2 = bytearray(32) data2[0] = 2 _data2 = data2[:] encrypt(data2, key) ciphertext2 = data2[:] decrypt(data2, key) assert data2 == _data2, (data2, _data2) parity = 1 # defaults to 1 xor_subroutine(_data, _data2) xor_subroutine(ciphertext, ciphertext2) parity ^= 1 # flip to 0 decrypt(ciphertext, key, parity) assert ciphertext == _data, ([byte for byte in ciphertext], [byte for byte in _data]) 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 encrypt(data, iv, key, associated_data='', hash_function=hash_function, permutation=arxcalibur512.permutation, rounds=ROUNDS): block_key = key assert len(block_key) == 8 assert len(iv) == 8 assert not len(data) % 8 blocks = ( block for block in slide(hash_function(associated_data) + iv + data, 8)) for block_count, block in enumerate(blocks): state = block + block_key for round in range(rounds): state = permutation(*[ round, ] + state) _store_block(data, block_count, state[:8]) block_key = list(state[8:]) assert len(block_key) == len(key) xor_subroutine(block_key, key) return block_key # block_key is the tag
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 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 authenticated_stream_cipher(data, key, nonce, additional_data='', post_processing_steps=STATE_SIZE): hash_input = key + nonce + additional_data for index, block in enumerate(slide(data, STATE_SIZE)): key_stream = bytearray(hash_function(hash_input, post_processing_steps=post_processing_steps)) xor_subroutine(block, key_stream) store(data, block, index) hash_input = key + nonce + block return hash_function(hash_input, post_processing_steps=post_processing_steps)
def crypt_stream(plaintext, key, nonce, rounds=16): data = bytearray(plaintext) data_size = len(data) output = bytearray() _stream_cipher(bytearray(nonce), bytearray(key), output, data_size, rounds) xor_subroutine(data, output) return bytes(data)
def stream_cipher(plaintext, key, seed, wordsize=8): # make state 2x key # 4 instances of 5-8 bit words via SIMD would be scalable? # 80-bit prng key, 160 bit state (5 * 8 = 40 * 4 = 160) # optional seed key for increased key bits? prng_key, seed_key = key assert len(seed) == 20 assert len(seed_key) == 20 assert len(prng_key) == 10 seed = list(seed) xor_subroutine(seed, seed_key) key = prng_key size = 5 state = bytearray(plaintext) plaintext_size = len(state) plaintext_index = 0 break_flag = False # requires one round warmup for full diffusion # a + b, a + c, a + d # b + c, b + d # c + d assert size - 1 for index in range(size - 1): for index2 in range(index, size): #add_key(seed, index, index2, key) constants = itertools.cycle((index + 1, index2 + 2)) add_constant(seed, index, index2, constants) permutation(seed, key, index, index2, wordsize) transposition(seed) while True: for index in range(size - 1): for index2 in range(index + 1, size): #add_key(seed, index, index2, key) constants = itertools.cycle((index, index2)) add_constant(seed, index, index2, constants) permutation(seed, key, index, index2, wordsize) combine_key_stream(state, seed, plaintext_index, index, index2) transposition(seed) plaintext_index += 4 if plaintext_index >= plaintext_size: break_flag = True break if break_flag: break if break_flag: break try: plaintext[:] = state except TypeError: pass return state
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 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 decrypt(data, key, parity=1): state = bytes_to_words(data[:32], 4) invert_keyed_bit_transposition(state, bytes_to_words(key[32:64], 4)) data[:32] = words_to_bytes(state, 4) random_mask = data[32:64] if parity: xor_subroutine(random_mask, key[:32]) xor_subroutine(data, random_mask) del data[32:64] return data
def authenticated_stream_cipher_decrypt(data, key, nonce, additional_data, tag): hash_input = key + nonce + additional_data for index, block in enumerate(slide(data, HASH_SIZE)): key_stream = bytearray(hash_function(hash_input)) hash_input = key + nonce + block xor_subroutine(block, key_stream) store(data, block, index) if hash_function(hash_input) == tag: return True else: return False
def authenticated_stream_cipher(data, key, nonce, additional_data=''): hash_input = key + nonce + additional_data for index, block in enumerate(slide(data, HASH_SIZE)): print "Hash input: ", hash_input key_stream = bytearray(hash_function(hash_input)) print "Generated key stream: ", key_stream raise SystemExit() xor_subroutine(block, key_stream) #print "After xor : ", block store(data, block, index) hash_input = key + nonce + block return hash_function(hash_input)
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 decrypt(data, key, rounds=2): state = bytes_to_words(data, WORDSIZE) _key = bytes_to_words(key, WORDSIZE) keys = key_schedule(_key, rounds) xor_subroutine(state, keys[0]) for round in reversed(range(rounds)): invert_permutation512(state, keys[round + 1]) xor_subroutine(state, keys[0]) data[:] = words_to_bytes(state, WORDSIZE)
def encrypt(plaintext, key, wordsize=WORDSIZE, rounds=ROUNDS): # 128 bit state assert len(key) == KEY_SIZE assert isinstance(plaintext, bytearray) xor_subroutine(plaintext, key) a, b, c, d = plaintext[:4], plaintext[4:8], plaintext[8:12], plaintext[12:16] for round in range(rounds): add_constants(a, b, c, d, key, round) mix_state(a, b, c, d) plaintext[:] = a + b + c + d xor_subroutine(plaintext, key) return plaintext
def encrypt(data, key, nonce, rounds=1): state = _setup_state_encrypt(key, nonce, rounds) blocksize = 32 ciphertext = bytearray() for index, block in enumerate(slide(bytearray(data), 32)): xor_subroutine(block, state[:32]) ciphertext.extend(block) state[index * blocksize:(index * blocksize) + len(block)] = block core(state, rounds) return state[:32], ciphertext
def decrypt(data, key, rounds=2): state = bytes_to_words(data, 4) _key = bytes_to_words(key, 4) keys = key_schedule(_key, rounds) xor_subroutine(state, keys[0]) for round in reversed(range(rounds)): invert_permutation256(state) invert_keyed_bit_transposition(state, keys[round + 1]) xor_subroutine(state, keys[0]) data[:] = words_to_bytes(state, 4)
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 encrypt(plaintext, key, wordsize=WORDSIZE, rounds=ROUNDS): assert len(key) == KEY_SIZE assert isinstance(plaintext, bytearray) assert len(plaintext) == 16, (len(plaintext), plaintext) xor_subroutine(plaintext, key) a, b, c, d = [bytes_to_integer(word) for word in slide(plaintext, 4)] # this conversion makes this version slower then the 8-bit python version for round in range(rounds): a, b, c, d = add_constants(a, b, c, d, round) a, b, c, d = sbox_layer(a, b, c, d) a, b, c, d = mix_state(a, b, c, d) plaintext[:] = integer_to_bytes(a, 4) + integer_to_bytes(b, 4) + integer_to_bytes(c, 4) + integer_to_bytes(d, 4) xor_subroutine(plaintext, key) return plaintext
def _setup_state_encrypt(key, nonce, rounds): # absorb key assert 16 <= len(key) <= 32 state = initialize_state(bytearray(key)) core(state, rounds) print sum(format(byte, 'b').count('1') for byte in state) # absorb nonce assert 8 <= len(nonce) <= 32 nonce = bytearray(nonce) xor_subroutine(state, nonce) state[:len(nonce)] = nonce core(state, rounds) print sum(format(byte, 'b').count('1') for byte in state) return state
def authenticated_stream_cipher(data, key, nonce, additional_data='', post_processing_steps=STATE_SIZE): hash_input = key + nonce + additional_data for index, block in enumerate(slide(data, STATE_SIZE)): key_stream = bytearray( hash_function(hash_input, post_processing_steps=post_processing_steps)) xor_subroutine(block, key_stream) store(data, block, index) hash_input = key + nonce + block return hash_function(hash_input, post_processing_steps=post_processing_steps)
def test_encrypt8_decrypt8(): key = (123, 456, 789, 101112) byte = 0 ciphertext = encrypt8(byte, key) plaintext = decrypt8(ciphertext, key) assert plaintext == byte byte2 = 1 ciphertext2 = encrypt8(byte2, key) plaintext2 = decrypt8(ciphertext2, key) assert plaintext2 == byte2 xor_subroutine(ciphertext, ciphertext2) plaintext3 = decrypt8(ciphertext, key) assert plaintext3 == byte2, (plaintext3, byte2)
def decrypt(tag, data, key, nonce, rounds=1): state = _setup_state_encrypt(key, nonce, rounds) blocksize = 32 plaintext = bytearray() for index, block in enumerate(slide(bytearray(data), 32)): _block = block[:] xor_subroutine(block, state[:32]) plaintext.extend(block) state[index * blocksize:(index * blocksize) + len(block)] = _block core(state, rounds) if tag != state[:32]: return -1 # raising exceptions takes notably longer then not raising one in python else: return plaintext
def xor_test(message, key, direction): xor_subroutine(message, key) state = xor_sum(message) size = len(message) - 1 index = 0 if direction == 1 else size for counter in range(len(message)): state ^= message[index] random_place = state & size message[index] ^= (state + key[random_place] + ephemeral_byte) % 256 #message[index] ^= key[random_place & (index - 1)] ^ random_place ^ state state ^= message[index] index += direction xor_subroutine(message, key)
def stream_cipher(plaintext, key, seed, modulus=2 ** 32, wordsize=32): # make state 2x key. 256 bit key, 512 bit state. 8 64-bit words, or 16-32 bit words # 4 instances of 4-32 bit words via SIMD would keep the latency low # 4 instances of 4-8 bit words via SIMD would be scalable? prng_key, seed_key = key seed = seed[:] xor_subroutine(seed, seed_key) key = itertools.cycle(prng_key) size = len(seed) state = bytes_to_words(bytearray(plaintext), 4) plaintext_size = len(state) plaintext_index = 0 break_flag = False # requires one round warmup for full diffusion # a + b, a + c, a + d # b + c, b + d # c + d assert size - 1 for index in range(size - 1): for index2 in range(index + 1, size): permutation(seed, index, index2, key, modulus, wordsize) while True: for index in range(size - 1): for index2 in range(index + 1, size): permutation(seed, index, index2, key, modulus, wordsize) state[plaintext_index] ^= (seed[index] + seed[index2]) % modulus plaintext_index += 1 if plaintext_index == plaintext_size: break_flag = True break if break_flag: break if break_flag: break _plaintext = words_to_bytes(state, 4) try: plaintext[:] = _plaintext except TypeError: pass return _plaintext
def decrypt(data, tag, iv, key, associated_data='', hash_function=hash_function, invert_permutation=arxcalibur512.invert_permutation, rounds=ROUNDS): block_key = tag[:] xor_subroutine(block_key, key) blocks = (block for block in reversed(list(slide(data, 8)))) for block_count, ciphertext in enumerate(blocks): state = ciphertext + block_key for round in reversed(range(rounds)): state = invert_permutation(*[round, ] + state) _store_block(data, block_count, state[:8]) block_key = list(state[8:]) if list(data[8:16]) == iv and hash_function(associated_data) == data[-8:]: remove_padding(data, 32) return True else: return False
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 encrypt(data, iv, key, associated_data='', hash_function=hash_function, permutation=arxcalibur512.permutation, rounds=ROUNDS): block_key = key assert len(block_key) == 8 assert len(iv) == 8 assert not len(data) % 8 blocks = (block for block in slide(hash_function(associated_data) + iv + data, 8)) for block_count, block in enumerate(blocks): state = block + block_key for round in range(rounds): state = permutation(*[round, ] + state) _store_block(data, block_count, state[:8]) block_key = list(state[8:]) assert len(block_key) == len(key) xor_subroutine(block_key, key) return block_key # block_key is the tag