wnaf_sxs_test.go raw
1 //go:build !js && !wasm && !tinygo && !wasm32
2
3 package p256k1
4
5 import (
6 "crypto/rand"
7 "testing"
8
9 "next.orly.dev/pkg/p256k1/wnaf"
10 )
11
12 // TestWNAFSXS compares the standalone wnaf.Encode against the internal Scalar.wNAF
13 // method to verify they produce identical output for random 256-bit scalars.
14 func TestWNAFSXS(t *testing.T) {
15 const iterations = 1000
16
17 for w := uint(2); w <= 8; w++ {
18 t.Run("w="+itoa(int(w)), func(t *testing.T) {
19 for i := range iterations {
20 // Generate random scalar bytes and load into Scalar
21 // (setB32 may reduce mod n, so use s.d directly for both paths)
22 var buf [32]byte
23 if _, err := rand.Read(buf[:]); err != nil {
24 t.Fatal(err)
25 }
26
27 var s Scalar
28 s.setB32(buf[:])
29
30 // Use the (possibly reduced) limbs for both
31 standaloneResult := wnaf.Encode(s.d, int(w))
32
33 var internalResult [257]int8
34 internalBits := s.wNAF(&internalResult, w)
35
36 // Compare digit-for-digit
37 standaloneBits := standaloneResult.Len
38 if standaloneBits != internalBits {
39 t.Fatalf("iteration %d, w=%d: bit count mismatch: standalone=%d internal=%d",
40 i, w, standaloneBits, internalBits)
41 }
42
43 for j := range 257 {
44 if standaloneResult.D[j] != internalResult[j] {
45 t.Fatalf("iteration %d, w=%d: digit mismatch at position %d: standalone=%d internal=%d",
46 i, w, j, standaloneResult.D[j], internalResult[j])
47 }
48 }
49 }
50 })
51 }
52 }
53
54 // itoa converts int to string without importing strconv.
55 func itoa(n int) string {
56 if n == 0 {
57 return "0"
58 }
59 var buf [20]byte
60 i := len(buf)
61 for n > 0 {
62 i--
63 buf[i] = byte('0' + n%10)
64 n /= 10
65 }
66 return string(buf[i:])
67 }
68