code wiki / (root) / nx_ecdsa_p256_test.nx

nx_ecdsa_p256_test.nx source

↩ module page · 141 lines · 7011 B

1// nx_ecdsa_p256_test.nx -- KAT for ECDSA signature verification. 2// 3// Test vector: RFC 6979 §A.2.5 (NIST P-256 + SHA-256, msg = "sample") 4// 5// Pubkey: 6// x = 60FED4BA255A9D31C961EB74C6356D68 7// C049B8923B61FA6CE669622E60F29FB6 8// y = 7903FE1008B8BC99A41AE9E95628BC64 9// F2F1B20C2D7E9F5177A3C294D4462299 10// 11// msg = "sample" 12// SHA-256(msg) = AF2BDBE1AA9B6EC1E2ADE1D694F41FC7 13// 1A831D0268E9891562113D8A62ADD1BF 14// 15// Sig (deterministic per RFC 6979): 16// r = EFD48B2AACB6A8FD1140DD9CD45E81D6 17// 9D2C877B56AAF991C34D0EA84EAF3716 18// s = F7CB1C942D657C41D436C7A1B6E29F65 19// F3E900DBB9AFF4064DC4AB2F843ACDA8 20// 21// expect_exit: 0 22// license_tier: ORIGINAL 23 24import "nx_syscalls.nx" 25import "nx_u256.nx" 26import "nx_p256_field.nx" 27import "nx_p256_modn.nx" 28import "nx_ecdsa_p256.nx" 29 30func main() -> i64 { 31 // ---- Build all RFC 6979 §A.2.5 inputs as BE byte buffers ---- 32 33 // Pubkey x 34 let qx_bytes: *u8 = sys_mmap(32) 35 qx_bytes[0] = 0x60; qx_bytes[1] = 0xFE; qx_bytes[2] = 0xD4; qx_bytes[3] = 0xBA 36 qx_bytes[4] = 0x25; qx_bytes[5] = 0x5A; qx_bytes[6] = 0x9D; qx_bytes[7] = 0x31 37 qx_bytes[8] = 0xC9; qx_bytes[9] = 0x61; qx_bytes[10] = 0xEB; qx_bytes[11] = 0x74 38 qx_bytes[12] = 0xC6; qx_bytes[13] = 0x35; qx_bytes[14] = 0x6D; qx_bytes[15] = 0x68 39 qx_bytes[16] = 0xC0; qx_bytes[17] = 0x49; qx_bytes[18] = 0xB8; qx_bytes[19] = 0x92 40 qx_bytes[20] = 0x3B; qx_bytes[21] = 0x61; qx_bytes[22] = 0xFA; qx_bytes[23] = 0x6C 41 qx_bytes[24] = 0xE6; qx_bytes[25] = 0x69; qx_bytes[26] = 0x62; qx_bytes[27] = 0x2E 42 qx_bytes[28] = 0x60; qx_bytes[29] = 0xF2; qx_bytes[30] = 0x9F; qx_bytes[31] = 0xB6 43 44 // Pubkey y 45 let qy_bytes: *u8 = sys_mmap(32) 46 qy_bytes[0] = 0x79; qy_bytes[1] = 0x03; qy_bytes[2] = 0xFE; qy_bytes[3] = 0x10 47 qy_bytes[4] = 0x08; qy_bytes[5] = 0xB8; qy_bytes[6] = 0xBC; qy_bytes[7] = 0x99 48 qy_bytes[8] = 0xA4; qy_bytes[9] = 0x1A; qy_bytes[10] = 0xE9; qy_bytes[11] = 0xE9 49 qy_bytes[12] = 0x56; qy_bytes[13] = 0x28; qy_bytes[14] = 0xBC; qy_bytes[15] = 0x64 50 qy_bytes[16] = 0xF2; qy_bytes[17] = 0xF1; qy_bytes[18] = 0xB2; qy_bytes[19] = 0x0C 51 qy_bytes[20] = 0x2D; qy_bytes[21] = 0x7E; qy_bytes[22] = 0x9F; qy_bytes[23] = 0x51 52 qy_bytes[24] = 0x77; qy_bytes[25] = 0xA3; qy_bytes[26] = 0xC2; qy_bytes[27] = 0x94 53 qy_bytes[28] = 0xD4; qy_bytes[29] = 0x46; qy_bytes[30] = 0x22; qy_bytes[31] = 0x99 54 55 // SHA-256("sample") 56 let e_bytes: *u8 = sys_mmap(32) 57 e_bytes[0] = 0xAF; e_bytes[1] = 0x2B; e_bytes[2] = 0xDB; e_bytes[3] = 0xE1 58 e_bytes[4] = 0xAA; e_bytes[5] = 0x9B; e_bytes[6] = 0x6E; e_bytes[7] = 0xC1 59 e_bytes[8] = 0xE2; e_bytes[9] = 0xAD; e_bytes[10] = 0xE1; e_bytes[11] = 0xD6 60 e_bytes[12] = 0x94; e_bytes[13] = 0xF4; e_bytes[14] = 0x1F; e_bytes[15] = 0xC7 61 e_bytes[16] = 0x1A; e_bytes[17] = 0x83; e_bytes[18] = 0x1D; e_bytes[19] = 0x02 62 e_bytes[20] = 0x68; e_bytes[21] = 0xE9; e_bytes[22] = 0x89; e_bytes[23] = 0x15 63 e_bytes[24] = 0x62; e_bytes[25] = 0x11; e_bytes[26] = 0x3D; e_bytes[27] = 0x8A 64 e_bytes[28] = 0x62; e_bytes[29] = 0xAD; e_bytes[30] = 0xD1; e_bytes[31] = 0xBF 65 66 // Signature r 67 let r_bytes: *u8 = sys_mmap(32) 68 r_bytes[0] = 0xEF; r_bytes[1] = 0xD4; r_bytes[2] = 0x8B; r_bytes[3] = 0x2A 69 r_bytes[4] = 0xAC; r_bytes[5] = 0xB6; r_bytes[6] = 0xA8; r_bytes[7] = 0xFD 70 r_bytes[8] = 0x11; r_bytes[9] = 0x40; r_bytes[10] = 0xDD; r_bytes[11] = 0x9C 71 r_bytes[12] = 0xD4; r_bytes[13] = 0x5E; r_bytes[14] = 0x81; r_bytes[15] = 0xD6 72 r_bytes[16] = 0x9D; r_bytes[17] = 0x2C; r_bytes[18] = 0x87; r_bytes[19] = 0x7B 73 r_bytes[20] = 0x56; r_bytes[21] = 0xAA; r_bytes[22] = 0xF9; r_bytes[23] = 0x91 74 r_bytes[24] = 0xC3; r_bytes[25] = 0x4D; r_bytes[26] = 0x0E; r_bytes[27] = 0xA8 75 r_bytes[28] = 0x4E; r_bytes[29] = 0xAF; r_bytes[30] = 0x37; r_bytes[31] = 0x16 76 77 // Signature s 78 let s_bytes: *u8 = sys_mmap(32) 79 s_bytes[0] = 0xF7; s_bytes[1] = 0xCB; s_bytes[2] = 0x1C; s_bytes[3] = 0x94 80 s_bytes[4] = 0x2D; s_bytes[5] = 0x65; s_bytes[6] = 0x7C; s_bytes[7] = 0x41 81 s_bytes[8] = 0xD4; s_bytes[9] = 0x36; s_bytes[10] = 0xC7; s_bytes[11] = 0xA1 82 s_bytes[12] = 0xB6; s_bytes[13] = 0xE2; s_bytes[14] = 0x9F; s_bytes[15] = 0x65 83 s_bytes[16] = 0xF3; s_bytes[17] = 0xE9; s_bytes[18] = 0x00; s_bytes[19] = 0xDB 84 s_bytes[20] = 0xB9; s_bytes[21] = 0xAF; s_bytes[22] = 0xF4; s_bytes[23] = 0x06 85 s_bytes[24] = 0x4D; s_bytes[25] = 0xC4; s_bytes[26] = 0xAB; s_bytes[27] = 0x2F 86 s_bytes[28] = 0x84; s_bytes[29] = 0x3A; s_bytes[30] = 0xCD; s_bytes[31] = 0xA8 87 88 // Load into U256 limbs 89 let qx: *i64 = u256_alloc() 90 let qy: *i64 = u256_alloc() 91 let e: *i64 = u256_alloc() 92 let r: *i64 = u256_alloc() 93 let s: *i64 = u256_alloc() 94 u256_load_be(qx, qx_bytes) 95 u256_load_be(qy, qy_bytes) 96 u256_load_be(e, e_bytes) 97 u256_load_be(r, r_bytes) 98 u256_load_be(s, s_bytes) 99 100 // ---- Test A: positive verify -- RFC 6979 §A.2.5 sig is valid ---- 101 // <-- THE BIG ONE: first end-to-end ECDSA-P256 verify in our substrate 102 let v: i64 = nx_ecdsa_p256_verify(qx, qy, e, r, s) 103 if v != NX_ECDSA_OK { return 1 } 104 105 // ---- Test B: range check -- r = 0 rejected ---- 106 let zero: *i64 = u256_alloc() 107 u256_zero(zero) 108 if nx_ecdsa_p256_verify(qx, qy, e, zero, s) != NX_ECDSA_BAD_R_RANGE { return 10 } 109 110 // ---- Test C: range check -- s = 0 rejected ---- 111 if nx_ecdsa_p256_verify(qx, qy, e, r, zero) != NX_ECDSA_BAD_S_RANGE { return 20 } 112 113 // ---- Test D: range check -- r = n rejected ---- 114 let n: *i64 = u256_alloc() 115 p256_modn_load_n(n) 116 if nx_ecdsa_p256_verify(qx, qy, e, n, s) != NX_ECDSA_BAD_R_RANGE { return 30 } 117 118 // ---- Test E: range check -- s = n rejected ---- 119 if nx_ecdsa_p256_verify(qx, qy, e, r, n) != NX_ECDSA_BAD_S_RANGE { return 40 } 120 121 // ---- Test F: off-curve pubkey rejected ---- 122 let qx_bad: *i64 = u256_alloc() 123 u256_copy(qx_bad, qx) 124 qx_bad[0] = qx_bad[0] ^ 1 // flip LSB of x 125 if nx_ecdsa_p256_verify(qx_bad, qy, e, r, s) != NX_ECDSA_PUBKEY_NOT_ON_CURVE { return 50 } 126 127 // ---- Test G: verdict gate ---- 128 if nx_ecdsa_p256_verdict_is_valid(NX_ECDSA_OK) != 1 { return 60 } 129 if nx_ecdsa_p256_verdict_is_valid(NX_ECDSA_BAD_R_RANGE) != 1 { return 61 } 130 if nx_ecdsa_p256_verdict_is_valid(NX_ECDSA_BAD_S_RANGE) != 1 { return 62 } 131 if nx_ecdsa_p256_verdict_is_valid(NX_ECDSA_PUBKEY_NOT_ON_CURVE) != 1 { return 63 } 132 if nx_ecdsa_p256_verdict_is_valid(NX_ECDSA_PUBKEY_INFINITY) != 1 { return 64 } 133 if nx_ecdsa_p256_verdict_is_valid(NX_ECDSA_INFINITY_RESULT) != 1 { return 65 } 134 if nx_ecdsa_p256_verdict_is_valid(NX_ECDSA_BAD_SIG) != 1 { return 66 } 135 if nx_ecdsa_p256_verdict_is_valid(NX_ECDSA_VERDICT_N) != 0 { return 67 } 136 if nx_ecdsa_p256_verdict_is_valid(0) != 0 { return 68 } 137 if nx_ecdsa_p256_verdict_is_valid(0 - 1) != 0 { return 69 } 138 if nx_ecdsa_p256_verdict_is_valid(999) != 0 { return 70 } 139 140 return 0 141}