nx_swhid_gate.nx source
↩ module page · 136 lines · 7673 B
1// nx_swhid_gate.nx -- GATE for nx_swhid_lib (SWHID, ISO/IEC 18670:2025).
2//
3// EVERY EXPECTED VALUE BELOW WAS PRODUCED BY AN INDEPENDENT IMPLEMENTATION -- git 2.49.0's
4// `git hash-object --stdin` -- and NOT by this code, not by hand, and not from memory. That is the
5// difference between a test and a tautology: a suite whose expectations are computed by the subject
6// passes for any self-consistent bug. This is the estate's ORACLE evidence class: agreement with an
7// independent implementation over published inputs.
8//
9// The vectors were chosen to cross the constructions that actually break:
10// 0 bytes -- the empty-object case a digit loop silently drops
11// 1, 3 bytes -- below one SHA-1 block
12// two 3-byte inputs -- same LENGTH, different CONTENT (a header-only hash would collide them)
13// 11, 12 bytes -- with and without a trailing newline
14// 64 bytes -- EXACTLY one SHA-1 block, before the header pushes it over
15// 256, 1000 bytes -- multi-block, and past the length where the decimal digit count changes
16// license_tier: ORIGINAL
17import "nx_syscalls.nx"
18import "nx_gate_verdict.nx"
19import "nx_swhid_lib.nx"
20
21// compute a SWHID over data and compare it, byte for byte and NUL-terminated, to an expected string.
22func swg_is(data: *u8, n: i64, want: *u8) -> i64 {
23 let out: *u8 = sys_mmap(SW_IDLEN + 8)
24 let r: i64 = swhid_cnt(data, n, out)
25 if r < 0 { return 0 }
26 var i: i64 = 0
27 while want[i] != (0 as u8) {
28 if out[i] != want[i] { return 0 }
29 i = i + 1
30 }
31 if out[i] != (0 as u8) { return 0 }
32 return 1
33}
34
35func swg_fill(c: i64, n: i64) -> *u8 {
36 let b: *u8 = sys_mmap(n + 8)
37 var i: i64 = 0
38 while i < n { b[i] = c as u8; i = i + 1 }
39 return b
40}
41
42func swg_lit(s: *u8) -> *u8 {
43 let n: i64 = sw_len(s)
44 let b: *u8 = sys_mmap(n + 8)
45 var i: i64 = 0
46 while i < n { b[i] = s[i]; i = i + 1 }
47 b[n] = 0 as u8
48 return b
49}
50
51func main(argc: i64, argv: *i64) -> i64 {
52 let ctr: *i64 = gv_ctr()
53 gv_head("=== nx_swhid_gate: SWHID vs git 2.49.0, an INDEPENDENT implementation ===" as *u8)
54
55 // ---- differential vectors, every expectation produced by git hash-object ----
56 let empty: *u8 = swg_fill(0, 8)
57 gv_check("empty-object-0-bytes" as *u8,
58 swg_is(empty, 0, "swh:1:cnt:e69de29bb2d1d6434b8b29ae775ad8c2e48c5391" as *u8), ctr)
59
60 gv_check("one-byte-a" as *u8,
61 swg_is(swg_lit("a" as *u8), 1, "swh:1:cnt:2e65efe2a145dda7ee51d1741299f848e5bf752e" as *u8), ctr)
62
63 gv_check("three-bytes-abc" as *u8,
64 swg_is(swg_lit("abc" as *u8), 3, "swh:1:cnt:f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f" as *u8), ctr)
65
66 // SAME LENGTH, DIFFERENT CONTENT. If the content were not hashed -- only the header -- these two
67 // would be identical, and every distinct 3-byte file in the library would share one identifier.
68 gv_check("three-bytes-abd-differs-from-abc-at-the-same-length" as *u8,
69 swg_is(swg_lit("abd" as *u8), 3, "swh:1:cnt:d4a5aa562b600d597c542a3610ae0b7b6ae0dbd7" as *u8), ctr)
70
71 gv_check("eleven-bytes-hello-world" as *u8,
72 swg_is(swg_lit("hello world" as *u8), 11, "swh:1:cnt:95d09f2b10159347eece71399a7e2e907ea3df4f" as *u8), ctr)
73
74 // twelve bytes: the same content plus a trailing newline, byte 10 CONSTRUCTED rather than written
75 // as a literal (a bare newline inside a string literal is ambiguous to this lexer).
76 let hw: *u8 = swg_lit("hello world" as *u8)
77 hw[11] = 10 as u8
78 hw[12] = 0 as u8
79 gv_check("twelve-bytes-hello-world-newline" as *u8,
80 swg_is(hw, 12, "swh:1:cnt:3b18e512dba79e4c8300dd08aeb37f8e728b8dad" as *u8), ctr)
81
82 // EXACTLY one SHA-1 block of content. The header then pushes the hashed buffer over the boundary,
83 // so this exercises the padding path the content length alone would not.
84 gv_check("sixty-four-bytes-exactly-one-sha1-block" as *u8,
85 swg_is(swg_fill(66, 64), 64, "swh:1:cnt:9df2c2a6dcd67d92e3c0c1117202782ad215cdf7" as *u8), ctr)
86
87 gv_check("two-hundred-fifty-six-bytes-multiblock" as *u8,
88 swg_is(swg_fill(65, 256), 256, "swh:1:cnt:6d1c7e6fac93e621235c6d97eafd91efe7c3b2da" as *u8), ctr)
89
90 // 1000 bytes: four decimal digits in the header, where a three-digit assumption would break.
91 gv_check("one-thousand-bytes-four-digit-length-header" as *u8,
92 swg_is(swg_fill(122, 1000), 1000, "swh:1:cnt:fe9b82970853ca6eb7b24d8969232f8bdfbccce8" as *u8), ctr)
93
94 // ---- well-formedness is checked by SHAPE, never trusted by origin ----
95 gv_check("wellformed-accepts-a-real-identifier" as *u8,
96 swhid_is_wellformed("swh:1:cnt:e69de29bb2d1d6434b8b29ae775ad8c2e48c5391" as *u8), ctr)
97 // UPPERCASE IS REFUSED. The syntax is lowercase; a case-insensitive reader is exactly how two
98 // identifiers for one object come into existence and then fail to join.
99 gv_check("wellformed-refuses-uppercase-hex" as *u8,
100 (swhid_is_wellformed("swh:1:cnt:E69DE29BB2D1D6434B8B29AE775AD8C2E48C5391" as *u8) == 0) as i64, ctr)
101 gv_check("wellformed-refuses-a-short-identifier" as *u8,
102 (swhid_is_wellformed("swh:1:cnt:e69de29bb2d1d6434b8b29ae775ad8c2e48c539" as *u8) == 0) as i64, ctr)
103 gv_check("wellformed-refuses-a-wrong-object-type" as *u8,
104 (swhid_is_wellformed("swh:1:dir:e69de29bb2d1d6434b8b29ae775ad8c2e48c5391" as *u8) == 0) as i64, ctr)
105 gv_check("wellformed-refuses-a-non-hex-character" as *u8,
106 (swhid_is_wellformed("swh:1:cnt:g69de29bb2d1d6434b8b29ae775ad8c2e48c5391" as *u8) == 0) as i64, ctr)
107 gv_check("wellformed-refuses-an-empty-string" as *u8,
108 (swhid_is_wellformed("" as *u8) == 0) as i64, ctr)
109
110 // ================= BITE-PROVEN NEGATIVE CONTROLS =================
111 // B1: IS THE GIT FRAMING ACTUALLY APPLIED? The FIPS-180 KAT plain SHA-1 of "abc" is
112 // a9993e364706816aba3e25717850c26c9cd0d89d -- nx_sha1's own smoke test asserts its first bytes.
113 // git's blob hash of the same three bytes is f2ba8f84... They differ ONLY because of the
114 // "blob 3\x00" header. If this organ ever hashed raw content, this tooth is the one that notices.
115 var b1_bad: i64 = 0
116 var b1_good: i64 = 0
117 if swg_is(swg_lit("abc" as *u8), 3, "swh:1:cnt:a9993e364706816aba3e25717850c26c9cd0d89d" as *u8) == 0 { b1_bad = 1 }
118 if swg_is(swg_lit("abc" as *u8), 3, "swh:1:cnt:f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f" as *u8) == 0 { b1_good = 1 }
119 gv_bite("neg-control-the-blob-header-is-applied-so-a-plain-sha1-does-NOT-match" as *u8, b1_bad, b1_good, ctr)
120
121 // B2: is the CONTENT hashed, or only the length? Two 3-byte inputs must not share an identifier.
122 var b2_bad: i64 = 0
123 var b2_good: i64 = 0
124 if swg_is(swg_lit("abd" as *u8), 3, "swh:1:cnt:f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f" as *u8) == 0 { b2_bad = 1 }
125 if swg_is(swg_lit("abc" as *u8), 3, "swh:1:cnt:f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f" as *u8) == 0 { b2_good = 1 }
126 gv_bite("neg-control-same-length-different-content-yields-a-different-identifier" as *u8, b2_bad, b2_good, ctr)
127
128 // B3: does the well-formedness check discriminate at all, or accept anything shaped roughly right?
129 var b3_bad: i64 = 0
130 var b3_good: i64 = 0
131 if swhid_is_wellformed("swh:1:cnt:E69DE29BB2D1D6434B8B29AE775AD8C2E48C5391" as *u8) == 0 { b3_bad = 1 }
132 if swhid_is_wellformed("swh:1:cnt:e69de29bb2d1d6434b8b29ae775ad8c2e48c5391" as *u8) == 0 { b3_good = 1 }
133 gv_bite("neg-control-wellformed-rejects-uppercase-and-accepts-the-lowercase-twin" as *u8, b3_bad, b3_good, ctr)
134
135 return gv_verdict("SWHID-GATE" as *u8, ctr, "nine differential vectors against git 2.49.0 agree byte for byte, and the blob framing is bite-proven" as *u8)
136}