scalar_test.go raw
1 package p256k1
2
3 import (
4 "crypto/rand"
5 "testing"
6 )
7
8 func TestScalarBasics(t *testing.T) {
9 // Test zero scalar
10 var zero Scalar
11 if !zero.isZero() {
12 t.Error("Zero scalar should be zero")
13 }
14
15 // Test one scalar
16 var one Scalar
17 one.setInt(1)
18 if !one.isOne() {
19 t.Error("One scalar should be one")
20 }
21
22 // Test equality
23 var one2 Scalar
24 one2.setInt(1)
25 if !one.equal(&one2) {
26 t.Error("Two ones should be equal")
27 }
28 }
29
30 func TestScalarSetB32(t *testing.T) {
31 // Test setting from 32-byte array
32 testCases := []struct {
33 name string
34 bytes [32]byte
35 }{
36 {
37 name: "zero",
38 bytes: [32]byte{},
39 },
40 {
41 name: "one",
42 bytes: [32]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
43 },
44 {
45 name: "group_order_minus_one",
46 bytes: [32]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40},
47 },
48 {
49 name: "group_order",
50 bytes: [32]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41},
51 },
52 }
53
54 for _, tc := range testCases {
55 t.Run(tc.name, func(t *testing.T) {
56 var s Scalar
57 overflow := s.setB32(tc.bytes[:])
58
59 // Test round-trip
60 var result [32]byte
61 s.getB32(result[:])
62
63 // For group order, should reduce to zero
64 if tc.name == "group_order" {
65 if !s.isZero() {
66 t.Error("Group order should reduce to zero")
67 }
68 if !overflow {
69 t.Error("Group order should cause overflow")
70 }
71 }
72 })
73 }
74 }
75
76 func TestScalarSetB32Seckey(t *testing.T) {
77 // Test valid secret key
78 validKey := [32]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
79 var s Scalar
80 if !s.setB32Seckey(validKey[:]) {
81 t.Error("Valid secret key should be accepted")
82 }
83
84 // Test zero key (invalid)
85 zeroKey := [32]byte{}
86 if s.setB32Seckey(zeroKey[:]) {
87 t.Error("Zero secret key should be rejected")
88 }
89
90 // Test group order key (invalid)
91 orderKey := [32]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41}
92 if s.setB32Seckey(orderKey[:]) {
93 t.Error("Group order secret key should be rejected")
94 }
95 }
96
97 func TestScalarArithmetic(t *testing.T) {
98 // Test addition
99 var a, b, c Scalar
100 a.setInt(5)
101 b.setInt(7)
102 c.add(&a, &b)
103
104 var expected Scalar
105 expected.setInt(12)
106 if !c.equal(&expected) {
107 t.Error("5 + 7 should equal 12")
108 }
109
110 // Test multiplication
111 var mult Scalar
112 mult.mul(&a, &b)
113
114 expected.setInt(35)
115 if !mult.equal(&expected) {
116 t.Error("5 * 7 should equal 35")
117 }
118
119 // Test negation
120 var neg Scalar
121 neg.negate(&a)
122
123 var sum Scalar
124 sum.add(&a, &neg)
125
126 if !sum.isZero() {
127 t.Error("a + (-a) should equal zero")
128 }
129 }
130
131 func TestScalarInverse(t *testing.T) {
132 // Test inverse of small numbers
133 for i := uint(1); i <= 10; i++ {
134 var a, inv, product Scalar
135 a.setInt(i)
136 inv.inverse(&a)
137 product.mul(&a, &inv)
138
139 if !product.isOne() {
140 t.Errorf("a * a^(-1) should equal 1 for a = %d", i)
141 }
142 }
143 }
144
145 func TestScalarHalf(t *testing.T) {
146 // Test halving
147 var a, half, doubled Scalar
148
149 // Test even number
150 a.setInt(14)
151 half.half(&a)
152 doubled.add(&half, &half)
153 if !doubled.equal(&a) {
154 t.Error("2 * (14/2) should equal 14")
155 }
156
157 // Test odd number
158 a.setInt(7)
159 half.half(&a)
160 doubled.add(&half, &half)
161 if !doubled.equal(&a) {
162 t.Error("2 * (7/2) should equal 7")
163 }
164 }
165
166 func TestScalarProperties(t *testing.T) {
167 var a Scalar
168 a.setInt(6)
169
170 // Test even/odd
171 if !a.isEven() {
172 t.Error("6 should be even")
173 }
174
175 a.setInt(7)
176 if a.isEven() {
177 t.Error("7 should be odd")
178 }
179 }
180
181 func TestScalarConditionalNegate(t *testing.T) {
182 var a, original Scalar
183 a.setInt(5)
184 original = a
185
186 // Test conditional negate with flag = 0
187 a.condNegate(0)
188 if !a.equal(&original) {
189 t.Error("Conditional negate with flag=0 should not change value")
190 }
191
192 // Test conditional negate with flag = 1
193 a.condNegate(1)
194 var neg Scalar
195 neg.negate(&original)
196 if !a.equal(&neg) {
197 t.Error("Conditional negate with flag=1 should negate value")
198 }
199 }
200
201 func TestScalarGetBits(t *testing.T) {
202 var a Scalar
203 a.setInt(0x12345678)
204
205 // Test getting bits
206 bits := a.getBits(0, 8)
207 if bits != 0x78 {
208 t.Errorf("Expected 0x78, got 0x%x", bits)
209 }
210
211 bits = a.getBits(8, 8)
212 if bits != 0x56 {
213 t.Errorf("Expected 0x56, got 0x%x", bits)
214 }
215 }
216
217 func TestScalarConditionalMove(t *testing.T) {
218 var a, b, original Scalar
219 a.setInt(5)
220 b.setInt(10)
221 original = a
222
223 // Test conditional move with flag = 0
224 a.cmov(&b, 0)
225 if !a.equal(&original) {
226 t.Error("Conditional move with flag=0 should not change value")
227 }
228
229 // Test conditional move with flag = 1
230 a.cmov(&b, 1)
231 if !a.equal(&b) {
232 t.Error("Conditional move with flag=1 should copy value")
233 }
234 }
235
236 func TestScalarClear(t *testing.T) {
237 var s Scalar
238 s.setInt(12345)
239
240 s.clear()
241
242 // After clearing, should be zero
243 if !s.isZero() {
244 t.Error("Cleared scalar should be zero")
245 }
246 }
247
248 func TestScalarRandomOperations(t *testing.T) {
249 // Test with random values
250 for i := 0; i < 50; i++ {
251 var aBytes, bBytes [32]byte
252 rand.Read(aBytes[:])
253 rand.Read(bBytes[:])
254
255 var a, b Scalar
256 a.setB32(aBytes[:])
257 b.setB32(bBytes[:])
258
259 // Skip if either is zero
260 if a.isZero() || b.isZero() {
261 continue
262 }
263
264 // Test (a + b) - a = b
265 var sum, diff Scalar
266 sum.add(&a, &b)
267 diff.sub(&sum, &a)
268 if !diff.equal(&b) {
269 t.Errorf("Random test %d: (a + b) - a should equal b", i)
270 }
271
272 // Test (a * b) / a = b
273 var prod, quot Scalar
274 prod.mul(&a, &b)
275 var aInv Scalar
276 aInv.inverse(&a)
277 quot.mul(&prod, &aInv)
278 if !quot.equal(&b) {
279 t.Errorf("Random test %d: (a * b) / a should equal b", i)
280 }
281 }
282 }
283
284 func TestScalarEdgeCases(t *testing.T) {
285 // Test n-1 + 1 = 0
286 nMinus1 := [32]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40}
287
288 var s Scalar
289 s.setB32(nMinus1[:])
290
291 // Add 1 should give 0
292 var one Scalar
293 one.setInt(1)
294 s.add(&s, &one)
295
296 if !s.isZero() {
297 t.Error("(n-1) + 1 should equal 0 in scalar arithmetic")
298 }
299 }
300