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