v
Зеркало из https://github.com/vlang/v
1module edwards25519
2
3import os
4import rand
5import encoding.hex
6
7const github_job = os.getenv('GITHUB_JOB')
8
9fn testsuite_begin() {
10if github_job != '' {
11// ensure that the CI does not run flaky tests:
12rand.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 {
27mut s := new_scalar().set_bytes_with_clamping(scalar[..])
28p := (&Point{}).scalar_base_mult(s)
29got := p.bytes_montgomery()
30want, _ := curve25519.X25519(scalar[..], curve25519.Basepoint)
31return bytes.equal(got, want)
32}
33
34fn test_bytes_montgomery() {
35/* f := fn(scalar [32]u8) bool {
36s := new_scalar().set_bytes_with_clamping(scalar[..])
37p := (&Point{}).scalar_base_mult(s)
38got := p.bytes_montgomery()
39want, _ := curve25519.X25519(scalar[..], curve25519.Basepoint)
40return bytes.equal(got, want)
41} */
42if err := quick.Check(f, nil); err != nil {
43t.Error(err)
44}
45}*/
46
47fn test_bytes_montgomery_sodium() {
48// Generated with libsodium.js 1.0.18
49// crypto_sign_keypair().pubkey
50pubkey := '3bf918ffc2c955dc895bf145f566fb96623c1cadbe040091175764b5fde322c0'
51mut p := Point{}
52p.set_bytes(hex.decode(pubkey)!)!
53
54// crypto_sign_ed25519_pk_to_curve25519(pubkey)
55want := 'efc6c9d0738e9ea18d738ad4a2653631558931b0f1fde4dd58c436d19686dc28'
56got := hex.encode(p.bytes_montgomery())
57assert got == want
58}
59
60fn test_bytes_montgomery_infinity() {
61mut p := new_identity_point()
62want := '0000000000000000000000000000000000000000000000000000000000000000'
63got := hex.encode(p.bytes_montgomery())
64
65assert got == want
66}
67
68const loworder_string = '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85'
69const loworder_bytes = hex.decode(loworder_string) or { panic(err) }
70
71fn fn_cofactor(mut data []u8) bool {
72if data.len != 64 {
73panic('data.len should be 64')
74}
75mut loworder := Point{}
76loworder.set_bytes(loworder_bytes) or { panic(err) }
77
78mut s := new_scalar()
79mut p := Point{}
80mut p8 := Point{}
81s.set_uniform_bytes(data) or { panic(err) }
82p.scalar_base_mult(mut s)
83p8.mult_by_cofactor(p)
84
85assert check_on_curve(p8) == true
86
87// 8 * p == (8 * s) * B
88mut sc := Scalar{
89s: [32]u8{}
90}
91sc.s[0] = u8(0x08)
92s.multiply(s, sc)
93mut pp := Point{}
94pp.scalar_base_mult(mut s)
95if p8.equal(pp) != 1 {
96return false
97}
98
99// 8 * p == 8 * (loworder + p)
100pp.add(p, loworder)
101pp.mult_by_cofactor(pp)
102if p8.equal(pp) != 1 {
103return false
104}
105
106// 8 * p == p + p + p + p + p + p + p + p
107pp.set(new_identity_point())
108for i := 0; i < 8; i++ {
109pp.add(pp, p)
110}
111return p8.equal(pp) == 1
112}
113
114fn test_mult_by_cofactor() {
115mut loworder := Point{}
116mut data := rand.bytes(64)!
117
118assert fn_cofactor(mut data) == true
119}
120
121fn invert_works(mut xinv Scalar, x NotZeroScalar) bool {
122xinv.invert(x)
123mut check := Scalar{}
124check.multiply(x, xinv)
125return check == sc_one && is_reduced(xinv)
126}
127
128fn test_scalar_invert() {
129nsc := generate_notzero_scalar(5) or { panic(err) }
130mut xsc := generate_scalar(5) or { panic(err) }
131assert invert_works(mut xsc, nsc) == true
132
133mut zero := new_scalar()
134mut xx := new_scalar()
135xx.invert(zero)
136assert xx.equal(zero) == 1
137}
138
139fn test_multiscalarmultmatchesbasemult() {
140for i in 0 .. 6 {
141x := generate_scalar(100) or { panic(err) }
142y := generate_scalar(5) or { panic(err) }
143z := generate_scalar(2) or { panic(err) }
144assert multiscalarmultmatchesbasemult(x, y, z) == true
145}
146}
147
148fn multiscalarmultmatchesbasemult(xx Scalar, yy Scalar, zz Scalar) bool {
149mut x := xx
150mut y := yy
151mut z := zz
152
153mut p := Point{}
154mut q1 := Point{}
155mut q2 := Point{}
156mut q3 := Point{}
157mut check := Point{}
158mut b := new_generator_point()
159
160p.multi_scalar_mult([x, y, z], [b, b, b])
161
162q1.scalar_base_mult(mut x)
163q2.scalar_base_mult(mut y)
164q3.scalar_base_mult(mut z)
165check.add(q1, q2)
166check.add(check, q3)
167
168check_on_curve(p, check, q1, q2, q3)
169return p.equal(check) == 1
170}
171
172fn vartime_multiscala_rmultmatches_basemult(xx Scalar, yy Scalar, zz Scalar) bool {
173mut x := xx
174mut y := yy
175mut z := zz
176mut p := Point{}
177mut q1 := Point{}
178mut q2 := Point{}
179mut q3 := Point{}
180mut check := Point{}
181mut b := new_generator_point()
182
183p.vartime_multiscalar_mult([x, y, z], [b, b, b])
184
185q1.scalar_base_mult(mut x)
186q2.scalar_base_mult(mut y)
187q3.scalar_base_mult(mut z)
188check.add(q1, q2)
189check.add(check, q3)
190
191check_on_curve(p, check, q1, q2, q3)
192return p.equal(check) == 1
193}
194
195fn test_vartimemultiscalarmultmatchesbasemult() {
196for i in 0 .. 5 {
197x := generate_scalar(100) or { panic(err) }
198y := generate_scalar(5) or { panic(err) }
199z := generate_scalar(2) or { panic(err) }
200assert vartime_multiscala_rmultmatches_basemult(x, y, z) == true
201}
202}
203