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 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.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 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 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) return mode_of_operation(state, rate, output_size, mixing_subroutine, absorb_mode)
def decrypt(ciphertexts, key, rounds=1, modulus=256, blocksize=16): output = bytearray() key = [modular_inverse(item | 1, modulus) for item in key] for index, block in enumerate(slide(ciphertexts, 2)): block[1] = (block[1] * key[1]) % modulus block[0] = (block[0] * key[0]) % modulus block[0] = modular_subtraction(block[0], block[1], modulus) output.append(block[0]) return output
def decrypt(ciphertexts, private_key, blocksize=BLOCKSIZE, decryption_function=secretkey.decrypt): """ usage: decrypt(ciphertexts : bytearray, private_key : bytearray, blocksize=BLOCKSIZE, decryption_function=secretkey.decrypt) => plaintext : bytearray Private key decryption function based on homomorphic encryption/decryption. """ message = []#bytearray() for ciphertext_byte in slide(ciphertexts, blocksize): plaintext_byte = decryption_function(ciphertext_byte, private_key) message.append(plaintext_byte[0]) return message
def decrypt(ciphertexts, key, rounds=5, modulus=DEFAULT_MODULUS): """ usage: decrypt(ciphertexts, key, rounds=5, modulus=DEFAULT_MODULUS) => plaintext Given ciphertexts and key, return plaintexts. """ output = [] for ciphertext in slide(ciphertexts, 2 ** rounds): multiplication_subroutine(ciphertext, [modular_inverse(item | 1, modulus) for item in key], modulus) for round in range(rounds): ciphertext[:] = decode(ciphertext, modulus) output.append(ciphertext[0]) return output
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 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 decrypt_then_mac(ciphertexts, private_key, blocksize=32, tag_size=64, integrity_key_size=32, decryption_function=secret_key_decrypt): tag = bytearray(ciphertext[-tag_size:]) ciphertexts = ciphertext[:-tag_size] _ciphertexts = [load_ciphertext(ciphertext) for ciphertext in slide(ciphertexts, blocksize)] # is this right? message = decryption_function(_ciphertexts[0], private_key) integrity_key = decryption_function(_ciphertexts[-1], private_key) _tag = hmac(integrity_key, ciphertexts) if compare_digest(_tag, tag): return message else: return None
def decrypt(ciphertexts, key, rounds=5, modulus=DEFAULT_MODULUS): """ usage: decrypt(ciphertexts, key, rounds=5, modulus=DEFAULT_MODULUS) => plaintext Given ciphertexts and key, return plaintexts. """ output = [] for ciphertext in slide(ciphertexts, 2**rounds): multiplication_subroutine( ciphertext, [modular_inverse(item | 1, modulus) for item in key], modulus) for round in range(rounds): ciphertext[:] = decode(ciphertext, modulus) output.append(ciphertext[0]) return output
def decrypt(ciphertexts, private_key, blocksize=BLOCKSIZE, decryption_function=secretkey.decrypt): """ usage: decrypt(ciphertexts : bytearray, private_key : bytearray, blocksize=BLOCKSIZE, decryption_function=secretkey.decrypt) => plaintext : bytearray Private key decryption function based on homomorphic encryption/decryption. """ message = [] #bytearray() for ciphertext_byte in slide(ciphertexts, blocksize): plaintext_byte = decryption_function(ciphertext_byte, private_key) message.append(plaintext_byte[0]) return message
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_then_mac(ciphertexts, private_key, blocksize=32, tag_size=64, integrity_key_size=32, decryption_function=secret_key_decrypt): tag = bytearray(ciphertext[-tag_size:]) ciphertexts = ciphertext[:-tag_size] _ciphertexts = [ load_ciphertext(ciphertext) for ciphertext in slide(ciphertexts, blocksize) ] # is this right? message = decryption_function(_ciphertexts[0], private_key) integrity_key = decryption_function(_ciphertexts[-1], private_key) _tag = hmac(integrity_key, ciphertexts) if compare_digest(_tag, tag): return message else: return None
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 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 crypt(data, key, iv, cipher, mode_of_operation, blocksize, tag, tweak): output = bytearray() for block in slide(data, blocksize): mode_of_operation(block, iv, key, cipher, tag, tweak) output.extend(block) replacement_subroutine(data, output)
def _print_state(state, message): print message for _bytes in slide(state, 4): print ' '.join(format(byte, 'b').zfill(4) for byte in _bytes) print
def load_ciphertext(saved_ciphertext): output = [] for entry in slide(bytearray(saved_ciphertext), BLOCKSIZE * 2): output.extend(bytes_to_words(entry, 2)) return output
def save_ciphertext(ciphertext): return ''.join( bytes(words_to_bytes(entry, 2)) for entry in slide(ciphertext, BLOCKSIZE))
def load_public_key(saved_key): output = [] for entry in slide(bytearray(saved_key), BLOCKSIZE * 2): output.extend(bytes_to_words(entry, 2)) return output
def save_public_key(public_key): return ''.join( bytes(words_to_bytes(entry, 2)) for entry in slide(public_key, BLOCKSIZE))
def load_public_key(saved_key): public_key = [] for line in slide(saved_key, 16): public_key.append(bytes_to_words(line, 4)) return public_key
def absorb(data, state, rate, mixing_subroutine, replacement_subroutine): for block in slide(bytearray(data), rate.stop - rate.start): replacement_subroutine(state, block) mixing_subroutine(state)
def save_public_key(public_key): return ''.join(bytes(words_to_bytes(entry, 2)) for entry in slide(public_key, BLOCKSIZE))
def decrypt(data, key, iv, mixing_subroutine, rate=32, **kwargs): decryptor = sponge_function(iv, key, mixing_subroutine=mixing_subroutine, mode_of_operation=decryption_mode, **kwargs) next(decryptor) return ''.join(decryptor.send(block) for block in slide(data, rate))
def save_ciphertext(ciphertext): return ''.join(bytes(words_to_bytes(entry, 2)) for entry in slide(ciphertext, BLOCKSIZE))
def print_state(self, state, message): print(message) for word in slide(state, 4): print(' '.join(format(byte, 'b').zfill(8) for byte in word)) print('')