code wiki / (root) / nx_ecdsa_p256_sign_test.nx

nx_ecdsa_p256_sign_test.nx source

↩ module page · 86 lines · 3926 B

1// nx_ecdsa_p256_sign_smoke.nx -- MONITOR for ECDSA P-256 SIGN. 2// 3// Sign-then-verify round-trip: pure-NishiLang produces (r, s) for 4// a known (priv_key, msg_hash) pair, then feeds (priv_key * G, hash, 5// r, s) to the already-shipped nx_ecdsa_p256_verify. Verify MUST 6// return OK -- closes the loop that the sign side is producing 7// substrate-valid signatures. 8// 9// Test vector: RFC 6979 §A.2.5 NIST P-256 + SHA-256 with the 10// well-known sample privkey + message hash. 11// priv = 0xC9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721 12// hash = SHA-256("sample") = 0xAF2BDBE1AA9B6EC1E2ADE1D694F41FC71A831D0268E9891562113D8A62ADD1BF 13// 14// Expected r = 0xEFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716 15// Expected s = 0xF7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8 16// 17// We don't compare against the RFC vector directly (the byte-order 18// of internal limb representation makes the comparison fiddly); we 19// instead assert that our sign output VERIFIES against the matching 20// public key. That's the load-bearing property: sign produces a 21// signature that the substrate's own verify accepts. 22 23import "nx_syscalls.nx" 24import "nx_u256.nx" 25import "nx_p256_modn.nx" 26import "nx_p256_point.nx" 27import "nx_p256_scalar_mul.nx" 28import "nx_ecdsa_p256.nx" 29import "nx_ecdsa_p256_sign.nx" 30 31func main() -> i64 { 32 // Priv key (32 bytes big-endian). 33 let priv_bytes: *u8 = sys_mmap(32) 34 priv_bytes[0]=0xC9; priv_bytes[1]=0xAF; priv_bytes[2]=0xA9; priv_bytes[3]=0xD8 35 priv_bytes[4]=0x45; priv_bytes[5]=0xBA; priv_bytes[6]=0x75; priv_bytes[7]=0x16 36 priv_bytes[8]=0x6B; priv_bytes[9]=0x5C; priv_bytes[10]=0x21; priv_bytes[11]=0x57 37 priv_bytes[12]=0x67; priv_bytes[13]=0xB1; priv_bytes[14]=0xD6; priv_bytes[15]=0x93 38 priv_bytes[16]=0x4E; priv_bytes[17]=0x50; priv_bytes[18]=0xC3; priv_bytes[19]=0xDB 39 priv_bytes[20]=0x36; priv_bytes[21]=0xE8; priv_bytes[22]=0x9B; priv_bytes[23]=0x12 40 priv_bytes[24]=0x7B; priv_bytes[25]=0x8A; priv_bytes[26]=0x62; priv_bytes[27]=0x2B 41 priv_bytes[28]=0x12; priv_bytes[29]=0x0F; priv_bytes[30]=0x67; priv_bytes[31]=0x21 42 43 let priv_limbs: *i64 = u256_alloc() 44 u256_load_be(priv_limbs, priv_bytes) 45 46 // Message hash = SHA-256("sample") -- the RFC 6979 §A.2.5 vector. 47 let hash_bytes: *u8 = sys_mmap(32) 48 hash_bytes[0]=0xAF; hash_bytes[1]=0x2B; hash_bytes[2]=0xDB; hash_bytes[3]=0xE1 49 hash_bytes[4]=0xAA; hash_bytes[5]=0x9B; hash_bytes[6]=0x6E; hash_bytes[7]=0xC1 50 hash_bytes[8]=0xE2; hash_bytes[9]=0xAD; hash_bytes[10]=0xE1; hash_bytes[11]=0xD6 51 hash_bytes[12]=0x94; hash_bytes[13]=0xF4; hash_bytes[14]=0x1F; hash_bytes[15]=0xC7 52 hash_bytes[16]=0x1A; hash_bytes[17]=0x83; hash_bytes[18]=0x1D; hash_bytes[19]=0x02 53 hash_bytes[20]=0x68; hash_bytes[21]=0xE9; hash_bytes[22]=0x89; hash_bytes[23]=0x15 54 hash_bytes[24]=0x62; hash_bytes[25]=0x11; hash_bytes[26]=0x3D; hash_bytes[27]=0x8A 55 hash_bytes[28]=0x62; hash_bytes[29]=0xAD; hash_bytes[30]=0xD1; hash_bytes[31]=0xBF 56 57 let hash_limbs: *i64 = u256_alloc() 58 u256_load_be(hash_limbs, hash_bytes) 59 60 // Sign. 61 let r: *i64 = u256_alloc() 62 let s: *i64 = u256_alloc() 63 let sv: i64 = nx_ecdsa_p256_sign(priv_limbs, hash_limbs, r, s) 64 if sv != NX_ECDSA_SIGN_OK { return 1 } 65 66 // r and s should be non-zero. 67 if u256_is_zero(r) == 1 { return 2 } 68 if u256_is_zero(s) == 1 { return 3 } 69 70 // Derive public key Q = priv * G. 71 let g: *P256Point = p256_point_alloc() 72 p256_point_load_g(g) 73 let q: *P256Point = p256_point_alloc() 74 p256_scalar_mul(q, priv_limbs, g) 75 p256_point_to_affine(q) 76 77 // Round-trip: verify our (r, s) against Q + hash. 78 let vv: i64 = nx_ecdsa_p256_verify(q.x, q.y, hash_limbs, r, s) 79 if vv != 1 { return 10 } // 1 = verify OK 80 81 let ok: *u8 = sys_mmap(8) 82 ok[0]=80; ok[1]=65; ok[2]=83; ok[3]=83; ok[4]=10 // "PASS\n" 83 sys_write(1, ok, 5) 84 return 0 85 return 0 86}