-
Notifications
You must be signed in to change notification settings - Fork 0
/
fdp_optimized.py
54 lines (41 loc) · 1.82 KB
/
fdp_optimized.py
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
from numpy import uint16, ndarray, concatenate, object as obj
from compatibility import block_from_secret, roll_output_block, numpy_ufunc
from lookup_tables import PERMUTE
@numpy_ufunc(2, 1)
def filter_block(state: uint16, echo: uint16) -> uint16:
"""Create accumulator ufunc which generates a "running total"-like array"""
return state - (state >> 4) + echo
def next_block(block: ndarray, state: uint16) -> (ndarray, uint16):
"""Encode an arbitrary-sized 1d block a single time (1 iteration)"""
# PERMUTE
permuted_block = PERMUTE[block] << 4
# FILTER
filtered_states = filter_block.accumulate(
concatenate(([state], permuted_block)), # state is initial value
dtype=obj # np.frompyfunc requires casting to object and back
).astype(uint16)[1:] # drop prev state
# ECHO
next_state = filtered_states[-1]
next_block = (filtered_states >> 3) & 0x00FF
return next_block, next_state
def encode(
secret: bytes,
block_size=512,
iterations=20,
backwards_compatible=True) -> (uint16, ndarray):
"""Perform PermuteFilterEcho hash"""
block, state = block_from_secret(block_size, secret, backwards_compatible)
for _ in range(iterations):
block, state = next_block(block, state)
block = roll_output_block(block, len(secret), backwards_compatible)
return state, block
if __name__ == '__main__':
print("fdp_optimized.py is the result of me learning how the original")
print("file worked as well as learning the basics of numpy. The following")
print("output should match the output of fdp_original.py, but this can be")
print("tested automatically with run_tests.py")
print()
state, echoes = encode(b'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
print('State:', state)
print('Delay line:')
print(echoes)