def _compress(block, state, printdebug): # Check argument types and lengths assert isinstance(block, tuple) and len(block) == _BLOCK_SIZE assert isinstance(state, tuple) and len(state) == 4 # Pack block bytes into schedule as uint32 in little endian schedule = [0] * 16 for (i, b) in enumerate(block): assert 0 <= b <= 0xFF schedule[i // 4] |= b << ((i % 4) * 8) # Unpack state into variables; each one is a uint32 a, b, c, d = state # Perform 48 rounds of hashing for i in range(48): # Compute f value, schedule index, and addition constant based on the round index i if printdebug: print( f" Round {i:2d}: a={a:08X}, b={b:08X}, c={c:08X}, d={d:08X}" ) if i < 16: f = (b & c) | (~b & d) k = i add = 0x00000000 elif i < 32: f = (b & c) | (b & d) | (c & d) k = ((i & 0x3) << 2) | ((i & 0xC) >> 2) add = 0x5A827999 else: f = b ^ c ^ d k = ((i >> 3) & 0x1) | ((i >> 1) & 0x2) | ((i << 1) & 0x4) | ( (i << 3) & 0x8) # Last 4 bits reversed add = 0x6ED9EBA1 # Perform the round calculation rot = _ROTATION_AMOUNTS[((i >> 2) & 0xC) | (i & 0x3)] temp = (a + f + schedule[k] + add) & cryptocommon.UINT32_MASK temp = cryptocommon.rotate_left_uint32(temp, rot) a = d d = c c = b b = temp # Return new state as a tuple return ((state[0] + a) & cryptocommon.UINT32_MASK, (state[1] + b) & cryptocommon.UINT32_MASK, (state[2] + c) & cryptocommon.UINT32_MASK, (state[3] + d) & cryptocommon.UINT32_MASK)
def _compress(block, state, printdebug): # Check argument types and lengths assert type(block) == tuple and len(block) == _BLOCK_SIZE assert type(state) == tuple and len(state) == 4 # Pack block bytes into schedule as uint32 in little endian schedule = [0] * 16 for (i, b) in enumerate(block): assert 0 <= b <= 0xFF schedule[i // 4] |= b << ((i % 4) * 8) # Unpack state into variables; each one is a uint32 a, b, c, d = state # Perform 64 rounds of hashing for i in range(len(_ROUND_CONSTANTS)): # Compute f value and schedule index based on the round index i if printdebug: print( " Round {:2d}: a={:08X}, b={:08X}, c={:08X}, d={:08X}". format(i, a, b, c, d)) if i < 16: f = (b & c) | (~b & d) k = i elif i < 32: f = (d & b) | (~d & c) k = (5 * i + 1) % 16 elif i < 48: f = b ^ c ^ d k = (3 * i + 5) % 16 else: f = c ^ (b | ~d) k = (7 * i) % 16 # Perform the round calculation rot = _ROTATION_AMOUNTS[((i >> 2) & 0xC) | (i & 0x3)] temp = (a + f + schedule[k] + _ROUND_CONSTANTS[i]) & cryptocommon.UINT32_MASK temp = cryptocommon.rotate_left_uint32(temp, rot) a = d d = c c = b b = (b + temp) & cryptocommon.UINT32_MASK # Return new state as a tuple return ((state[0] + a) & cryptocommon.UINT32_MASK, (state[1] + b) & cryptocommon.UINT32_MASK, (state[2] + c) & cryptocommon.UINT32_MASK, (state[3] + d) & cryptocommon.UINT32_MASK)
def _compress(block, state, printdebug): # Check argument types and lengths assert isinstance(block, tuple) and len(block) == _BLOCK_SIZE assert isinstance(state, tuple) and len(state) == 4 # Pack block bytes into schedule as uint32 in little endian schedule = [0] * 16 for (i, b) in enumerate(block): assert 0 <= b <= 0xFF schedule[i // 4] |= b << ((i % 4) * 8) # Unpack state into variables; each one is a uint32 a, b, c, d = state # Perform 48 rounds of hashing for i in range(48): # Compute f value, schedule index, and addition constant based on the round index i if printdebug: print(" Round {:2d}: a={:08X}, b={:08X}, c={:08X}, d={:08X}".format(i, a, b, c, d)) if i < 16: f = (b & c) | (~b & d) k = i add = 0x00000000 elif i < 32: f = (b & c) | (b & d) | (c & d) k = ((i & 0x3) << 2) | ((i & 0xC) >> 2) add = 0x5A827999 else: f = b ^ c ^ d k = ((i >> 3) & 0x1) | ((i >> 1) & 0x2) | ((i << 1) & 0x4) | ((i << 3) & 0x8) # Last 4 bits reversed add = 0x6ED9EBA1 # Perform the round calculation rot = _ROTATION_AMOUNTS[((i >> 2) & 0xC) | (i & 0x3)] temp = (a + f + schedule[k] + add) & cryptocommon.UINT32_MASK temp = cryptocommon.rotate_left_uint32(temp, rot) a = d d = c c = b b = temp # Return new state as a tuple return ( (state[0] + a) & cryptocommon.UINT32_MASK, (state[1] + b) & cryptocommon.UINT32_MASK, (state[2] + c) & cryptocommon.UINT32_MASK, (state[3] + d) & cryptocommon.UINT32_MASK)
def _compress(block, state, printdebug): # Check argument types and lengths assert isinstance(block, tuple) and len(block) == _BLOCK_SIZE assert isinstance(state, tuple) and len(state) == 4 # Pack block bytes into schedule as uint32 in little endian schedule = [0] * 16 for (i, b) in enumerate(block): assert 0 <= b <= 0xFF schedule[i // 4] |= b << ((i % 4) * 8) # Unpack state into variables; each one is a uint32 a, b, c, d = state # Perform 64 rounds of hashing for i in range(len(_ROUND_CONSTANTS)): # Compute f value and schedule index based on the round index i if printdebug: print(" Round {:2d}: a={:08X}, b={:08X}, c={:08X}, d={:08X}".format(i, a, b, c, d)) if i < 16: f = (b & c) | (~b & d) k = i elif i < 32: f = (d & b) | (~d & c) k = (5 * i + 1) % 16 elif i < 48: f = b ^ c ^ d k = (3 * i + 5) % 16 else: f = c ^ (b | ~d) k = (7 * i) % 16 # Perform the round calculation rot = _ROTATION_AMOUNTS[((i >> 2) & 0xC) | (i & 0x3)] temp = (a + f + schedule[k] + _ROUND_CONSTANTS[i]) & cryptocommon.UINT32_MASK temp = cryptocommon.rotate_left_uint32(temp, rot) a = d d = c c = b b = (b + temp) & cryptocommon.UINT32_MASK # Return new state as a tuple return ( (state[0] + a) & cryptocommon.UINT32_MASK, (state[1] + b) & cryptocommon.UINT32_MASK, (state[2] + c) & cryptocommon.UINT32_MASK, (state[3] + d) & cryptocommon.UINT32_MASK)