def mixing_operation(interval, b, c, d): """Perform one of four operations, based on the interval. The b, c, and d arguments are SHA-1 sub-registers. """ if 0 <= interval <= 19: return bitwise_or(bitwise_and(b, c), bitwise_and(bitwise_not(b), d)) elif interval <= 39: return bitwise_xor(b, c, d) elif interval <= 59: return bitwise_or(bitwise_and(b, c), bitwise_and(b, d), bitwise_and(c, d)) elif interval <= 79: return bitwise_xor(b, c, d) else: raise Exception('Interval out of bounds')
def ff_mult(binary1, binary2): """Multiply two binary strings in the GF(2^8) finite field.""" return bitwise_xor(*[ times_x(binary2, power) for power, bit in reversed(list(enumerate(reversed(binary1)))) if bit == '1' ])
def feistel_function(half_block, key): """Perform confusion and diffusion on a 32-bit binary string.""" expanded = permute(half_block, EXPANSION_PERMUTATION) xored = bitwise_xor(expanded, key) b_sections = [xored[place:place + 6] for place in xrange(0, 48, 6)] c_sections = [apply_s_box(section, S_BOXES[number]) for number, section in enumerate(b_sections)] return permute(''.join(c_sections), C_PERMUTATION)
def times_x(binary, power=1): """Multiply a binary string by X^P in the GF(2^8) finite field.""" for _ in xrange(power): binary += '0' if binary[0] == '1': # X^8 overflow binary = bitwise_xor(binary, '100011011') binary = binary[1:] return binary
def feistel_function(half_block, key): """Perform confusion and diffusion on a 32-bit binary string.""" expanded = permute(half_block, EXPANSION_PERMUTATION) xored = bitwise_xor(expanded, key) b_sections = [xored[place:place + 6] for place in xrange(0, 48, 6)] c_sections = [ apply_s_box(section, S_BOXES[number]) for number, section in enumerate(b_sections) ] return permute(''.join(c_sections), C_PERMUTATION)
def mix_columns(block_matrix, mix_matrix): """Multiply two matrixes in the GF(2^8) finite field. The first argument should be the the current block state, the right argument a transformation constant (COLUMN_MIX for encryption, INVERSE_COLUMN_MIX for decryption). """ return [[bitwise_xor(*[ff_mult(mix_matrix[row][index], block_matrix[index][column]) for index in xrange(MATRIX_SIZE)]) for column in xrange(MATRIX_SIZE)] for row in xrange(MATRIX_SIZE)]
def mix_columns(block_matrix, mix_matrix): """Multiply two matrixes in the GF(2^8) finite field. The first argument should be the the current block state, the right argument a transformation constant (COLUMN_MIX for encryption, INVERSE_COLUMN_MIX for decryption). """ return [[ bitwise_xor(*[ ff_mult(mix_matrix[row][index], block_matrix[index][column]) for index in xrange(MATRIX_SIZE) ]) for column in xrange(MATRIX_SIZE) ] for row in xrange(MATRIX_SIZE)]
def sha_1_expansion(block): """Take a 512 bit binary message and convert it into a series of 32 bit blocks. """ sub_blocks = block_split(block, SUB_BLOCKSIZE) for interval in xrange(len(sub_blocks), SHA_1_INTERVALS): new_sub_block = bitwise_xor(sub_blocks[interval - 3], sub_blocks[interval - 8], sub_blocks[interval - 14], sub_blocks[interval - 16]) sub_blocks.append(wrap_bits_left(new_sub_block, 1)) return sub_blocks
def feistel_scheme(binary_text, subkeys): """Run the DES algorithm on a each block of the string input text. The subkeys parameter should be a list of sixteen 48-bit binary strings. """ final_blocks = [] for block in block_split(binary_text): block = permute(block, INITIAL_PERMUTATION) left, right = half_string(block) for key in subkeys: right, left = bitwise_xor(left, feistel_function(right, key)), right block = permute(right + left, FINAL_PERMUTATION) final_blocks.append(block) return ''.join(final_blocks)
def transform_subkey(column, column_number): """Obfuscate a key column of length four.""" shifted = rotate(column, 1) s_boxed = [apply_s_box(byte, S_BOX) for byte in shifted] return ([bitwise_xor(s_boxed[0], round_constant(column_number))] + s_boxed[1:])
def add_round_key(block_matrix, key_matrix): """XOR two matrixes to produce a single matrix of the same size.""" return [[bitwise_xor(element1, element2) for element1, element2 in zip(row1, row2)] for row1, row2 in zip(block_matrix, key_matrix)]
def xor_columns(column1, column2): return [bitwise_xor(element1, element2) for element1, element2 in zip(column1, column2)]
def add_round_key(block_matrix, key_matrix): """XOR two matrixes to produce a single matrix of the same size.""" return [[ bitwise_xor(element1, element2) for element1, element2 in zip(row1, row2) ] for row1, row2 in zip(block_matrix, key_matrix)]
def xor_columns(column1, column2): return [ bitwise_xor(element1, element2) for element1, element2 in zip(column1, column2) ]
def ff_mult(binary1, binary2): """Multiply two binary strings in the GF(2^8) finite field.""" return bitwise_xor(*[times_x(binary2, power) for power, bit in reversed(list(enumerate(reversed(binary1)))) if bit == '1'])