code wiki / (root) / nx_p256_wnaf_difftest.nx

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}