Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# -*- coding: utf-8 -*-
# Implementation by Gilles Van Assche, hereby denoted as "the implementer".
#
# For more information, feedback or questions, please refer to our website:
# https://keccak.team/
#
# To the extent possible under law, the implementer has waived all copyright
# and related or neighboring rights to the source code in this file.
# http://creativecommons.org/publicdomain/zero/1.0/
import numpy as np
KECCAK_BYTES = 200
KECCAK_LANES = 25
KECCAK_PLANES_SLICES = 5
THETA_REORDER = ((4, 0, 1, 2, 3), (1, 2, 3, 4, 0))
#Iota Step Round Constants For Keccak-p(1600, 24)
IOTA_CONSTANTS = np.array([0x0000000000000001,0x0000000000008082, 0x800000000000808A,
0x8000000080008000, 0x000000000000808B, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008A,
0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x000000000000800A, 0x800000008000000A, 0x8000000080008081,
0x8000000000008080, 0x0000000080000001, 0x8000000080008008],
dtype=np.uint64)
#Lane Shifts for Rho Step
RHO_SHIFTS = np.array([[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]], dtype=np.uint64)
#Lane Re-order Mapping for Chi Step
CHI_REORDER = ((1, 2, 3, 4, 0), (2, 3, 4, 0, 1))
#Row Re-order Mapping for Pi Step
PI_ROW_REORDER = np.array([[0, 3, 1, 4, 2],
[1, 4, 2, 0, 3],
[2, 0, 3, 1, 4],
[3, 1, 4, 2, 0],
[4, 2, 0, 3, 1]])
#Column Re-order Mapping for Pi Step
PI_COLUMN_REORDER = np.array([[0, 0, 0, 0, 0],
[1, 1, 1, 1, 1],
[2, 2, 2, 2, 2],
[3, 3, 3, 3, 3],
[4, 4, 4, 4, 4]])
def KeccakF1600(state):
state = np.copy(np.frombuffer(state, dtype=np.uint64, count=25).reshape([5, 5], order='F'))
for round_num in range(24):
# theta_step:
# Exclusive-or each slice-lane by state based permutation value
array_shift = state << 1 | state >> 63
state ^= np.bitwise_xor.reduce(state[THETA_REORDER[0], ], 1, keepdims=True) ^ np.bitwise_xor.reduce(array_shift[THETA_REORDER[1], ], 1, keepdims=True)
# rho_step:
# Left Rotate each lane by pre-calculated value
state = state << RHO_SHIFTS | state >> np.uint64(64 - RHO_SHIFTS)
# pi_step:
# Shuffle lanes to pre-calculated positions
state = state[PI_ROW_REORDER, PI_COLUMN_REORDER]
# chi_step:
# Exclusive-or each individual lane based on and/invert permutation
state ^= ~state[CHI_REORDER[0], ] & state[CHI_REORDER[1], ]
# iota_step:
# Exclusive-or first lane of state with round constant
state[0, 0] ^= IOTA_CONSTANTS[round_num]
return bytearray(state.tobytes(order='F'))
def Keccak(rate, capacity, inputBytes, delimitedSuffix, outputByteLen):
outputBytes = bytearray()
state = bytearray([0 for i in range(200)])
rateInBytes = rate//8
blockSize = 0
if (((rate + capacity) != 1600) or ((rate % 8) != 0)):
return
inputOffset = 0
# === Absorb all the input blocks ===
while(inputOffset < len(inputBytes)):
blockSize = min(len(inputBytes)-inputOffset, rateInBytes)
for i in range(blockSize):
state[i] = state[i] ^ inputBytes[i+inputOffset]
inputOffset = inputOffset + blockSize
if (blockSize == rateInBytes):
state = KeccakF1600(state)
blockSize = 0
# === Do the padding and switch to the squeezing phase ===
state[blockSize] = state[blockSize] ^ delimitedSuffix
if (((delimitedSuffix & 0x80) != 0) and (blockSize == (rateInBytes-1))):
state = KeccakF1600(state)
state[rateInBytes-1] = state[rateInBytes-1] ^ 0x80
state = KeccakF1600(state)
# === Squeeze out all the output blocks ===
while(outputByteLen > 0):
blockSize = min(outputByteLen, rateInBytes)
outputBytes = outputBytes + state[0:blockSize]
outputByteLen = outputByteLen - blockSize
if (outputByteLen > 0):
state = KeccakF1600(state)
return outputBytes
def SHAKE128(inputBytes, outputByteLen):
return Keccak(1344, 256, inputBytes, 0x1F, outputByteLen)
def SHAKE256(inputBytes, outputByteLen):
return Keccak(1088, 512, inputBytes, 0x1F, outputByteLen)
def SHA3_224(inputBytes):
return Keccak(1152, 448, inputBytes, 0x06, 224//8)
def SHA3_256(inputBytes):
return Keccak(1088, 512, inputBytes, 0x06, 256//8)
def SHA3_384(inputBytes):
return Keccak(832, 768, inputBytes, 0x06, 384//8)
def SHA3_512(inputBytes):
return Keccak(576, 1024, inputBytes, 0x06, 512//8)