code wiki / (root) / nx_ecdsa_p384_bisect_test.nx

nx_ecdsa_p384_bisect_test.nx source

↩ module page · 241 lines · 8191 B

1// nx_ecdsa_p384_bisect_test.nx -- bisect the verify failure on 2// RFC 6979 §A.2.6. Compares each substrate intermediate to the 3// Python golden bytes. Exit code identifies the first divergent 4// step. 5// 6// Step verdicts (returned as exit code): 7// 0 -- all steps match (verify would pass) 8// 1 -- s_inv diverges (p384_modn_inv broken at this scale) 9// 2 -- u1 diverges (p384_modn_mul broken or e_n wrong) 10// 3 -- u2 diverges (same primitives, different input) 11// 4 -- u1G.x diverges (scalar_mul or point_add broken) 12// 5 -- u2Q.x diverges (same scalar_mul, non-G base) 13// 14// expect_exit: 0 15// license_tier: ORIGINAL 16 17import "nx_syscalls.nx" 18import "nx_u384.nx" 19import "nx_p384_field.nx" 20import "nx_p384_field_mul.nx" 21import "nx_p384_field_inv.nx" 22import "nx_p384_modn.nx" 23import "nx_p384_point.nx" 24import "nx_p384_point_add.nx" 25import "nx_p384_scalar_mul.nx" 26import "nx_ecdsa_p384.nx" 27 28func dump_hex(label0: i64, label1: i64, buf: *i64) -> i64 { 29 let lab: *u8 = sys_mmap(8) 30 lab[0]=label0 as u8; lab[1]=label1 as u8; lab[2]=0x3D 31 sys_write(2, lab, 3) 32 var li: i64 = 11 33 while li >= 0 { 34 var bi: i64 = 0 35 while bi < 4 { 36 let b: i64 = (buf[li] >> ((3 - bi) * 8)) & 0xff 37 let hi: i64 = (b >> 4) & 0xf 38 let lo: i64 = b & 0xf 39 let chh: *u8 = sys_mmap(8) 40 if hi < 10 { chh[0] = (0x30 + hi) as u8 } else { chh[0] = (0x61 + hi - 10) as u8 } 41 if lo < 10 { chh[1] = (0x30 + lo) as u8 } else { chh[1] = (0x61 + lo - 10) as u8 } 42 sys_write(2, chh, 2) 43 bi = bi + 1 44 } 45 li = li - 1 46 } 47 let nl: *u8 = sys_mmap(8); nl[0]=0x0A; sys_write(2, nl, 1) 48 return 0 49} 50 51func limbs_eq(a: *i64, b: *i64) -> i64 { 52 var i: i64 = 0 53 while i < 12 { 54 if (a[i] & 0xFFFFFFFF) != (b[i] & 0xFFFFFFFF) { return 0 } 55 i = i + 1 56 } 57 return 1 58} 59 60func main() -> i64 { 61 // ---- Load inputs ---- 62 let pub_x: *i64 = u384_alloc() 63 pub_x[0]=0x5480BC13; pub_x[1]=0x64A25451; pub_x[2]=0x90558660; pub_x[3]=0xDEF8F0EA 64 pub_x[4]=0x6B300C64; pub_x[5]=0x06AAE528; pub_x[6]=0xAE92E02E; pub_x[7]=0xDA9A8BC4 65 pub_x[8]=0x9F427FA5; pub_x[9]=0x56861802; pub_x[10]=0x5B4E19A4; pub_x[11]=0xEC3A4E41 66 67 let pub_y: *i64 = u384_alloc() 68 pub_y[0]=0x33264720; pub_y[1]=0x7344FD25; pub_y[2]=0x3AE0D4FE; pub_y[3]=0x288B231C 69 pub_y[4]=0x3F1C9DB1; pub_y[5]=0xF54CA84B; pub_y[6]=0x67F9DFB9; pub_y[7]=0x6708A593 70 pub_y[8]=0xC0C62189; pub_y[9]=0x4EA8EF9A; pub_y[10]=0x2D7D5724; pub_y[11]=0x8015D9B7 71 72 let e: *i64 = u384_alloc() 73 e[0]=0x62ADD1BF; e[1]=0x62113D8A; e[2]=0x68E98915; e[3]=0x1A831D02 74 e[4]=0x94F41FC7; e[5]=0xE2ADE1D6; e[6]=0xAA9B6EC1; e[7]=0xAF2BDBE1 75 76 let sig_r: *i64 = u384_alloc() 77 sig_r[0]=0x6D8FB2CD; sig_r[1]=0x2FA2B3C3; sig_r[2]=0xE63355D9; sig_r[3]=0xBDE1E888 78 sig_r[4]=0x1D3DAA33; sig_r[5]=0x354B63A2; sig_r[6]=0x98D4EA8E; sig_r[7]=0x0C570C6F 79 sig_r[8]=0xF99AF8B3; sig_r[9]=0x392D03C5; sig_r[10]=0x013C7FA1; sig_r[11]=0x21B13D1E 80 81 let sig_s: *i64 = u384_alloc() 82 sig_s[0]=0xA4FA0AB0; sig_s[1]=0xC0CB8668; sig_s[2]=0xCD1AC42E; sig_s[3]=0xEFDC63EC 83 sig_s[4]=0xA7D1FEEB; sig_s[5]=0x5DB2266F; sig_s[6]=0xCA67E3D4; sig_s[7]=0x32068A10 84 sig_s[8]=0x38916746; sig_s[9]=0xF4BD77CB; sig_s[10]=0xB107745B; sig_s[11]=0xF3AA443F 85 86 // ---- STEP 1: s_inv = s^(-1) mod n ---- 87 let s_inv: *i64 = u384_alloc() 88 p384_modn_inv(s_inv, sig_s) 89 dump_hex(0x53, 0x49, s_inv) 90 91 let exp_s_inv: *i64 = u384_alloc() 92 exp_s_inv[0]=0xe78e2687 93 exp_s_inv[1]=0x831fb3fe 94 exp_s_inv[2]=0x62385ee3 95 exp_s_inv[3]=0xaf3e45c1 96 exp_s_inv[4]=0xfabb0e2f 97 exp_s_inv[5]=0x83e00ecf 98 exp_s_inv[6]=0x0ee27ee4 99 exp_s_inv[7]=0x8c968272 100 exp_s_inv[8]=0x72039531 101 exp_s_inv[9]=0xb57d6d77 102 exp_s_inv[10]=0xbeec8854 103 exp_s_inv[11]=0xe6cb2626 104 if limbs_eq(s_inv, exp_s_inv) != 1 { return 1 } 105 106 // ---- STEP 2: u1 = e_n * s_inv mod n ---- 107 let e_n: *i64 = u384_alloc() 108 p384_modn_reduce(e_n, e) 109 let u1: *i64 = u384_alloc() 110 p384_modn_mul(u1, e_n, s_inv) 111 dump_hex(0x55, 0x31, u1) 112 113 let exp_u1: *i64 = u384_alloc() 114 exp_u1[0]=0xc5e00ea7 115 exp_u1[1]=0x066146d0 116 exp_u1[2]=0xb0054274 117 exp_u1[3]=0xd654dcc9 118 exp_u1[4]=0x357ff82f 119 exp_u1[5]=0xe784cad5 120 exp_u1[6]=0x41ebcc1c 121 exp_u1[7]=0x66552301 122 exp_u1[8]=0x77b78df4 123 exp_u1[9]=0xcc728ec1 124 exp_u1[10]=0xb913ac04 125 exp_u1[11]=0xf3574de6 126 if limbs_eq(u1, exp_u1) != 1 { return 2 } 127 128 // ---- STEP 3: u2 = r * s_inv mod n ---- 129 let u2: *i64 = u384_alloc() 130 p384_modn_mul(u2, sig_r, s_inv) 131 dump_hex(0x55, 0x32, u2) 132 133 let exp_u2: *i64 = u384_alloc() 134 exp_u2[0]=0xee3a224e 135 exp_u2[1]=0x898092eb 136 exp_u2[2]=0x3c02fc43 137 exp_u2[3]=0x435e1d63 138 exp_u2[4]=0xd8c5f562 139 exp_u2[5]=0x85fa3dcc 140 exp_u2[6]=0x09a6ea23 141 exp_u2[7]=0xcf5641a1 142 exp_u2[8]=0xf9783c07 143 exp_u2[9]=0x7e854369 144 exp_u2[10]=0xf3af5e11 145 exp_u2[11]=0x1fcfa37d 146 if limbs_eq(u2, exp_u2) != 1 { return 3 } 147 148 // ---- STEP 4: u1*G ---- ORCHESTRATOR MODE: leave Jacobian ---- 149 let G: *P384Point = p384_point_alloc() 150 p384_point_load_g(G) 151 let u1G: *P384Point = p384_point_alloc() 152 p384_scalar_mul(u1G, u1, G) 153 // ORCHESTRATOR DOES NOT to_affine HERE -- snapshot a copy for affine check 154 let u1G_aff: *P384Point = p384_point_alloc() 155 p384_point_copy(u1G_aff, u1G) 156 p384_point_to_affine(u1G_aff) 157 dump_hex(0x47, 0x58, u1G_aff.x) 158 159 let exp_u1G_x: *i64 = u384_alloc() 160 exp_u1G_x[0]=0x5ce352f3 161 exp_u1G_x[1]=0x3f6a4b93 162 exp_u1G_x[2]=0x1615d28c 163 exp_u1G_x[3]=0x0ec5746d 164 exp_u1G_x[4]=0x7cebcfd6 165 exp_u1G_x[5]=0xabfeb127 166 exp_u1G_x[6]=0x8ce6be30 167 exp_u1G_x[7]=0x5632cb7a 168 exp_u1G_x[8]=0x1a016ef0 169 exp_u1G_x[9]=0xe8906341 170 exp_u1G_x[10]=0xba788535 171 exp_u1G_x[11]=0xd64326e9 172 if limbs_eq(u1G_aff.x, exp_u1G_x) != 1 { return 4 } 173 174 // ---- STEP 5: u2*Q ---- ORCHESTRATOR MODE: leave Jacobian ---- 175 let Q: *P384Point = p384_point_alloc() 176 p384_point_set_affine(Q, pub_x, pub_y) 177 let u2Q: *P384Point = p384_point_alloc() 178 p384_scalar_mul(u2Q, u2, Q) 179 let u2Q_aff: *P384Point = p384_point_alloc() 180 p384_point_copy(u2Q_aff, u2Q) 181 p384_point_to_affine(u2Q_aff) 182 dump_hex(0x51, 0x58, u2Q_aff.x) 183 184 let exp_u2Q_x: *i64 = u384_alloc() 185 exp_u2Q_x[0]=0xced576e0 186 exp_u2Q_x[1]=0xeb337a17 187 exp_u2Q_x[2]=0x3ea103a6 188 exp_u2Q_x[3]=0xaa404121 189 exp_u2Q_x[4]=0x6feff612 190 exp_u2Q_x[5]=0x1c097d31 191 exp_u2Q_x[6]=0xa59259b7 192 exp_u2Q_x[7]=0x1808dcde 193 exp_u2Q_x[8]=0xd987cde4 194 exp_u2Q_x[9]=0x69c1180e 195 exp_u2Q_x[10]=0x3daea37a 196 exp_u2Q_x[11]=0x922ade62 197 if limbs_eq(u2Q_aff.x, exp_u2Q_x) != 1 { return 5 } 198 199 // ---- STEP 6: R = u1G + u2Q ---- JACOBIAN INPUTS to point_add ---- 200 // This mirrors the orchestrator (which doesn't to_affine before add). 201 let R: *P384Point = p384_point_alloc() 202 p384_point_add(R, u1G, u2Q) 203 p384_point_to_affine(R) 204 dump_hex(0x52, 0x58, R.x) 205 206 let exp_R_x: *i64 = u384_alloc() 207 exp_R_x[0]=0x6D8FB2CD 208 exp_R_x[1]=0x2FA2B3C3 209 exp_R_x[2]=0xE63355D9 210 exp_R_x[3]=0xBDE1E888 211 exp_R_x[4]=0x1D3DAA33 212 exp_R_x[5]=0x354B63A2 213 exp_R_x[6]=0x98D4EA8E 214 exp_R_x[7]=0x0C570C6F 215 exp_R_x[8]=0xF99AF8B3 216 exp_R_x[9]=0x392D03C5 217 exp_R_x[10]=0x013C7FA1 218 exp_R_x[11]=0x21B13D1E 219 if limbs_eq(R.x, exp_R_x) != 1 { return 6 } 220 221 // ---- STEP 7: mirror orchestrator's final modn_eq check ---- 222 // Goal: verify orchestrator's "modn_eq(v, sig_r)" returns 1. 223 let v: *i64 = u384_alloc() 224 p384_modn_reduce(v, R.x) 225 dump_hex(0x56, 0x58, v) // "VX=" v post-reduce 226 227 if p384_modn_eq(v, sig_r) != 1 { return 7 } 228 229 // ---- STEP 8: call orchestrator with SAME inputs ---- 230 let orc: i64 = nx_ecdsa_p384_verify(pub_x, pub_y, e, sig_r, sig_s) 231 let lab2: *u8 = sys_mmap(8) 232 lab2[0]=0x4F; lab2[1]=0x52; lab2[2]=0x3D // "OR=" 233 sys_write(2, lab2, 3) 234 let d: *u8 = sys_mmap(8) 235 d[0] = (0x30 + orc) as u8 236 sys_write(2, d, 1) 237 let nl: *u8 = sys_mmap(8); nl[0]=0x0A; sys_write(2, nl, 1) 238 if orc != NX_ECDSA_P384_OK { return 8 } 239 240 return 0 241}