v2 / vlib / crypto / ed25519 / internal / edwards25519 / scalar_test.v
209 lines · 169 sloc · 5.77 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1module edwards25519
2
3import os
4import rand
5import encoding.hex
6import math.big
7
8const github_job = os.getenv('GITHUB_JOB')
9
10fn testsuite_begin() {
11 if github_job != '' {
12 // ensure that the CI does not run flaky tests:
13 rand.seed([u32(0xffff24), 0xabcd])
14 }
15}
16
17fn test_scalar_equal() {
18 assert sc_one.equal(sc_minus_one) != 1
19
20 assert sc_minus_one.equal(sc_minus_one) != 0
21}
22
23fn test_scalar_non_adjacent_form() {
24 mut s := Scalar{
25 s: [u8(0x1a), 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d, 0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8,
26 0x26, 0x4d, 0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1, 0x58, 0x9e, 0x7b, 0x7f,
27 0x23, 0x76, 0xef, 0x09]!
28 }
29 expected_naf := [i8(0), 13, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, -11,
30 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 9, 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, 3, 0, 0,
31 0, 0, 11, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 9, 0, 0, 0,
32 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, -15, 0, 0, 0, 0, -7, 0, 0,
33 0, 0, -9, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, -11, 0, 0, 0,
34 0, -7, 0, 0, 0, 0, -13, 0, 0, 0, 0, 11, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
35 -15, 0, 0, 0, 0, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 13, 0, 0,
36 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
37 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, -15, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0,
38 0, 0, 0, 0, 1, 0, 0, 0, 0]
39
40 snaf := s.non_adjacent_form(5)
41 for i := 0; i < 256; i++ {
42 assert expected_naf[i] == snaf[i]
43 }
44}
45
46fn addlike_subneg(x Scalar, y Scalar) bool {
47 // Compute t1 = x - y
48 mut t1 := Scalar{}
49 t1.subtract(x, y)
50
51 // Compute t2 = -y + x
52 mut t2 := Scalar{}
53 t2.negate(y)
54 t2.add(t2, x)
55
56 return t1 == t2 && is_reduced(t1)
57}
58
59fn test_scalar_add_like_subneg() {
60 for i in 0 .. 15 {
61 x := generate_scalar(1000) or { panic(err) }
62 y := generate_scalar(1000) or { panic(err) }
63 assert addlike_subneg(x, y) == true
64 }
65}
66
67fn fg(sc Scalar) bool {
68 return is_reduced(sc)
69}
70
71fn test_scalar_generate() {
72 for i in 0 .. 15 {
73 sc := generate_scalar(1000) or { panic(err) }
74
75 assert fg(sc) == true
76 }
77}
78
79//
80fn test_scalar_set_canonical_bytes() {
81 for i in 0 .. 10 {
82 mut buf := rand.bytes(32) or { panic(err) }
83 mut sc := generate_scalar(1000) or { panic(err) }
84 buf[buf.len - 1] &= (1 << 4) - 1
85 sc = sc.set_canonical_bytes(buf) or { panic(err) }
86
87 assert buf[..] == sc.bytes()
88 assert is_reduced(sc)
89 }
90}
91
92fn test_scalar_set_canonical_bytes_round_trip() {
93 for i in 0 .. 10 {
94 mut sc1 := generate_scalar(2)!
95 mut sc2 := generate_scalar(6)!
96 sc2.set_canonical_bytes(sc1.bytes()) or { panic(err) }
97
98 assert sc1 == sc2
99 }
100}
101
102const sc_error = Scalar{
103 s: [32]u8{init: (u8(-1))}
104}
105
106fn test_scalar_set_canonical_bytes_on_noncanonical_value() {
107 mut b := sc_minus_one.s
108 b[31] += 1
109
110 mut s := sc_one
111 out :=
112 s.set_canonical_bytes(b[..]) or { sc_error } // set_canonical_bytes shouldn't worked on a non-canonical value"
113 assert out == sc_error
114 assert s == sc_one
115}
116
117fn test_scalar_set_uniform_bytes() {
118 // mod, _ := new(big.Integer).SetString("27742317777372353535851937790883648493", 10)
119 mut mod := big.integer_from_string('27742317777372353535851937790883648493')!
120 // mod.Add(mod, new(big.Integer).Lsh(big.NewInt(1), 252))
121 mod = mod + big.integer_from_i64(1).left_shift(252)
122
123 mut sc := generate_scalar(100)!
124 inp := rand.bytes(64)!
125
126 sc.set_uniform_bytes(inp[..])!
127 assert is_reduced(sc) == true
128
129 scbig := bigint_from_le_bytes(sc.s[..])
130 inbig := bigint_from_le_bytes(inp)
131 // return inbig.Mod(inbig, mod).Cmp(scbig) == 0
132 _, m := inbig.div_mod(mod)
133 assert m.abs_cmp(scbig) == 0 // NEED FIX
134}
135
136fn bigint_from_le_bytes(b []u8) big.Integer {
137 mut bc := b.clone()
138 buf := swap_endianness(mut bc) // WITHOUT THIS, some test would fail
139 bg := big.integer_from_bytes(buf)
140 return bg
141}
142
143fn test_scalar_set_bytes_with_clamping() {
144 // Generated with libsodium.js 1.0.18 crypto_scalarmult_ed25519_base.
145 /*
146 random := "633d368491364dc9cd4c1bf891b1d59460face1644813240a313e61f2c88216e"
147 s, _ := new(Scalar).SetBytesWithClamping(decodeHex(random))
148 p := new(Point).ScalarBaseMult(s)
149 want := "1d87a9026fd0126a5736fe1628c95dd419172b5b618457e041c9c861b2494a94"
150 if got := hex.EncodeToString(p.Bytes()); got != want {
151 t.Errorf("random: got %q, want %q", got, want)
152 }*/
153 random := '633d368491364dc9cd4c1bf891b1d59460face1644813240a313e61f2c88216e'
154 random_bytes := hex.decode(random) or { panic(err) }
155
156 mut s0 := Scalar{}
157 s0.set_bytes_with_clamping(random_bytes) or { panic(err) }
158
159 mut p0 := Point{}
160 p0.scalar_base_mult(mut s0)
161
162 want0 := '1d87a9026fd0126a5736fe1628c95dd419172b5b618457e041c9c861b2494a94'
163 got0 := hex.encode(p0.bytes())
164
165 assert got0 == want0
166
167 zero := '0000000000000000000000000000000000000000000000000000000000000000'
168 mut s1 := Scalar{}
169 zero_bytes := hex.decode(zero) or { panic(err) }
170 s1.set_bytes_with_clamping(zero_bytes) or { panic(err) }
171 mut p1 := Point{}
172 p1.scalar_base_mult(mut s1)
173
174 want1 := '693e47972caf527c7883ad1b39822f026f47db2ab0e1919955b8993aa04411d1'
175 got1 := hex.encode(p1.bytes())
176 assert want1 == got1
177
178 one := 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
179 mut s2 := Scalar{}
180 mut one_bytes := hex.decode(one) or { panic(err) }
181 s2.set_bytes_with_clamping(one_bytes) or { panic(err) }
182 mut p2 := Point{}
183 p2.scalar_base_mult(mut s2)
184
185 want2 := '12e9a68b73fd5aacdbcaf3e88c46fea6ebedb1aa84eed1842f07f8edab65e3a7'
186 got2 := hex.encode(p2.bytes())
187
188 assert want2 == got2
189}
190
191fn test_scalar_multiply_distributes_over_add() {
192 x := generate_scalar(100)!
193 y := generate_scalar(100)!
194 z := generate_scalar(100)!
195
196 // Compute t1 = (x+y)*z
197 mut t1 := Scalar{}
198 t1.add(x, y)
199 t1.multiply(t1, z)
200
201 // Compute t2 = x*z + y*z
202 mut t2 := Scalar{}
203 mut t3 := Scalar{}
204 t2.multiply(x, z)
205 t3.multiply(y, z)
206 t2.add(t2, t3)
207
208 assert t1 == t2 && is_reduced(t1) && is_reduced(t3)
209}
210