code wiki / _hdl_build / nx_rsa_pkcs1_sign.nx
nx_rsa_pkcs1_sign.nx
buildroot/runtime/_hdl_build/nx_rsa_pkcs1_sign.nx
about
nx_rsa_pkcs1_sign.nx -- F103e RUNG 8: RSASSA-PKCS1-v1_5 SIGNING with SHA-256.
The estate shipped the VERIFY half years-equivalent ago and never the sign half, because its
modexp took the exponent as an i64 (fine for e = 65537, impossible for d ~2048 bits). Rung 4
removed that; rung 7 produces the key. This is the join.
RFC 8017 EMSA-PKCS1-v1_5, k = 256 (RSA-2048):
EM = 0x00 || 0x01 || PS(0xFF * 202) || 0x00 || DigestInfo(19) || H(32) = 256 bytes
s = EM^d mod n
★THE 19-BYTE DIGESTINFO PREFIX IS COMPOSED, NOT RETYPED. `rsa_pkcs1_sha256_di_byte` already
encodes it in the incumbent verifier; copying those bytes into this file by hand would be a
recalled constant AND a second source of truth that can drift. ★★★★★★**IF THE VERIFIER AND THE
SIGNER DISAGREE ABOUT A CONSTANT, EVERY SIGNATURE IS INVALID AND BOTH FILES LOOK CORRECT.**
★THE ORACLE IS THE INCUMBENT VERIFIER. Every tooth signs with this code and verifies with
`rsa_pkcs1_v1_5_sha256_verify` -- two independently written halves meeting in the middle. That is
a far stronger statement than any self-check, and it is why no golden vector is needed for the
round trip. ⚠It does NOT prove byte-agreement with another implementation's signatures; PKCS#1
v1.5 is deterministic so that IS checkable later against a known vector, and is named as owed.
Usage: nx_rsa_pkcs1_sign selftest (~5 min: generates a real 2048-bit modulus first)
Exit: 0 GREEN | 1 RED. Log -> knowledge/status/nishi_os.log, verdict= LAST.
license_tier: ORIGINAL
dependencies 12 imports · 3 importers
diagram shows first 10 each side; +2 more imports, +0 more importers in the complete lists below.
imports: nx_syscalls.nxnx_sha256.nxnx_u2048.nxnx_u2048_mul.nxnx_rsa2048_mod.nxnx_rsa2048_mod_exp.nxnx_rsa2048_mont.nxnx_rsa2048_mod_exp_big.nxnx_rsa_pkcs1_v1_5_sha256.nxnx_u2048_millerrabin.nxnx_u2048_smallops.nxnx_rsa_keygen.nx
imported by: nx_authenticode_sign.nxnx_efivars_enrol.nxnx_x509_emit.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 37 | const PS_MAGIC_20260808: i64 = 20260808 |
| 38 | const PS_MAGIC_1024: i64 = 1024 |
| 39 | const PS_MAGIC_65537: i64 = 65537 |
| 41 | const PS_K: i64 = 256 // RSA-2048 modulus bytes |
| 42 | const PS_TLEN: i64 = 51 // 19 DigestInfo + 32 SHA-256 |
| 43 | const PS_MINPAD: i64 = 8 // RFC 8017 floor for PS |
functions
| 45 | func ps_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } |
| 46 | func ps_fp(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 } |
| 47 | func ps_fn(fd: i64, v: i64) -> i64 |
| 57 | func ps_eq_str(a: *u8, b: *u8) -> i64 |
| 65 | func rsa_pkcs1_v1_5_sha256_em(em: *u8, msg: *u8, msg_len: i64) -> i64 |
| 83 | func rsa_pkcs1_v1_5_sha256_sign(sig_out: *u8, msg: *u8, msg_len: i64, d: *i64, n: *i64) -> i64 |
| 95 | func ps_selftest() -> i64 |
| 227 | func main(argc: i64, argv: *i64) -> i64 calls 1: ps_selftest |