1736d6639SKyle Evans#/* 2736d6639SKyle Evans# * Copyright (C) 2017 - This file is part of libecc project 3736d6639SKyle Evans# * 4736d6639SKyle Evans# * Authors: 5736d6639SKyle Evans# * Ryad BENADJILA <ryadbenadjila@gmail.com> 6736d6639SKyle Evans# * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7736d6639SKyle Evans# * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8736d6639SKyle Evans# * 9736d6639SKyle Evans# * Contributors: 10736d6639SKyle Evans# * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11736d6639SKyle Evans# * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12736d6639SKyle Evans# * 13736d6639SKyle Evans# * This software is licensed under a dual BSD and GPL v2 license. 14736d6639SKyle Evans# * See LICENSE file at the root folder of the project. 15736d6639SKyle Evans# */ 16736d6639SKyle Evansimport struct, sys 17736d6639SKyle Evans 18736d6639SKyle Evanskeccak_rc = [ 19736d6639SKyle Evans 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, 20736d6639SKyle Evans 0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, 21736d6639SKyle Evans 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A, 22736d6639SKyle Evans 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003, 23736d6639SKyle Evans 0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A, 24736d6639SKyle Evans 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 25736d6639SKyle Evans] 26736d6639SKyle Evans 27736d6639SKyle Evanskeccak_rot = [ 28736d6639SKyle Evans [ 0, 36, 3, 41, 18 ], 29736d6639SKyle Evans [ 1, 44, 10, 45, 2 ], 30736d6639SKyle Evans [ 62, 6, 43, 15, 61 ], 31736d6639SKyle Evans [ 28, 55, 25, 21, 56 ], 32736d6639SKyle Evans [ 27, 20, 39, 8, 14 ], 33736d6639SKyle Evans] 34736d6639SKyle Evans 35736d6639SKyle Evansdef is_python_2(): 36736d6639SKyle Evans if sys.version_info[0] < 3: 37736d6639SKyle Evans return True 38736d6639SKyle Evans else: 39736d6639SKyle Evans return False 40736d6639SKyle Evans 41736d6639SKyle Evans# Keccak function 42736d6639SKyle Evansdef keccak_rotl(x, l): 43736d6639SKyle Evans return (((x << l) ^ (x >> (64 - l))) & (2**64-1)) 44736d6639SKyle Evans 45736d6639SKyle Evansdef keccakround(bytestate, rc): 46736d6639SKyle Evans # Import little endian state 47736d6639SKyle Evans state = [0] * 25 48736d6639SKyle Evans for i in range(0, 25): 49736d6639SKyle Evans to_unpack = ''.join(bytestate[(8*i):(8*i)+8]) 50736d6639SKyle Evans if is_python_2() == False: 51736d6639SKyle Evans to_unpack = to_unpack.encode('latin-1') 52736d6639SKyle Evans (state[i],) = struct.unpack('<Q', to_unpack) 53736d6639SKyle Evans # Proceed with the KECCAK core 54736d6639SKyle Evans bcd = [0] * 25 55736d6639SKyle Evans # Theta 56736d6639SKyle Evans for i in range(0, 5): 57736d6639SKyle Evans bcd[i] = state[i] ^ state[i + (5*1)] ^ state[i + (5*2)] ^ state[i + (5*3)] ^ state[i + (5*4)] 58736d6639SKyle Evans 59736d6639SKyle Evans for i in range(0, 5): 60736d6639SKyle Evans tmp = bcd[(i+4)%5] ^ keccak_rotl(bcd[(i+1)%5], 1) 61736d6639SKyle Evans for j in range(0, 5): 62736d6639SKyle Evans state[i + (5 * j)] = state[i + (5 * j)] ^ tmp 63736d6639SKyle Evans # Rho and Pi 64736d6639SKyle Evans for i in range(0, 5): 65736d6639SKyle Evans for j in range(0, 5): 66736d6639SKyle Evans bcd[j + (5*(((2*i)+(3*j)) % 5))] = keccak_rotl(state[i + (5*j)], keccak_rot[i][j]) 67736d6639SKyle Evans # Chi 68736d6639SKyle Evans for i in range(0, 5): 69736d6639SKyle Evans for j in range(0, 5): 70736d6639SKyle Evans state[i + (5*j)] = bcd[i + (5*j)] ^ (~bcd[((i+1)%5) + (5*j)] & bcd[((i+2)%5) + (5*j)]) 71736d6639SKyle Evans # Iota 72736d6639SKyle Evans state[0] = state[0] ^ keccak_rc[rc] 73736d6639SKyle Evans # Pack the output state 74736d6639SKyle Evans output = [0] * (25 * 8) 75736d6639SKyle Evans for i in range(0, 25): 76736d6639SKyle Evans packed = struct.pack('<Q', state[i]) 77736d6639SKyle Evans if is_python_2() == True: 78736d6639SKyle Evans output[(8*i):(8*i)+1] = packed 79736d6639SKyle Evans else: 80736d6639SKyle Evans output[(8*i):(8*i)+1] = packed.decode('latin-1') 81736d6639SKyle Evans return output 82736d6639SKyle Evans 83736d6639SKyle Evansdef keccakf(bytestate): 84736d6639SKyle Evans for rnd in range(0, 24): 85736d6639SKyle Evans bytestate = keccakround(bytestate, rnd) 86736d6639SKyle Evans return bytestate 87736d6639SKyle Evans 88736d6639SKyle Evans# SHA-3 context class 89736d6639SKyle Evansclass Sha3_ctx(object): 90736d6639SKyle Evans def __init__(self, digest_size): 91736d6639SKyle Evans self.digest_size = digest_size / 8 92736d6639SKyle Evans self.block_size = (25*8) - (2 * (digest_size / 8)) 93736d6639SKyle Evans self.idx = 0 94736d6639SKyle Evans self.state = [chr(0)] * (25 * 8) 95736d6639SKyle Evans def digest_size(self): 96736d6639SKyle Evans return self.digest_size 97736d6639SKyle Evans def block_size(self): 98736d6639SKyle Evans return self.block_size 99736d6639SKyle Evans def update(self, message): 100736d6639SKyle Evans if (is_python_2() == False): 101736d6639SKyle Evans message = message.decode('latin-1') 102736d6639SKyle Evans for i in range(0, len(message)): 103736d6639SKyle Evans self.state[self.idx] = chr(ord(self.state[self.idx]) ^ ord(message[i])) 104736d6639SKyle Evans self.idx = self.idx + 1 105736d6639SKyle Evans if (self.idx == self.block_size): 106736d6639SKyle Evans self.state = keccakf(self.state) 107736d6639SKyle Evans self.idx = 0 108736d6639SKyle Evans def digest(self): 109736d6639SKyle Evans self.state[self.idx] = chr(ord(self.state[self.idx]) ^ 0x06) 110736d6639SKyle Evans self.state[int(self.block_size - 1)] = chr(ord(self.state[int(self.block_size - 1)]) ^ 0x80) 111736d6639SKyle Evans self.state = keccakf(self.state) 112736d6639SKyle Evans digest = ''.join(self.state[:int(self.digest_size)]) 113736d6639SKyle Evans if is_python_2() == False: 114736d6639SKyle Evans digest = digest.encode('latin-1') 115736d6639SKyle Evans return digest 116