def one_way_function_base_conversion(old_value, tweak=ASCII_CONSTANT): new_base = tweak old_base_mapping = {} old_value = ''.join(reversed(bytes(old_value))) for index, symbol in enumerate(slide(old_value, 2)): old_base_mapping[symbol] = index _old_value = bytearray(old_value) xor_key = xor_sum(_old_value) old_base_size = len(old_base_mapping) decimal_value = (xor_key + sum(((xor_key ^ old_base_mapping[value_representation]) * (old_base_size ** power) for power, value_representation in enumerate(slide(old_value, 2))))) #decimal_value = xor_key #for power, value_representation in enumerate(slide(old_value, 2)): # decimal_value += (xor_key ^ old_base_mapping[value_representation]) * (old_base_size ** power) new_value = '' new_base_size = len(new_base) new_value = '' while decimal_value > 0 or not new_value: # divmod = divide and modulo in one action decimal_value, digit = divmod(decimal_value, new_base_size) new_value += new_base[digit] return ''.join(reversed(new_value))
def slow_hash(seed, tweak, rounds=1, output_size=32, tables=256): seed = bytearray(null_pad(seed, 256)) state = seed[0] _rows = [rotate(tweak, amount) for amount in xrange(tables)] for round in range(rounds): for i in reversed(range(1, 256)): for rows in slide(_rows, 256): for row in rows: j = state & (i - 1) row[i], row[j] = row[j], row[i] random_row = rows[j] row[j], random_row[j] = random_row[j], row[j] seed[i] ^= random_row[row[j]] ^ row[random_row[j]] state ^= seed[i] ^ seed[j] ^ row[i] ^ random_row[i] i = 0 for rows in slide(_rows, 256): for row in rows: seed[i] ^= random_row[row[j]] ^ row[random_row[j]] state ^= seed[i] ^ seed[j] ^ row[i] ^ random_row[i] output = [] for index in range(output_size): output.append(seed[rows[index][index]]) return bytearray(output)
def decrypt(data, cipher, iv, tag=None, tweak=None): #key, iv, cipher, mode_of_operation, tweak=None): mode = cipher.mode #if mode != "ella": # assert not tag, (mode, data, cipher, iv, tag) if mode in ("cbc", "ella", "ecb"): crypt_block = cipher.decrypt_block if mode == "ella": data = ''.join( reversed( [block for block in slide(bytes(data), cipher.blocksize)])) else: crypt_block = cipher.encrypt_block #data = bytearray(data) crypt(data, cipher.key, iv, crypt_block, DECRYPTION_MODES[mode], cipher.blocksize, tag, tweak) if mode == "ella": if tag != cipher.mac_key: raise InvalidTag() return ''.join( reversed([block for block in slide(bytes(data), cipher.blocksize)])) elif mode in ("cbc", "ecb"): padding_amount = data[-1] return bytes(data)[:-(padding_amount or cipher.blocksize)] else: return bytes(data)
def one_way_function_base_conversion(old_value, tweak=ASCII_CONSTANT): new_base = tweak old_base_mapping = {} old_value = ''.join(reversed(bytes(old_value))) for index, symbol in enumerate(slide(old_value, 2)): old_base_mapping[symbol] = index _old_value = bytearray(old_value) xor_key = xor_sum(_old_value) old_base_size = len(old_base_mapping) decimal_value = (xor_key + sum( ((xor_key ^ old_base_mapping[value_representation]) * (old_base_size**power) for power, value_representation in enumerate(slide(old_value, 2))))) #decimal_value = xor_key #for power, value_representation in enumerate(slide(old_value, 2)): # decimal_value += (xor_key ^ old_base_mapping[value_representation]) * (old_base_size ** power) new_value = '' new_base_size = len(new_base) new_value = '' while decimal_value > 0 or not new_value: # divmod = divide and modulo in one action decimal_value, digit = divmod(decimal_value, new_base_size) new_value += new_base[digit] return ''.join(reversed(new_value))
def _test_random_data(): import os outputs = [] for key_count, key in enumerate(slide(os.urandom(16 * 256), 16)): ciphertext = os.urandom(16 * 65535) pride.functions.utilities.print_in_place(str(key_count / 256.0) + '% complete; Current bias: {}'.format(float(outputs.count(1)) / (outputs.count(0) or 1))) for index, block in enumerate(slide(os.urandom(16 * 65535), 16)): outputs.append(1 if xor_parity(block) ^ xor_parity(ciphertext[index * 16:(index + 1) * 16]) else 0) zero_bits = outputs.count(0) one_bits = outputs.count(1) print float(one_bits) / zero_bits, one_bits, zero_bits
def encrypt(plaintext, key, wordsize=WORDSIZE, rounds=ROUNDS): # 128 bit state assert len(key) == KEY_SIZE assert isinstance(plaintext, bytearray) assert len(plaintext) == 16, (len(plaintext), plaintext) 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 key = [bytes_to_integer(word) for word in slide(key, 4)] for round in range(rounds): a, b, c, d = add_key_and_constants(a, b, c, d, key, 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) return plaintext
def decrypt(ciphertext, key, function, input_block_size, mode_of_operation=xor_with_key, key_rotation=all_or_nothing, output_block_size=1): """ Decrypt the ciphertext hash chain as produced by encrypt. The amount of work and therefore time taken to recover the plaintext increases dramatically as output_block_size is incremented. The output_block_size argument must be set to the same value used by the server or the decryption will fail. """ test_bytes = [RANGE_256 for count in range(output_block_size)] plaintext = plaintext_block = '' for ciphertext_block in slide(ciphertext, input_block_size): (plaintext_block, ciphertext_block, key, function) = mode_of_operation(plaintext_block, ciphertext_block, key, function) plaintext_block = brute_force(ciphertext_block, function, test_bytes, key) plaintext += plaintext_block (plaintext_block, ciphertext_block, key, function) = key_rotation(plaintext_block, ciphertext_block, key, function) return plaintext
def sponge_function(hash_input, key='', output_size=32, capacity=32, rate=32, mixing_subroutine=None, mode_of_operation=variable_length_hash, absorb_mode=xor_subroutine): assert mixing_subroutine is not None #print "Hashing: ", [byte for byte in hash_input] if isinstance(rate, int): rate = slice(0, rate) if isinstance(capacity, int): end_of_rate = rate.stop capacity = slice(end_of_rate, end_of_rate + capacity) state_size = capacity.stop state = bytearray(state_size) if key: absorb(key, state, rate, mixing_subroutine, absorb_mode) rate_in_bytes = rate.stop - rate.start hash_input = pad_input(bytearray(hash_input), rate_in_bytes) #print "\nBeginning absorption", [byte for byte in hash_input] for _bytes in slide(hash_input, rate_in_bytes): #print "Absorbing: ", [byte for byte in _bytes] absorb(_bytes, state, rate, mixing_subroutine, absorb_mode) # print "\nBeginning final mix before mode of operation: ", [byte for byte in state] mixing_subroutine(state) # print "State: ", [byte for byte in state] return mode_of_operation(state, rate, output_size, mixing_subroutine, absorb_mode)
def find_duplicate_via_prng(): import random import itertools from crypto.utilities import slide, bytes_to_longs from crypto.designs.nonlinear.ciphercomponents import optimized_bit_byte_transposition_words as prng_of_hamming_weight sample_size = 16 weight = 64 test_sample = list(('1' * weight).zfill(128)) target_sample = bytearray(16) while sum(format(byte, 'b').zfill(8).count('1') for byte in target_sample) != weight: target_sample[:] = urandom(16) random.shuffle(test_sample) test_sample = tuple(int(word, 2) for word in slide(''.join(test_sample), 32)) target_sample = bytes_to_longs(target_sample) failed = True outputs = set() for counter in itertools.count(): if test_sample == target_sample: break if test_sample in outputs: print "Entered cycle after {} without finding target".format(counter) outputs.remove(test_sample) failed = True #break else: outputs.add(test_sample) test_sample = prng_of_hamming_weight(*test_sample) else: print "Failed to find identical sample after 2 ** {}".format(log(counter, 2)) failed = True if not failed: print "Regenerated identical samples after: {} (2 ** {})".format(counter, log(counter, 2))
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 encrypt(plaintext, key, wordsize=WORDSIZE, rounds=ROUNDS): # 128 bit state assert len(key) == KEY_SIZE assert isinstance(plaintext, bytearray) assert len(plaintext) == 16, (len(plaintext), plaintext) 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 key = [bytes_to_integer(word) for word in slide(key, 4)] for round in range(rounds): a, b, c, d = add_key_and_constants(a, b, c, d, key, 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) 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 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 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 _test_random_data(): import os outputs = [] for key_count, key in enumerate(slide(os.urandom(16 * 256), 16)): ciphertext = os.urandom(16 * 65535) pride.functions.utilities.print_in_place( str(key_count / 256.0) + '% complete; Current bias: {}'.format( float(outputs.count(1)) / (outputs.count(0) or 1))) for index, block in enumerate(slide(os.urandom(16 * 65535), 16)): outputs.append(1 if xor_parity(block) ^ xor_parity(ciphertext[index * 16:(index + 1) * 16]) else 0) zero_bits = outputs.count(0) one_bits = outputs.count(1) print float(one_bits) / zero_bits, one_bits, zero_bits
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 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 encrypt(data, key, iv, mixing_subroutine, rate=32, **kwargs): encryptor = sponge_function(iv, key, mixing_subroutine=mixing_subroutine, mode_of_operation=encryption_mode, **kwargs) next(encryptor) return ''.join(encryptor.send(block) for block in slide(data, rate))
def hamming_weight_hash(data, output_size=32): accumulator = 0 data = bytearray(pad_input(data[:], 32)) output = bytearray(output_size) for counter, word in enumerate(slide(data, 4)): word_weight = hamming_weight(cast(word, "integer")) accumulator += word_weight + choice(accumulator, word_weight, counter) + counter output[counter] = (output[counter] + accumulator) return output
def unpack_exponents(exponent_string): output = [] generator = (half_byte for half_byte in slide(exponent_string, 4)) while True: try: half_byte = next(generator) except StopIteration: break else: if not half_byte & 8: output.append(accumulator) else: accumulator += half_byte & 7 for half_byte in slide(exponent_string, 4): if half_byte & 8: return [int(half_byte, 2) for half_byte in slide(exponent_string, 4)]
def cipher(message, key, iv=None, mode=None): data = bytearray(message) key = bytearray(key) if iv is not None: addition_subroutine(data, bytearray(iv), 256) output = bytearray() for block in slide(data, 16): addition_subroutine(block, output[-16:], 256) output.extend(encrypt(block, key, rounds=4)) return output
def permute_hash(data, rounds=1, blocksize=16): data = list(bytearray(pad_input(data, blocksize))) output = [0 for byte in range(blocksize)] key = data[:blocksize] for round in range(rounds): for data_block in slide(data, blocksize): permutation(data_block, key) key = data_block return bytes(bytearray((byte >> 8) ^ (byte & 255) for byte in data_block))
def compression_function(data, rounds=ROUNDS): output = [0, 0, 0, 0] for a, b, c, d in slide(bytes_to_words(data, 8), 4): a ^= output[0]; b ^= output[1]; c ^= output[2]; d ^= output[3]; for round in range(rounds): a, b, c, d = sbox(a, b, c, d) a, b, c, d = linear_layer(a, b, c, d) output[0] ^= a; output[1] ^= b; output[2] ^= c; output[3] ^= d; return bytes(words_to_bytes(output, 8))
def decrypt2(ciphertext, iv, key, work_factor1=1, hash_function=tunable_hash): """ usage: decrypt2(ciphertext, iv, key, work_factor1=1, hash_function=tunable_hash) => plaintext Fast decryption function for corresponding slow encryption function. work_factor1 has effectively no influence on computation time.""" digest_size = len(hash_function('')) plaintext = b'' for hash_input in slide(ciphertext, digest_size): plaintext += hash_function(hash_input)[:work_factor1] return plaintext
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 generate_key_stream(key, nonce, block_count): for index, byte in enumerate(key): nonce[index] ^= byte state = [block128 for block128 in slide(bytes_to_words(nonce, 4), 4)] output = [] while len(output) < block_count: for round in range(2): state = mix_blocks(*state) output.extend(state[0] + state[1] + state[2] + state[3]) return words_to_bytes(output, 4)
def compression_function(data): o0, o1, o2, o3 = 0, 1, 8 , 64 for a, b, c, d in slide(bytes_to_words(data, 4), 4): a, b, c, d = mix_words(a, b, c, d) s0, s1, s2, s3 = mix_words(a, 1, 8, 64) s0, s1, s2, s3 = mix_words(s0, b, s1, s3) s0, s1, s2, s3 = mix_words(s0, s1, c, s3) s0, s1, s2, s3 = mix_words(s0, s1, s2, d) o0 ^= s0; o1 ^= s1; o2 ^= s2; o3 ^= s3; return words_to_bytes((o0, o1, o2, o3), 4)
def print_4x4_state(inputs, bits): weight_total = 0 print inputs for words in slide(inputs, 4): bit_string = weight_string = '' for word in words: weight = hamming_weight(word) weight_total += weight bit_string += ''.join(bit for bit in format(word, 'b').zfill(bits)) + ' ' weight_string += "({}/{}) ".format(weight, bits) print("{} {}".format(bit_string, weight_string)) print("{} ({}/{})".format(' ' * ((len("({}/{}) ") * 3) + 4 + (bits * 4)), weight_total, (bits * len(inputs))))
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 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(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 compression_function(data): o0, o1, o2, o3 = 0, 1, 8, 64 for a, b, c, d in slide(bytes_to_words(data, 4), 4): a, b, c, d = mix_words(a, b, c, d) s0, s1, s2, s3 = mix_words(a, 1, 8, 64) s0, s1, s2, s3 = mix_words(s0, b, s1, s3) s0, s1, s2, s3 = mix_words(s0, s1, c, s3) s0, s1, s2, s3 = mix_words(s0, s1, s2, d) o0 ^= s0 o1 ^= s1 o2 ^= s2 o3 ^= s3 return words_to_bytes((o0, o1, o2, o3), 4)
def compression_function(data, rounds=ROUNDS): data = bytes_to_words(data, 8) # convert 8-bit words to 64-bit words a, b, c, d = (0, 0, 0, 0) counter = 1 for in0, in1, in2, in3 in slide(data, 4): # work on 4 64-bit words at a time (256 bit state) # print "Digesting: ", in0, in1, in2, in3 a, b, c, d = add_block(a, b, c, d, in0, in1, in2, in3, counter) assert counter <= INTEGER64_OVERFLOW for round in range(rounds): a, b, c, d = round_function(a, b, c, d) a, b, c, d = add_block(a, b, c, d, in0, in1, in2, in3, counter) counter += 1 a, b, c, d = round_function(a, b, c, d) return bytes(words_to_bytes((a, b, c, d), 8))
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 p_box(input_bytes): """ Data concentrating permutation box. Evenly distributes input bits amongst output. """ bits = cast(bytes(input_bytes), "binary") # if a 64 bit block was acceptable, the operation would be this simple: # for index, byte in enumerate(int(bits[index::8], 2) for index in range(8)): # input_bytes[index] = byte bit_count = len(bits) word_size = bit_count / 8 word_size_in_bytes = word_size / 8 for index in range(8): bits_at_index = bits[index::word_size] _index = index * word_size_in_bytes for offset, _bits in enumerate(slide(bits_at_index, 8)): input_bytes[_index + offset] = int(_bits, 2)
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 _decrypt(ciphertext, key, iv, work_factor, hash_function): """ usage: decrypt(ciphertext, key, iv, work_factor, hash_function) => plaintext Slow decryption function for corresponding fast(er) encryption function. - Incrementing work factor increases decryption cost exponentially""" plaintext = b'' test_bytes = [bytes(bytearray(range(256))) for factor in range(work_factor)] block_size = len(hash_function('')) for ciphertext_bytes in slide(ciphertext, block_size): data_bytes = brute_force(ciphertext_bytes, hash_function, test_bytes, prefix=plaintext + key + iv) plaintext += data_bytes[-work_factor:] return plaintext
def _encrypt(data, key, iv, work_factor, hash_function): """ usage: encrypt(data, key, iv, work_factor, hash_function) => ciphertext Encrypt data in a way that decryption takes significantly more computational expense then encryption, based on work_factor. - Incrementing work factor increases decryption cost exponentially Ciphertext will be (len(data) / work_factor) * digest_size bytes in size. """ ciphertext = b'' cumulative_input = b'' for data_bytes in slide(data, work_factor): output = hash_function(cumulative_input + key + iv + data_bytes) ciphertext += output cumulative_input += data_bytes return ciphertext
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 encrypt(plaintext, key, function, mode_of_operation=xor_with_key, key_rotation=all_or_nothing, input_block_size=1): """ An encryption function with an associated work factor. Returns a ciphertext encrypted under key. The input_block_size adjusts two factors: First, by a smaller amount, as input_block_size increases, generating the challenge tends to take less time. Second, as input_block_size increases, solving the challenge tends to take significantly more time. As an example, consider a server that requires proof of work with each request submitted by a client. An overloaded server could increment the bytes per hash to crack. As a result, it would spend less time generating each challenge, while clients would take significantly longer to solve each challenge. The net effect is an actual reduction in traffic, as clients cannot effectively make additional requests until the current challenge is solved. Note that output block size is determined implicitly by the function used, and is not otherwise configurable. As a result, when used with hash functions, ciphertext is necessarily significantly larger then the input plaintext.""" if len(plaintext) % input_block_size: raise ValueError("Plaintext length not a multiple of input_block_size") ciphertext = '' for plaintext_block in slide(plaintext, input_block_size): ciphertext_block = function(key, plaintext_block) (plaintext_block, ciphertext_block, key, function) = mode_of_operation(plaintext_block, ciphertext_block, key, function) ciphertext += ciphertext_block (plaintext_block, ciphertext_block, key, function) = key_rotation(plaintext_block, ciphertext_block, key, function) return ciphertext
def _print_active_sbox_info(function, function_args, bit_width=64, active_bytes=True, active_bits=True, bit_strings=True): output = function(*function_args) bits = [' '.join(slide(format(word, 'b').zfill(bit_width), 8)) for word in output] if active_bytes: for bit_string in bits: actives = [(index, byte) for index, byte in enumerate(bit_string.split()) if '1' in byte] print "Non-zero bytes: {} {}".format(len(actives), [index for index, byte in actives]) if bit_strings: for word in bits: print word if active_bits: for word in bits: actives = [index for index, bit in enumerate(''.join(word.split())) if bit == '1'] print "Set bits: {} {}".format(len(actives), actives) return output
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 quints_to_bytes(hash_output): bits = ''.join(format(word, 'b').zfill(5) for word in hash_output) return bytearray(int(_bits, 2) for _bits in slide(bits, 8))