code wiki / (root) / nx_rsa_pkcs1_v1_5_sha256_4096_real_test.nx

nx_rsa_pkcs1_v1_5_sha256_4096_real_test.nx source

↩ module page · 116 lines · 3986 B

1// nx_rsa_pkcs1_v1_5_sha256_4096_real_test.nx -- REAL RSA-4096 verify 2// against an openssl-generated keypair + signature. 3// 4// Proves the full PKCS1v1.5-SHA256 + RSA-4096 mod-exp + u4096_load_be 5// pipeline shipped this session works end-to-end against bytes 6// produced by a real production toolchain (openssl). No TLS, no 7// X.509, no PEM parsing -- just the load-bearing math + padding. 8// 9// Test fixtures (must exist before running): 10// /tmp/rsa4096_test_n.hex -- 1024-char hex of the 4096-bit modulus 11// + trailing newline 12// /tmp/rsa4096_test_msg.txt -- 23-byte message "hello-rsa4096-substrate" 13// /tmp/rsa4096_test.sig -- 512-byte raw RSA-PKCS1v1.5-SHA256 signature 14// 15// Generated by (host-side): 16// openssl genrsa -out rsa4096_test.key 4096 17// openssl rsa -in rsa4096_test.key -modulus -noout | sed 's/Modulus=//' \ 18// > rsa4096_test_n.hex 19// echo -n 'hello-rsa4096-substrate' > rsa4096_test_msg.txt 20// openssl dgst -sha256 -sign rsa4096_test.key -out rsa4096_test.sig \ 21// rsa4096_test_msg.txt 22// 23// expect_exit: 0 24 25import "nx_syscalls.nx" 26import "nx_u4096.nx" 27import "nx_rsa_pkcs1_v1_5_sha256_4096.nx" 28 29// Decode one hex char (ASCII) to nibble 0..15. Returns -1 on bad. 30func _hex_nibble(c: u8) -> i64 { 31 let ci: i64 = c as i64 32 if ci >= 48 { 33 if ci <= 57 { return ci - 48 } // 0..9 34 } 35 if ci >= 65 { 36 if ci <= 70 { return ci - 65 + 10 } // A..F 37 } 38 if ci >= 97 { 39 if ci <= 102 { return ci - 97 + 10 } // a..f 40 } 41 return 0 - 1 42} 43 44// Read entire file into out (caller-sized cap). Returns bytes read or 45// -1 on open fail. 46func _read_file(path: *u8, out: *u8, cap: i64) -> i64 { 47 let fd: i64 = sys_openat_rd(path) 48 if fd < 0 { return 0 - 1 } 49 var total: i64 = 0 50 var keep: i64 = 1 51 while keep == 1 { 52 let r: i64 = sys_read(fd, (out as i64 + total) as *u8, cap - total) 53 if r <= 0 { keep = 0 } 54 else { 55 total = total + r 56 if total >= cap { keep = 0 } 57 } 58 } 59 sys_close(fd) 60 return total 61} 62 63func main() -> i64 { 64 // ---- Load n (1024 hex chars + maybe trailing \n) ---- 65 let n_hex_path: *u8 = "/tmp/rsa4096_test_n.hex\x00" 66 let n_hex_buf: *u8 = sys_mmap(2048) 67 let n_hex_n: i64 = _read_file(n_hex_path, n_hex_buf, 2048) 68 if n_hex_n < 1024 { return 1 } 69 70 // Decode 1024 hex chars -> 512 raw bytes 71 let n_bytes: *u8 = sys_mmap(512) 72 var i: i64 = 0 73 while i < 512 { 74 let hi: i64 = _hex_nibble(n_hex_buf[i * 2]) 75 let lo: i64 = _hex_nibble(n_hex_buf[i * 2 + 1]) 76 if hi < 0 { return 2 } 77 if lo < 0 { return 3 } 78 n_bytes[i] = ((hi << 4) | lo) as u8 79 i = i + 1 80 } 81 82 let n: *i64 = u4096_alloc() 83 u4096_load_be(n, n_bytes) 84 85 // ---- Load msg ---- 86 let msg_path: *u8 = "/tmp/rsa4096_test_msg.txt\x00" 87 let msg_buf: *u8 = sys_mmap(128) 88 let msg_n: i64 = _read_file(msg_path, msg_buf, 128) 89 if msg_n != 23 { return 4 } 90 91 // ---- Load signature (raw 512 bytes) ---- 92 let sig_path: *u8 = "/tmp/rsa4096_test.sig\x00" 93 let sig_buf: *u8 = sys_mmap(512) 94 let sig_n: i64 = _read_file(sig_path, sig_buf, 512) 95 if sig_n != 512 { return 5 } 96 97 // ---- Verify ---- 98 let v: i64 = rsa_pkcs1_v1_5_sha256_4096_verify(msg_buf, msg_n, 99 sig_buf, n, 65537) 100 if v != NX_RSA_PKCS1_V15_4096_OK { 101 // Surface the verdict so we can diagnose if it fails. 102 return 10 + v 103 } 104 105 // ---- Negative case: flip one byte of msg, must NOT verify ---- 106 msg_buf[0] = (msg_buf[0] ^ 0x01) as u8 107 let v2: i64 = rsa_pkcs1_v1_5_sha256_4096_verify(msg_buf, msg_n, 108 sig_buf, n, 65537) 109 if v2 == NX_RSA_PKCS1_V15_4096_OK { return 20 } // must NOT pass 110 111 // "PASS\n" 112 let ok: *u8 = sys_mmap(8) 113 ok[0]=80; ok[1]=65; ok[2]=83; ok[3]=83; ok[4]=10 114 sys_write(1, ok, 5) 115 return 0 116}