spec/crypto/sha3.bend
bend-collections-laws-crypto@1.0.0.0 · 115 lines · 15 definitions
1import Base
2import bend-collections-laws-crypto@1.0.0.0/src/crypto/keccak/types.bend as T
3import bend-collections-laws-crypto@1.0.0.0/spec/crypto/keccak/permutation.bend as K
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25def padding_bytes(q: Nat) -> List<&2, U32>:
26 match q:
27 case 0n:
28 Nil{}
29 case 1n:
30 [U32.or(6, 128)]
31 case 2n+k:
32 6 <> List.append(&2, U32, List.replicate(U32, k, 0), [128])
33
34def padding(+n: Nat) -> List<&2, U32>:
35 padding_bytes(Nat.sub(136n, Nat.mod(n, 136n)))
36
37def pad(+bytes: List<&2, U32>) -> List<&2, U32>:
38 List.append(&2, U32, bytes, padding(List.length(&2, U32, bytes)))
39
40
41
42def le32(a: U32, b: U32, c: U32, d: U32) -> U32:
43 U32.or(U32.or(U32.or(U32.and(a, 255), U32.shln(U32.and(b, 255), 8n)),
44 U32.shln(U32.and(c, 255), 16n)), U32.shln(U32.and(d, 255), 24n))
45
46
47def lanes(bytes: List<&2, U32>) -> List<&2, T.Lane>:
48 match bytes:
49 case a <> b <> c <> d <> e <> f <> g <> h <> rest:
50 T.W{le32(a, b, c, d), le32(e, f, g, h)} <> lanes(rest)
51 case _:
52 Nil{}
53
54
55
56
57def initial() -> T.State:
58 T.S{T.W{0, 0}, T.W{0, 0}, T.W{0, 0}, T.W{0, 0}, T.W{0, 0},
59 T.W{0, 0}, T.W{0, 0}, T.W{0, 0}, T.W{0, 0}, T.W{0, 0},
60 T.W{0, 0}, T.W{0, 0}, T.W{0, 0}, T.W{0, 0}, T.W{0, 0},
61 T.W{0, 0}, T.W{0, 0}, T.W{0, 0}, T.W{0, 0}, T.W{0, 0},
62 T.W{0, 0}, T.W{0, 0}, T.W{0, 0}, T.W{0, 0}, T.W{0, 0}}
63
64def to_lanes(s: T.State) -> List<&2, T.Lane>:
65 match s:
66 case T.S{a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24}:
67 [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24]
68
69def of_lanes(ls: List<&2, T.Lane>) -> T.State:
70 match ls:
71 case a0 <> a1 <> a2 <> a3 <> a4 <> a5 <> a6 <> a7 <> a8 <> a9 <> a10 <> a11 <> a12 <> a13 <> a14 <> a15 <> a16 <> a17 <> a18 <> a19 <> a20 <> a21 <> a22 <> a23 <> a24 <> rest:
72 T.S{a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24}
73 case _:
74 initial()
75
76
77def xor_lanes(xs: List<&2, T.Lane>, ys: List<&2, T.Lane>) -> List<&2, T.Lane>:
78 match xs ys:
79 case x <> xt y <> yt:
80 K.xor(x, y) <> xor_lanes(xt, yt)
81 case xs _:
82 xs
83
84
85def absorb(ls: List<&2, T.Lane>, +rounds: Nat, s: T.State) -> T.State:
86 match ls:
87 case l0 <> l1 <> l2 <> l3 <> l4 <> l5 <> l6 <> l7 <> l8 <> l9 <> l10 <> l11 <> l12 <> l13 <> l14 <> l15 <> l16 <> rest:
88 absorb(rest, rounds, K.rounds(rounds, 0n, of_lanes(xor_lanes(to_lanes(s),
89 [l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16]))))
90 case _:
91 s
92
93
94def lane_bytes(l: T.Lane) -> List<&2, U32>:
95 match l:
96 case T.W{+lo, +hi}:
97 [U32.and(lo, 255), U32.and(U32.shrn(lo, 8n), 255), U32.and(U32.shrn(lo, 16n), 255), U32.shrn(lo, 24n),
98 U32.and(hi, 255), U32.and(U32.shrn(hi, 8n), 255), U32.and(U32.shrn(hi, 16n), 255), U32.shrn(hi, 24n)]
99
100def state_bytes(ls: List<&2, T.Lane>) -> List<&2, U32>:
101 match ls:
102 case Nil{}:
103 Nil{}
104 case l <> rest:
105 List.append(&2, U32, lane_bytes(l), state_bytes(rest))
106
107def squeeze(s: T.State) -> List<&2, U32>:
108 List.take(&2, U32, state_bytes(to_lanes(s)), 32n)
109
110def keccak(bytes: List<&2, U32>, +rounds: Nat) -> List<&2, U32>:
111 squeeze(absorb(lanes(pad(bytes)), rounds, initial()))
112
113
114def sha3_256(bytes: List<&2, U32>) -> List<&2, U32>:
115 keccak(bytes, 24n)