nx_p256_wnaf_difftest.nx source
↩ module page · 75 lines · 2919 B
1// nx_p256_wnaf_difftest.nx -- prove p256_scalar_mul_wnaf == p256_scalar_mul (generic double-and-add,
2// the proven reference) over random scalars + edge cases (0, 1, small, high-bit-set). Compares in
3// AFFINE form (Jacobian reps of the same point differ in x/y/z but are equal after to_affine).
4// expect_exit: 0 license_tier: ORIGINAL
5import "nx_syscalls.nx"
6import "nx_csprng.nx"
7import "nx_p256_scalar_mul_wnaf.nx"
8import "nx_p256_scalar_mul.nx"
9
10func dp(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
11func dn(v: i64) -> i64 {
12 let t: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
13 let b: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 }
14 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
15 var i: i64 = 0; while i < k { b[i] = t[k-1-i]; i = i + 1 } sys_write(1, b, k); return 0
16}
17
18// compare k*G via wnaf vs generic in affine form. 1=equal.
19func chk(k: *i64, g: *P256Point) -> i64 {
20 let r1: *P256Point = p256_point_alloc()
21 let r2: *P256Point = p256_point_alloc()
22 p256_scalar_mul_wnaf(r1, k, g)
23 p256_scalar_mul(r2, k, g)
24 let a1: i64 = p256_point_is_infinity(r1)
25 let a2: i64 = p256_point_is_infinity(r2)
26 if a1 == 1 { if a2 == 1 { return 1 } return 0 }
27 if a2 == 1 { return 0 }
28 p256_point_to_affine(r1)
29 p256_point_to_affine(r2)
30 return p256_point_eq(r1, r2)
31}
32
33func main() -> i64 {
34 dp("=== nx_p256_wnaf_difftest: p256_scalar_mul_wnaf vs generic ===\n" as *u8)
35 let g: *P256Point = p256_point_alloc()
36 p256_point_load_g(g)
37 let k: *i64 = u256_alloc()
38 let be: *u8 = sys_mmap(32)
39 var pass: i64 = 0
40 var total: i64 = 0
41
42 // edge: k=0
43 var z: i64 = 0; while z < 8 { k[z] = 0; z = z + 1 }
44 pass = pass + chk(k, g); total = total + 1
45 // edge: k=1
46 k[0] = 1; z = 1; while z < 8 { k[z] = 0; z = z + 1 }
47 pass = pass + chk(k, g); total = total + 1
48 // edge: k=2,7,8,15,16 (wNAF digit boundaries)
49 var sm: i64 = 0
50 while sm < 5 {
51 z = 0; while z < 8 { k[z] = 0; z = z + 1 }
52 if sm == 0 { k[0] = 2 }
53 if sm == 1 { k[0] = 7 }
54 if sm == 2 { k[0] = 8 }
55 if sm == 3 { k[0] = 15 }
56 if sm == 4 { k[0] = 16 }
57 pass = pass + chk(k, g); total = total + 1
58 sm = sm + 1
59 }
60 // edge: all-ones low limb + high bit
61 z = 0; while z < 8 { k[z] = 0xffffffff; z = z + 1 }
62 pass = pass + chk(k, g); total = total + 1
63
64 // 400 random scalars
65 var n: i64 = 0
66 while n < 400 {
67 nx_csprng_fill(be, 32); u256_load_be(k, be)
68 pass = pass + chk(k, g); total = total + 1
69 n = n + 1
70 }
71
72 dp("=== WNAF-DIFFTEST pass=" as *u8); dn(pass); dp("/" as *u8); dn(total)
73 if pass == total { dp(" verdict=GREEN ===\n" as *u8); sys_exit(0); return 0 }
74 dp(" verdict=RED ===\n" as *u8); sys_exit(1); return 1
75}