1*f0865ec9SKyle Evans#/* 2*f0865ec9SKyle Evans# * Copyright (C) 2017 - This file is part of libecc project 3*f0865ec9SKyle Evans# * 4*f0865ec9SKyle Evans# * Authors: 5*f0865ec9SKyle Evans# * Ryad BENADJILA <ryadbenadjila@gmail.com> 6*f0865ec9SKyle Evans# * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7*f0865ec9SKyle Evans# * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8*f0865ec9SKyle Evans# * 9*f0865ec9SKyle Evans# * Contributors: 10*f0865ec9SKyle Evans# * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11*f0865ec9SKyle Evans# * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12*f0865ec9SKyle Evans# * 13*f0865ec9SKyle Evans# * This software is licensed under a dual BSD and GPL v2 license. 14*f0865ec9SKyle Evans# * See LICENSE file at the root folder of the project. 15*f0865ec9SKyle Evans# */ 16*f0865ec9SKyle Evansimport struct, sys 17*f0865ec9SKyle Evans 18*f0865ec9SKyle Evanskeccak_rc = [ 19*f0865ec9SKyle Evans 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, 20*f0865ec9SKyle Evans 0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, 21*f0865ec9SKyle Evans 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A, 22*f0865ec9SKyle Evans 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003, 23*f0865ec9SKyle Evans 0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A, 24*f0865ec9SKyle Evans 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 25*f0865ec9SKyle Evans] 26*f0865ec9SKyle Evans 27*f0865ec9SKyle Evanskeccak_rot = [ 28*f0865ec9SKyle Evans [ 0, 36, 3, 41, 18 ], 29*f0865ec9SKyle Evans [ 1, 44, 10, 45, 2 ], 30*f0865ec9SKyle Evans [ 62, 6, 43, 15, 61 ], 31*f0865ec9SKyle Evans [ 28, 55, 25, 21, 56 ], 32*f0865ec9SKyle Evans [ 27, 20, 39, 8, 14 ], 33*f0865ec9SKyle Evans] 34*f0865ec9SKyle Evans 35*f0865ec9SKyle Evansdef is_python_2(): 36*f0865ec9SKyle Evans if sys.version_info[0] < 3: 37*f0865ec9SKyle Evans return True 38*f0865ec9SKyle Evans else: 39*f0865ec9SKyle Evans return False 40*f0865ec9SKyle Evans 41*f0865ec9SKyle Evans# Keccak function 42*f0865ec9SKyle Evansdef keccak_rotl(x, l): 43*f0865ec9SKyle Evans return (((x << l) ^ (x >> (64 - l))) & (2**64-1)) 44*f0865ec9SKyle Evans 45*f0865ec9SKyle Evansdef keccakround(bytestate, rc): 46*f0865ec9SKyle Evans # Import little endian state 47*f0865ec9SKyle Evans state = [0] * 25 48*f0865ec9SKyle Evans for i in range(0, 25): 49*f0865ec9SKyle Evans to_unpack = ''.join(bytestate[(8*i):(8*i)+8]) 50*f0865ec9SKyle Evans if is_python_2() == False: 51*f0865ec9SKyle Evans to_unpack = to_unpack.encode('latin-1') 52*f0865ec9SKyle Evans (state[i],) = struct.unpack('<Q', to_unpack) 53*f0865ec9SKyle Evans # Proceed with the KECCAK core 54*f0865ec9SKyle Evans bcd = [0] * 25 55*f0865ec9SKyle Evans # Theta 56*f0865ec9SKyle Evans for i in range(0, 5): 57*f0865ec9SKyle Evans bcd[i] = state[i] ^ state[i + (5*1)] ^ state[i + (5*2)] ^ state[i + (5*3)] ^ state[i + (5*4)] 58*f0865ec9SKyle Evans 59*f0865ec9SKyle Evans for i in range(0, 5): 60*f0865ec9SKyle Evans tmp = bcd[(i+4)%5] ^ keccak_rotl(bcd[(i+1)%5], 1) 61*f0865ec9SKyle Evans for j in range(0, 5): 62*f0865ec9SKyle Evans state[i + (5 * j)] = state[i + (5 * j)] ^ tmp 63*f0865ec9SKyle Evans # Rho and Pi 64*f0865ec9SKyle Evans for i in range(0, 5): 65*f0865ec9SKyle Evans for j in range(0, 5): 66*f0865ec9SKyle Evans bcd[j + (5*(((2*i)+(3*j)) % 5))] = keccak_rotl(state[i + (5*j)], keccak_rot[i][j]) 67*f0865ec9SKyle Evans # Chi 68*f0865ec9SKyle Evans for i in range(0, 5): 69*f0865ec9SKyle Evans for j in range(0, 5): 70*f0865ec9SKyle Evans state[i + (5*j)] = bcd[i + (5*j)] ^ (~bcd[((i+1)%5) + (5*j)] & bcd[((i+2)%5) + (5*j)]) 71*f0865ec9SKyle Evans # Iota 72*f0865ec9SKyle Evans state[0] = state[0] ^ keccak_rc[rc] 73*f0865ec9SKyle Evans # Pack the output state 74*f0865ec9SKyle Evans output = [0] * (25 * 8) 75*f0865ec9SKyle Evans for i in range(0, 25): 76*f0865ec9SKyle Evans packed = struct.pack('<Q', state[i]) 77*f0865ec9SKyle Evans if is_python_2() == True: 78*f0865ec9SKyle Evans output[(8*i):(8*i)+1] = packed 79*f0865ec9SKyle Evans else: 80*f0865ec9SKyle Evans output[(8*i):(8*i)+1] = packed.decode('latin-1') 81*f0865ec9SKyle Evans return output 82*f0865ec9SKyle Evans 83*f0865ec9SKyle Evansdef keccakf(bytestate): 84*f0865ec9SKyle Evans for rnd in range(0, 24): 85*f0865ec9SKyle Evans bytestate = keccakround(bytestate, rnd) 86*f0865ec9SKyle Evans return bytestate 87*f0865ec9SKyle Evans 88*f0865ec9SKyle Evans# SHA-3 context class 89*f0865ec9SKyle Evansclass Sha3_ctx(object): 90*f0865ec9SKyle Evans def __init__(self, digest_size): 91*f0865ec9SKyle Evans self.digest_size = digest_size / 8 92*f0865ec9SKyle Evans self.block_size = (25*8) - (2 * (digest_size / 8)) 93*f0865ec9SKyle Evans self.idx = 0 94*f0865ec9SKyle Evans self.state = [chr(0)] * (25 * 8) 95*f0865ec9SKyle Evans def digest_size(self): 96*f0865ec9SKyle Evans return self.digest_size 97*f0865ec9SKyle Evans def block_size(self): 98*f0865ec9SKyle Evans return self.block_size 99*f0865ec9SKyle Evans def update(self, message): 100*f0865ec9SKyle Evans if (is_python_2() == False): 101*f0865ec9SKyle Evans message = message.decode('latin-1') 102*f0865ec9SKyle Evans for i in range(0, len(message)): 103*f0865ec9SKyle Evans self.state[self.idx] = chr(ord(self.state[self.idx]) ^ ord(message[i])) 104*f0865ec9SKyle Evans self.idx = self.idx + 1 105*f0865ec9SKyle Evans if (self.idx == self.block_size): 106*f0865ec9SKyle Evans self.state = keccakf(self.state) 107*f0865ec9SKyle Evans self.idx = 0 108*f0865ec9SKyle Evans def digest(self): 109*f0865ec9SKyle Evans self.state[self.idx] = chr(ord(self.state[self.idx]) ^ 0x06) 110*f0865ec9SKyle Evans self.state[int(self.block_size - 1)] = chr(ord(self.state[int(self.block_size - 1)]) ^ 0x80) 111*f0865ec9SKyle Evans self.state = keccakf(self.state) 112*f0865ec9SKyle Evans digest = ''.join(self.state[:int(self.digest_size)]) 113*f0865ec9SKyle Evans if is_python_2() == False: 114*f0865ec9SKyle Evans digest = digest.encode('latin-1') 115*f0865ec9SKyle Evans return digest 116