v / vlib / crypto / ed25519 / internal / edwards25519 / extra_test.v
202 lines · 170 sloc · 5.17 KB
Raw
1module edwards25519
2
3import os
4import rand
5import encoding.hex
6
7const github_job = os.getenv('GITHUB_JOB')
8
9fn testsuite_begin() {
10 if github_job != '' {
11 // ensure that the CI does not run flaky tests:
12 rand.seed([u32(0xffff24), 0xabcd])
13 }
14}
15
16// test_bytes_montgomery tests the set_bytes_with_clamping+bytes_montgomery path
17// equivalence to curve25519.X25519 for basepoint scalar multiplications.
18//
19// Note that you can't actually implement X25519 with this package because
20// there is no SetBytesMontgomery, and it would not be possible to implement
21// it properly: points on the twist would get rejected, and the Scalar returned
22// by set_bytes_with_clamping does not preserve its cofactor-clearing properties.
23//
24// Disabled curve25519 not available yet, but maybe can use own curve25519
25/*
26fn fn_mon(scalar [32]u8) bool {
27 mut s := new_scalar().set_bytes_with_clamping(scalar[..])
28 p := (&Point{}).scalar_base_mult(s)
29 got := p.bytes_montgomery()
30 want, _ := curve25519.X25519(scalar[..], curve25519.Basepoint)
31 return bytes.equal(got, want)
32 }
33
34fn test_bytes_montgomery() {
35 /* f := fn(scalar [32]u8) bool {
36 s := new_scalar().set_bytes_with_clamping(scalar[..])
37 p := (&Point{}).scalar_base_mult(s)
38 got := p.bytes_montgomery()
39 want, _ := curve25519.X25519(scalar[..], curve25519.Basepoint)
40 return bytes.equal(got, want)
41 } */
42 if err := quick.Check(f, nil); err != nil {
43 t.Error(err)
44 }
45}*/
46
47fn test_bytes_montgomery_sodium() {
48 // Generated with libsodium.js 1.0.18
49 // crypto_sign_keypair().pubkey
50 pubkey := '3bf918ffc2c955dc895bf145f566fb96623c1cadbe040091175764b5fde322c0'
51 mut p := Point{}
52 p.set_bytes(hex.decode(pubkey)!)!
53
54 // crypto_sign_ed25519_pk_to_curve25519(pubkey)
55 want := 'efc6c9d0738e9ea18d738ad4a2653631558931b0f1fde4dd58c436d19686dc28'
56 got := hex.encode(p.bytes_montgomery())
57 assert got == want
58}
59
60fn test_bytes_montgomery_infinity() {
61 mut p := new_identity_point()
62 want := '0000000000000000000000000000000000000000000000000000000000000000'
63 got := hex.encode(p.bytes_montgomery())
64
65 assert got == want
66}
67
68const loworder_string = '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85'
69const loworder_bytes = hex.decode(loworder_string) or { []u8{} }
70
71fn fn_cofactor(mut data []u8) bool {
72 if data.len != 64 {
73 panic('data.len should be 64')
74 }
75 mut loworder := Point{}
76 loworder.set_bytes(loworder_bytes) or { return false }
77
78 mut s := new_scalar()
79 mut p := Point{}
80 mut p8 := Point{}
81 s.set_uniform_bytes(data) or { panic(err) }
82 p.scalar_base_mult(mut s)
83 p8.mult_by_cofactor(p)
84
85 assert check_on_curve(p8) == true
86
87 // 8 * p == (8 * s) * B
88 mut sc := Scalar{
89 s: [32]u8{}
90 }
91 sc.s[0] = u8(0x08)
92 s.multiply(s, sc)
93 mut pp := Point{}
94 pp.scalar_base_mult(mut s)
95 if p8.equal(pp) != 1 {
96 return false
97 }
98
99 // 8 * p == 8 * (loworder + p)
100 pp.add(p, loworder)
101 pp.mult_by_cofactor(pp)
102 if p8.equal(pp) != 1 {
103 return false
104 }
105
106 // 8 * p == p + p + p + p + p + p + p + p
107 pp.set(new_identity_point())
108 for i := 0; i < 8; i++ {
109 pp.add(pp, p)
110 }
111 return p8.equal(pp) == 1
112}
113
114fn test_mult_by_cofactor() {
115 mut loworder := Point{}
116 mut data := rand.bytes(64)!
117
118 assert fn_cofactor(mut data) == true
119}
120
121fn invert_works(mut xinv Scalar, x NotZeroScalar) bool {
122 xinv.invert(x)
123 mut check := Scalar{}
124 check.multiply(x, xinv)
125 return check == sc_one && is_reduced(xinv)
126}
127
128fn test_scalar_invert() {
129 nsc := generate_notzero_scalar(5) or { panic(err) }
130 mut xsc := generate_scalar(5) or { panic(err) }
131 assert invert_works(mut xsc, nsc) == true
132
133 mut zero := new_scalar()
134 mut xx := new_scalar()
135 xx.invert(zero)
136 assert xx.equal(zero) == 1
137}
138
139fn test_multiscalarmultmatchesbasemult() {
140 for i in 0 .. 6 {
141 x := generate_scalar(100) or { panic(err) }
142 y := generate_scalar(5) or { panic(err) }
143 z := generate_scalar(2) or { panic(err) }
144 assert multiscalarmultmatchesbasemult(x, y, z) == true
145 }
146}
147
148fn multiscalarmultmatchesbasemult(xx Scalar, yy Scalar, zz Scalar) bool {
149 mut x := xx
150 mut y := yy
151 mut z := zz
152
153 mut p := Point{}
154 mut q1 := Point{}
155 mut q2 := Point{}
156 mut q3 := Point{}
157 mut check := Point{}
158 mut b := new_generator_point()
159
160 p.multi_scalar_mult([x, y, z], [b, b, b])
161
162 q1.scalar_base_mult(mut x)
163 q2.scalar_base_mult(mut y)
164 q3.scalar_base_mult(mut z)
165 check.add(q1, q2)
166 check.add(check, q3)
167
168 check_on_curve(p, check, q1, q2, q3)
169 return p.equal(check) == 1
170}
171
172fn vartime_multiscala_rmultmatches_basemult(xx Scalar, yy Scalar, zz Scalar) bool {
173 mut x := xx
174 mut y := yy
175 mut z := zz
176 mut p := Point{}
177 mut q1 := Point{}
178 mut q2 := Point{}
179 mut q3 := Point{}
180 mut check := Point{}
181 mut b := new_generator_point()
182
183 p.vartime_multiscalar_mult([x, y, z], [b, b, b])
184
185 q1.scalar_base_mult(mut x)
186 q2.scalar_base_mult(mut y)
187 q3.scalar_base_mult(mut z)
188 check.add(q1, q2)
189 check.add(check, q3)
190
191 check_on_curve(p, check, q1, q2, q3)
192 return p.equal(check) == 1
193}
194
195fn test_vartimemultiscalarmultmatchesbasemult() {
196 for i in 0 .. 5 {
197 x := generate_scalar(100) or { panic(err) }
198 y := generate_scalar(5) or { panic(err) }
199 z := generate_scalar(2) or { panic(err) }
200 assert vartime_multiscala_rmultmatches_basemult(x, y, z) == true
201 }
202}
203