aboutsummaryrefslogtreecommitdiff
path: root/scripts/sha3.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/sha3.py')
-rw-r--r--scripts/sha3.py115
1 files changed, 115 insertions, 0 deletions
diff --git a/scripts/sha3.py b/scripts/sha3.py
new file mode 100644
index 000000000000..79ed8bb990fe
--- /dev/null
+++ b/scripts/sha3.py
@@ -0,0 +1,115 @@
+#/*
+# * Copyright (C) 2017 - This file is part of libecc project
+# *
+# * Authors:
+# * Ryad BENADJILA <ryadbenadjila@gmail.com>
+# * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
+# * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
+# *
+# * Contributors:
+# * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
+# * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
+# *
+# * This software is licensed under a dual BSD and GPL v2 license.
+# * See LICENSE file at the root folder of the project.
+# */
+import struct, sys
+
+keccak_rc = [
+ 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000,
+ 0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
+ 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
+ 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003,
+ 0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A,
+ 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
+]
+
+keccak_rot = [
+ [ 0, 36, 3, 41, 18 ],
+ [ 1, 44, 10, 45, 2 ],
+ [ 62, 6, 43, 15, 61 ],
+ [ 28, 55, 25, 21, 56 ],
+ [ 27, 20, 39, 8, 14 ],
+]
+
+def is_python_2():
+ if sys.version_info[0] < 3:
+ return True
+ else:
+ return False
+
+# Keccak function
+def keccak_rotl(x, l):
+ return (((x << l) ^ (x >> (64 - l))) & (2**64-1))
+
+def keccakround(bytestate, rc):
+ # Import little endian state
+ state = [0] * 25
+ for i in range(0, 25):
+ to_unpack = ''.join(bytestate[(8*i):(8*i)+8])
+ if is_python_2() == False:
+ to_unpack = to_unpack.encode('latin-1')
+ (state[i],) = struct.unpack('<Q', to_unpack)
+ # Proceed with the KECCAK core
+ bcd = [0] * 25
+ # Theta
+ for i in range(0, 5):
+ bcd[i] = state[i] ^ state[i + (5*1)] ^ state[i + (5*2)] ^ state[i + (5*3)] ^ state[i + (5*4)]
+
+ for i in range(0, 5):
+ tmp = bcd[(i+4)%5] ^ keccak_rotl(bcd[(i+1)%5], 1)
+ for j in range(0, 5):
+ state[i + (5 * j)] = state[i + (5 * j)] ^ tmp
+ # Rho and Pi
+ for i in range(0, 5):
+ for j in range(0, 5):
+ bcd[j + (5*(((2*i)+(3*j)) % 5))] = keccak_rotl(state[i + (5*j)], keccak_rot[i][j])
+ # Chi
+ for i in range(0, 5):
+ for j in range(0, 5):
+ state[i + (5*j)] = bcd[i + (5*j)] ^ (~bcd[((i+1)%5) + (5*j)] & bcd[((i+2)%5) + (5*j)])
+ # Iota
+ state[0] = state[0] ^ keccak_rc[rc]
+ # Pack the output state
+ output = [0] * (25 * 8)
+ for i in range(0, 25):
+ packed = struct.pack('<Q', state[i])
+ if is_python_2() == True:
+ output[(8*i):(8*i)+1] = packed
+ else:
+ output[(8*i):(8*i)+1] = packed.decode('latin-1')
+ return output
+
+def keccakf(bytestate):
+ for rnd in range(0, 24):
+ bytestate = keccakround(bytestate, rnd)
+ return bytestate
+
+# SHA-3 context class
+class Sha3_ctx(object):
+ def __init__(self, digest_size):
+ self.digest_size = digest_size / 8
+ self.block_size = (25*8) - (2 * (digest_size / 8))
+ self.idx = 0
+ self.state = [chr(0)] * (25 * 8)
+ def digest_size(self):
+ return self.digest_size
+ def block_size(self):
+ return self.block_size
+ def update(self, message):
+ if (is_python_2() == False):
+ message = message.decode('latin-1')
+ for i in range(0, len(message)):
+ self.state[self.idx] = chr(ord(self.state[self.idx]) ^ ord(message[i]))
+ self.idx = self.idx + 1
+ if (self.idx == self.block_size):
+ self.state = keccakf(self.state)
+ self.idx = 0
+ def digest(self):
+ self.state[self.idx] = chr(ord(self.state[self.idx]) ^ 0x06)
+ self.state[int(self.block_size - 1)] = chr(ord(self.state[int(self.block_size - 1)]) ^ 0x80)
+ self.state = keccakf(self.state)
+ digest = ''.join(self.state[:int(self.digest_size)])
+ if is_python_2() == False:
+ digest = digest.encode('latin-1')
+ return digest