spec/crypto/curve25519/field.bend
bend-collections-laws-crypto@1.0.0.0 · 169 lines · 33 definitions
1import Base
2import bend-collections-laws-crypto@1.0.0.0/spec/lib/common.bend as C
3import bend-collections-laws-crypto@1.0.0.0/src/crypto/curve25519/field.bend as F
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
34def value(xs: List<&2, U32>) -> Nat:
35 match xs:
36 case Nil{}:
37 0n
38 case Con{h, t}:
39 Nat.add(U32.to_nat(h), C.shift(8n, value(t)))
40
41
42def bytes_ok(n: Nat, xs: List<&2, U32>) -> Bool:
43 match n:
44 case 0n:
45 match xs:
46 case Nil{}:
47 True{}
48 case Con{x, xt}:
49 False{}
50 case 1n+m:
51 match xs:
52 case Nil{}:
53 False{}
54 case Con{x, xt}:
55 Bool.and(Nat.is_lt(U32.to_nat(x), 256n), bytes_ok(m, xt))
56
57def tight(xs: List<&2, U32>) -> Bool:
58 bytes_ok(32n, xs)
59
60
61
62
63def digits(+one: Nat, ds: List<&2, Nat>) -> Nat:
64 match ds:
65 case Nil{}:
66 0n
67 case Con{d, dt}:
68 Nat.add(Nat.mul(one, d), C.shift(8n, digits(one, dt)))
69
70
71
72def uvalue(+one: Nat, xs: List<&2, U32>) -> Nat:
73 match xs:
74 case Nil{}:
75 0n
76 case Con{x, xt}:
77 Nat.add(Nat.mul(one, U32.to_nat(x)), C.shift(8n, uvalue(one, xt)))
78
79
80def prime(+one: Nat) -> Nat:
81 Nat.sub(C.shift(255n, one), 19n)
82
83
84def fadd(+p: Nat, a: Nat, b: Nat) -> Nat:
85 Nat.mod(Nat.add(a, b), p)
86
87def fsub(+p: Nat, a: Nat, b: Nat) -> Nat:
88 Nat.mod(Nat.sub(Nat.add(a, p), Nat.mod(b, p)), p)
89
90def fmul(+p: Nat, a: Nat, b: Nat) -> Nat:
91 Nat.mod(Nat.mul(a, b), p)
92
93def fpow(+p: Nat, a: Nat, e: Nat) -> Nat:
94 Nat.mod(Nat.pow(a, e), p)
95
96
97def finv(+p: Nat, a: Nat) -> Nat:
98 fpow(p, a, Nat.sub(p, 2n))
99
100
101
102def Add.value(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +b: List<&2, U32>, +ha: {tight(a) == True{} : Bool}, +hb: {tight(b) == True{} : Bool}) -> Type:
103 {Nat.mod(value(F.add(a, b)), prime(one)) == fadd(prime(one), value(a), value(b)) : Nat}
104
105def Add.tight(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +b: List<&2, U32>, +ha: {tight(a) == True{} : Bool}, +hb: {tight(b) == True{} : Bool}) -> Type:
106 {tight(F.add(a, b)) == True{} : Bool}
107
108def Sub.value(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +b: List<&2, U32>, +ha: {tight(a) == True{} : Bool}, +hb: {tight(b) == True{} : Bool}) -> Type:
109 {Nat.mod(value(F.sub(a, b)), prime(one)) == fsub(prime(one), value(a), value(b)) : Nat}
110
111def Sub.tight(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +b: List<&2, U32>, +ha: {tight(a) == True{} : Bool}, +hb: {tight(b) == True{} : Bool}) -> Type:
112 {tight(F.sub(a, b)) == True{} : Bool}
113
114def Mul.value(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +b: List<&2, U32>, +ha: {tight(a) == True{} : Bool}, +hb: {tight(b) == True{} : Bool}) -> Type:
115 {Nat.mod(value(F.mul(a, b)), prime(one)) == fmul(prime(one), value(a), value(b)) : Nat}
116
117def Mul.tight(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +b: List<&2, U32>, +ha: {tight(a) == True{} : Bool}, +hb: {tight(b) == True{} : Bool}) -> Type:
118 {tight(F.mul(a, b)) == True{} : Bool}
119
120def Sq.value(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +ha: {tight(a) == True{} : Bool}) -> Type:
121 {Nat.mod(value(F.sq(a)), prime(one)) == fmul(prime(one), value(a), value(a)) : Nat}
122
123def Sq.tight(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +ha: {tight(a) == True{} : Bool}) -> Type:
124 {tight(F.sq(a)) == True{} : Bool}
125
126
127def MulSmall.value(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +k: U32, +ha: {tight(a) == True{} : Bool}, +hk: {Nat.is_lt(U32.to_nat(k), C.shift(17n, one)) == True{} : Bool}) -> Type:
128 {Nat.mod(value(F.mul_small(a, k)), prime(one)) == fmul(prime(one), value(a), U32.to_nat(k)) : Nat}
129
130def MulSmall.tight(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +k: U32, +ha: {tight(a) == True{} : Bool}, +hk: {Nat.is_lt(U32.to_nat(k), C.shift(17n, one)) == True{} : Bool}) -> Type:
131 {tight(F.mul_small(a, k)) == True{} : Bool}
132
133def Select.zero(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +b: List<&2, U32>, +ha: {tight(a) == True{} : Bool}, +hb: {tight(b) == True{} : Bool}) -> Type:
134 {F.select(0, a, b) == a : List<&2, U32>}
135
136def Select.one(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +b: List<&2, U32>, +ha: {tight(a) == True{} : Bool}, +hb: {tight(b) == True{} : Bool}) -> Type:
137 {F.select(1, a, b) == b : List<&2, U32>}
138
139def Inv.value(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +ha: {tight(a) == True{} : Bool}) -> Type:
140 {Nat.mod(value(F.inv(a)), prime(one)) == finv(prime(one), value(a)) : Nat}
141
142def Inv.tight(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +ha: {tight(a) == True{} : Bool}) -> Type:
143 {tight(F.inv(a)) == True{} : Bool}
144
145
146def PowP58.value(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +ha: {tight(a) == True{} : Bool}) -> Type:
147 {Nat.mod(value(F.pow_p58(a)), prime(one)) == fpow(prime(one), value(a), Nat.div(Nat.sub(prime(one), 5n), 8n)) : Nat}
148
149def PowP58.tight(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +ha: {tight(a) == True{} : Bool}) -> Type:
150 {tight(F.pow_p58(a)) == True{} : Bool}
151
152
153def Freeze.value(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +ha: {tight(a) == True{} : Bool}) -> Type:
154 {value(F.freeze(a)) == Nat.mod(value(a), prime(one)) : Nat}
155
156def Freeze.tight(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +ha: {tight(a) == True{} : Bool}) -> Type:
157 {tight(F.freeze(a)) == True{} : Bool}
158
159def OfBytes.tight(+one: Nat, +h1: {one == 1n : Nat}, +bs: List<&2, U32>, +hb: {tight(bs) == True{} : Bool}) -> Type:
160 {tight(F.of_bytes(bs)) == True{} : Bool}
161
162def Eq.value(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +b: List<&2, U32>, +ha: {tight(a) == True{} : Bool}, +hb: {tight(b) == True{} : Bool}) -> Type:
163 {F.eq(a, b) == Nat.is_eq(Nat.mod(value(a), prime(one)), Nat.mod(value(b), prime(one))) : Bool}
164
165def IsZero.value(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +ha: {tight(a) == True{} : Bool}) -> Type:
166 {F.is_zero(a) == Nat.is_eq(Nat.mod(value(a), prime(one)), 0n) : Bool}
167
168def Parity.value(+one: Nat, +h1: {one == 1n : Nat}, +a: List<&2, U32>, +ha: {tight(a) == True{} : Bool}) -> Type:
169 {U32.to_nat(F.parity(a)) == Nat.mod(Nat.mod(value(a), prime(one)), 2n) : Nat}