code wiki / _hdl_build / nx_dr_encrypt_gate.nx

nx_dr_encrypt_gate.nx source

↩ module page · 54 lines · 3394 B

1import "nx_gate_gn.nx" 2// nx_dr_encrypt_gate.nx -- exceed-gate for CAP-DR-ENCRYPT. Proves encryption-at-rest: seal->open round-trips 3// byte-exact, the ciphertext is NOT plaintext (confidentiality), a single-byte tamper is REJECTED (auth), and a 4// wrong key is REJECTED (the plaintext is never emitted). This is what a plain cp to /mnt/d cannot do. 5// Sovereign: nx_syscalls + nx_sha256 + nx_chacha20_poly1305. expect_exit: 0 6import "nx_syscalls.nx" 7import "nx_sha256.nx" 8import "nx_chacha20_poly1305.nx" 9import "nx_gate_verdict.nx" 10 11func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 12func g_eq(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if a[i]!=b[i] { return 0 } i=i+1 } return 1 } 13 14func main(argc: i64, argv: *i64) -> i64 { 15 gp("=== nx_dr_encrypt_gate (encryption-at-rest: round-trip / confidential / tamper+wrongkey rejected) ===\n" as *u8) 16 var pass: i64=0; var fail: i64=0 17 18 let key: *u8 = sys_mmap(32); sha256_digest("my dr archive passphrase" as *u8, 24, key) 19 let pt: *u8 = "accounts: elderwesto = operator level 3 SECRET" as *u8 20 let n: i64 = 46 21 let dig: *u8 = sys_mmap(64); sha256_digest(pt, n, dig) // convergent nonce source 22 let ct: *u8 = sys_mmap(n + 16); let tag: *u8 = sys_mmap(32) 23 nx_chacha20_poly1305_encrypt(key, dig, "" as *u8, 0, pt, n, ct, tag) 24 25 // T1 round-trip 26 let pt2: *u8 = sys_mmap(n + 16) 27 let v1: i64 = nx_chacha20_poly1305_decrypt(key, dig, "" as *u8, 0, ct, n, tag, pt2) 28 if v1 == NX_AEAD_VERDICT_OK { if g_eq(pt, pt2, n) == 1 { pass=pass+1; gp(" T1 seal->open round-trip byte-exact PASS\n" as *u8) } else { fail=fail+1; gp(" T1 FAIL bytes\n" as *u8) } } else { fail=fail+1; gp(" T1 FAIL verdict\n" as *u8) } 29 30 // T2 confidentiality: ciphertext differs from plaintext 31 if g_eq(pt, ct, n) == 0 { pass=pass+1; gp(" T2 ciphertext != plaintext (confidential) PASS\n" as *u8) } else { fail=fail+1; gp(" T2 FAIL plaintext leaked\n" as *u8) } 32 33 // T3 tamper the ciphertext -> rejected 34 ct[0] = (ct[0] as i64 ^ 1) as u8 35 let v3: i64 = nx_chacha20_poly1305_decrypt(key, dig, "" as *u8, 0, ct, n, tag, pt2) 36 if v3 != NX_AEAD_VERDICT_OK { pass=pass+1; gp(" T3 single-byte ciphertext tamper -> REJECTED PASS\n" as *u8) } else { fail=fail+1; gp(" T3 FAIL tamper accepted\n" as *u8) } 37 ct[0] = (ct[0] as i64 ^ 1) as u8 // restore 38 39 // T4 wrong key -> rejected 40 let key2: *u8 = sys_mmap(32); sha256_digest("WRONG passphrase" as *u8, 16, key2) 41 let v4: i64 = nx_chacha20_poly1305_decrypt(key2, dig, "" as *u8, 0, ct, n, tag, pt2) 42 if v4 != NX_AEAD_VERDICT_OK { pass=pass+1; gp(" T4 wrong key -> REJECTED (plaintext never emitted) PASS\n" as *u8) } else { fail=fail+1; gp(" T4 FAIL wrong key accepted\n" as *u8) } 43 44 gp("RESULT pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail) 45 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 46 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 47 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 48 let ctr__dry: *i64 = gv_ctr() 49 ctr__dry[0] = pass 50 ctr__dry[1] = pass + fail 51 let rc__dry: i64 = gv_verdict("DR-ENCRYPT-GATE" as *u8, ctr__dry, "AEAD encryption-at-rest -- exceeds a plaintext cp)" as *u8) 52 sys_exit(rc__dry) 53 return rc__dry 54}