verifyhash 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +883 -0
  3. package/cli/abi/ContributionRegistry.json +881 -0
  4. package/cli/agent.js +2173 -0
  5. package/cli/anchor-artifact.js +853 -0
  6. package/cli/anchor.js +400 -0
  7. package/cli/claim.js +881 -0
  8. package/cli/core/agent-commit.js +448 -0
  9. package/cli/core/agent-session.js +598 -0
  10. package/cli/core/anchor-binding.js +663 -0
  11. package/cli/core/attestation.js +580 -0
  12. package/cli/core/evidence-plans.js +495 -0
  13. package/cli/core/fixtures/evidence-plans/baseline.json +19 -0
  14. package/cli/core/fulfill-intake.js +1082 -0
  15. package/cli/core/go-live-preflight.js +481 -0
  16. package/cli/core/license.js +534 -0
  17. package/cli/core/manifest.js +243 -0
  18. package/cli/core/packetseal.js +591 -0
  19. package/cli/core/registryArtifact.js +49 -0
  20. package/cli/core/revocation.js +539 -0
  21. package/cli/core/rfc3161.js +389 -0
  22. package/cli/core/timestamp.js +482 -0
  23. package/cli/core/trust-asof.js +479 -0
  24. package/cli/dataset.js +2950 -0
  25. package/cli/evidence.js +2227 -0
  26. package/cli/fulfill-webhook-http.js +438 -0
  27. package/cli/git.js +220 -0
  28. package/cli/hash.js +550 -0
  29. package/cli/identity.js +1072 -0
  30. package/cli/journal-cli.js +1110 -0
  31. package/cli/journal-log.js +454 -0
  32. package/cli/journal.js +334 -0
  33. package/cli/lineage.js +447 -0
  34. package/cli/list.js +287 -0
  35. package/cli/parcel.js +1509 -0
  36. package/cli/proof.js +578 -0
  37. package/cli/prove.js +300 -0
  38. package/cli/receipt.js +631 -0
  39. package/cli/registry.js +331 -0
  40. package/cli/reputation.js +344 -0
  41. package/cli/revocation.js +495 -0
  42. package/cli/serve-verify-http.js +298 -0
  43. package/cli/serve-verify.js +333 -0
  44. package/cli/show.js +339 -0
  45. package/cli/verify.js +383 -0
  46. package/cli/vh.js +3927 -0
  47. package/docs/ADOPT.md +183 -0
  48. package/docs/ADOPTION.json +11 -0
  49. package/docs/AGENTTRACE.md +247 -0
  50. package/docs/ANCHORING.md +167 -0
  51. package/docs/AUDIT.md +55 -0
  52. package/docs/CONFORMANCE.md +107 -0
  53. package/docs/DATALEDGER.md +638 -0
  54. package/docs/DECIDE.md +47 -0
  55. package/docs/DECISIONS-PENDING.md +27 -0
  56. package/docs/DEPLOY-PUBLIC-SITE.md +301 -0
  57. package/docs/ENGINE-LEDGER.json +12 -0
  58. package/docs/EVIDENCE.md +519 -0
  59. package/docs/GO-LIVE.md +66 -0
  60. package/docs/IDENTITY.md +123 -0
  61. package/docs/INDEPENDENT-VERIFICATION.md +377 -0
  62. package/docs/INTEGRITY-JOURNAL.md +337 -0
  63. package/docs/KEY-LIFECYCLE.md +179 -0
  64. package/docs/LICENSING.md +46 -0
  65. package/docs/LINEAGE.md +307 -0
  66. package/docs/LOOP-AUDIT-2026-07-03.json +580 -0
  67. package/docs/LOOP-HARDENING-PLAN.md +44 -0
  68. package/docs/MERKLE-LEAVES.md +113 -0
  69. package/docs/METRICS.jsonl +31 -0
  70. package/docs/MORNING.md +204 -0
  71. package/docs/PILOT.md +444 -0
  72. package/docs/PROOFPARCEL.md +227 -0
  73. package/docs/PROOFS.md +262 -0
  74. package/docs/RECEIPTS.md +341 -0
  75. package/docs/REPUTATION.md +158 -0
  76. package/docs/SDK.md +301 -0
  77. package/docs/STRATEGY-ARCHIVE.md +5055 -0
  78. package/docs/SUPERVISOR-RUNBOOK.md +52 -0
  79. package/docs/TRUST-BOUNDARIES.md +335 -0
  80. package/docs/TRUSTLEDGER.md +1976 -0
  81. package/docs/USAGE-BUDGET.json +121 -0
  82. package/docs/VERIFY-SERVICE.md +168 -0
  83. package/index.js +160 -0
  84. package/package.json +41 -0
  85. package/trustledger/build-standalone.js +796 -0
  86. package/trustledger/cli.js +3179 -0
  87. package/trustledger/close.js +391 -0
  88. package/trustledger/corpus.js +159 -0
  89. package/trustledger/dist/BUILD-PROVENANCE.json +99 -0
  90. package/trustledger/dist/trustledger-standalone.html +6197 -0
  91. package/trustledger/dist/trustledger-standalone.html.sha256 +1 -0
  92. package/trustledger/door-core.js +442 -0
  93. package/trustledger/fixtures/bank.csv +7 -0
  94. package/trustledger/fixtures/bank.malformed.csv +3 -0
  95. package/trustledger/fixtures/bank.noalias.csv +5 -0
  96. package/trustledger/fixtures/bank.ofx +34 -0
  97. package/trustledger/fixtures/bank.real.csv +5 -0
  98. package/trustledger/fixtures/corpus/_shared/prior-close.json +22 -0
  99. package/trustledger/fixtures/corpus/bank-book-mismatch--benign-twin/inputs.json +14 -0
  100. package/trustledger/fixtures/corpus/bank-book-mismatch--benign-twin/meta.json +7 -0
  101. package/trustledger/fixtures/corpus/bank-book-mismatch--out-of-trust/inputs.json +14 -0
  102. package/trustledger/fixtures/corpus/bank-book-mismatch--out-of-trust/meta.json +7 -0
  103. package/trustledger/fixtures/corpus/continuity-break--benign-twin/inputs.json +15 -0
  104. package/trustledger/fixtures/corpus/continuity-break--benign-twin/meta.json +7 -0
  105. package/trustledger/fixtures/corpus/continuity-break--out-of-trust/inputs.json +15 -0
  106. package/trustledger/fixtures/corpus/continuity-break--out-of-trust/meta.json +7 -0
  107. package/trustledger/fixtures/corpus/negative-tenant-ledger--benign-twin/inputs.json +13 -0
  108. package/trustledger/fixtures/corpus/negative-tenant-ledger--benign-twin/meta.json +7 -0
  109. package/trustledger/fixtures/corpus/negative-tenant-ledger--out-of-trust/inputs.json +13 -0
  110. package/trustledger/fixtures/corpus/negative-tenant-ledger--out-of-trust/meta.json +7 -0
  111. package/trustledger/fixtures/corpus/owner-overdraw--benign-twin/inputs.json +15 -0
  112. package/trustledger/fixtures/corpus/owner-overdraw--benign-twin/meta.json +7 -0
  113. package/trustledger/fixtures/corpus/owner-overdraw--out-of-trust/inputs.json +15 -0
  114. package/trustledger/fixtures/corpus/owner-overdraw--out-of-trust/meta.json +7 -0
  115. package/trustledger/fixtures/corpus/security-deposit-segregation--benign-twin/inputs.json +16 -0
  116. package/trustledger/fixtures/corpus/security-deposit-segregation--benign-twin/meta.json +7 -0
  117. package/trustledger/fixtures/corpus/security-deposit-segregation--out-of-trust/inputs.json +13 -0
  118. package/trustledger/fixtures/corpus/security-deposit-segregation--out-of-trust/meta.json +7 -0
  119. package/trustledger/fixtures/corpus/subledger-out-of-balance--benign-twin/inputs.json +13 -0
  120. package/trustledger/fixtures/corpus/subledger-out-of-balance--benign-twin/meta.json +7 -0
  121. package/trustledger/fixtures/corpus/subledger-out-of-balance--out-of-trust/inputs.json +13 -0
  122. package/trustledger/fixtures/corpus/subledger-out-of-balance--out-of-trust/meta.json +7 -0
  123. package/trustledger/fixtures/e2e/bank.aliased.csv +4 -0
  124. package/trustledger/fixtures/e2e/bank.csv +4 -0
  125. package/trustledger/fixtures/e2e/bank.nsf.csv +4 -0
  126. package/trustledger/fixtures/e2e/quickbooks.csv +6 -0
  127. package/trustledger/fixtures/e2e/quickbooks.nsf.csv +8 -0
  128. package/trustledger/fixtures/e2e/rentroll.csv +6 -0
  129. package/trustledger/fixtures/e2e/rentroll.nsf.csv +8 -0
  130. package/trustledger/fixtures/e2e/rentroll.short.csv +5 -0
  131. package/trustledger/fixtures/plans/baseline.json +25 -0
  132. package/trustledger/fixtures/plans/price-binding.example.json +27 -0
  133. package/trustledger/fixtures/policy/ambiguous-deposit-example.json +12 -0
  134. package/trustledger/fixtures/policy/baseline.json +19 -0
  135. package/trustledger/fixtures/policy/ca-example.json +12 -0
  136. package/trustledger/fixtures/policy/negative-tenant-ledger-example.json +12 -0
  137. package/trustledger/fixtures/policy/owner-overdraw-example.json +12 -0
  138. package/trustledger/fixtures/quickbooks.csv +7 -0
  139. package/trustledger/fixtures/quickbooks.real.csv +5 -0
  140. package/trustledger/fixtures/rentroll.csv +6 -0
  141. package/trustledger/fixtures/rentroll.real.csv +4 -0
  142. package/trustledger/ingest.js +1163 -0
  143. package/trustledger/lib/policy-bundled-loader.js +44 -0
  144. package/trustledger/lib/sha256-vendored.js +227 -0
  145. package/trustledger/license.js +563 -0
  146. package/trustledger/match.js +551 -0
  147. package/trustledger/plans.js +551 -0
  148. package/trustledger/policy.js +398 -0
  149. package/trustledger/public/index.html +512 -0
  150. package/trustledger/reconcile.js +1486 -0
  151. package/trustledger/report.js +887 -0
  152. package/trustledger/seal.js +854 -0
  153. package/trustledger/server.js +391 -0
  154. package/trustledger/valueproof.js +350 -0
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ // trustledger/lib/policy-bundled-loader.js — the policy module's SOLE impure seam (T-65.1).
4
+ //
5
+ // WHY THIS FILE EXISTS
6
+ // trustledger/policy.js is pure (readPolicy/validatePolicy/applyPolicy: no clock, no I/O, no hidden
7
+ // state) EXCEPT for one convenience: loading the bundled per-state fixture policies from disk so
8
+ // `vh trust reconcile --state <code>` can resolve a code without a file path. That filesystem code —
9
+ // and ONLY that code — lives here, behind one clearly-named module boundary, so:
10
+ // * the browser bundle (EPIC-65) can shim/replace THIS ONE FILE (e.g. with the fixture JSON inlined)
11
+ // and ship policy.js's pure path byte-for-byte unchanged;
12
+ // * a static purity scan of the browser path (test/trustledger.browser-core.test.js) can allow
13
+ // exactly one fs-requiring module — this one — and fail if fs/http/net/etc. creep in anywhere else.
14
+ // policy.js requires this module LAZILY (inside bundledPolicies(), never at module top level), so merely
15
+ // loading policy.js executes no fs/path require at all.
16
+ //
17
+ // RAW I/O ONLY — NO POLICY LOGIC
18
+ // Validation, sorting, error naming (PolicyError), and the {code,file,policy} entry shape all stay in
19
+ // policy.js, so this module cannot drift from the schema: it reads directory names and file text from
20
+ // the package's OWN bundled fixtures directory (never a caller path) and nothing more. Errors are thrown
21
+ // RAW; policy.js wraps them into the same named PolicyErrors it always threw — zero behavior change.
22
+
23
+ const fs = require("fs");
24
+ const path = require("path");
25
+
26
+ // The package's own bundled fixtures directory. Same absolute path as the historical
27
+ // policy.js constant (trustledger/fixtures/policy) — this file just lives one level down.
28
+ const BUNDLED_DIR = path.join(__dirname, "..", "fixtures", "policy");
29
+
30
+ // List the bundled policy fixture FILENAMES (the "*.json" basenames, unsorted — policy.js
31
+ // sorts them so ordering stays that module's documented, deterministic concern). Throws raw.
32
+ function listBundledPolicyNames() {
33
+ return fs.readdirSync(BUNDLED_DIR).filter((n) => n.endsWith(".json"));
34
+ }
35
+
36
+ // Read ONE bundled policy fixture by basename, returning { full, text } where `full` is the
37
+ // absolute path (policy.js reports it in each entry) and `text` is the raw UTF-8 file text
38
+ // (policy.js validates it). Throws raw.
39
+ function readBundledPolicyFile(name) {
40
+ const full = path.join(BUNDLED_DIR, name);
41
+ return { full, text: fs.readFileSync(full, "utf8") };
42
+ }
43
+
44
+ module.exports = { BUNDLED_DIR, listBundledPolicyNames, readBundledPolicyFile };
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+
3
+ // trustledger/lib/sha256-vendored.js — a PURE-JS, ZERO-DEPENDENCY SHA-256 (T-65.1).
4
+ //
5
+ // WHY THIS FILE EXISTS
6
+ // The TrustLedger reconciliation core (ingest -> match -> reconcile -> report -> close) is pure JS with
7
+ // ONE Node-only dependency left on its hot path: close.js took SHA-256 from Node's built-in `crypto` to
8
+ // compute the period-close `inputsDigest`. That is correct in Node but makes the core non-portable — a
9
+ // browser has no Node `crypto` builtin — and the zero-install offline app (EPIC-65) must run the SAME core,
10
+ // byte-for-byte, inside a single HTML file. This module is the missing piece: a from-scratch SHA-256 that
11
+ // `require`s NOTHING (no Node core, no third-party package, no relative module), following the EXACT
12
+ // discipline of verifier/lib/keccak256-vendored.js (T-35.1). It is a drop-in for the one call close.js
13
+ // makes, so every existing `inputsDigest` byte is UNCHANGED.
14
+ //
15
+ // CORRECTNESS, NOT NOVELTY
16
+ // SHA-256 is the FIXED, standardized FIPS 180-4 algorithm: 64-byte blocks, Merkle–Damgård padding
17
+ // (0x80, zero fill, 64-bit big-endian bit length), the 64 published K round constants (fractional cube
18
+ // roots of the first 64 primes) and 8 published H init words (fractional square roots of the first 8
19
+ // primes). Everything below runs on plain 32-bit JS integer ops (>>> and | keep values in uint32 space;
20
+ // sums of up to five uint32 values stay < 2^53 so plain + is exact before the final >>> 0). This is
21
+ // independent CODE but never an independent ALGORITHM: test/trustledger.browser-core.test.js proves the
22
+ // output byte-identical to Node's `crypto.createHash("sha256")` across the published vectors, every
23
+ // committed fixture file, every committed close artifact, all block-padding edge lengths, and hundreds of
24
+ // random buffers — a single mismatch FAILS the suite, so this file cannot silently diverge.
25
+ //
26
+ // UTF-8, EXPLICITLY
27
+ // close.js hashes a canonical JSON STRING as UTF-8. Node spells that Buffer.from(s, "utf8"); a browser
28
+ // spells it TextEncoder. To depend on NEITHER, utf8Bytes() below is a from-scratch WHATWG-compatible
29
+ // UTF-8 encoder (surrogate pairs combined; LONE surrogates replaced with U+FFFD — exactly what both
30
+ // Buffer.from(s, "utf8") and TextEncoder produce), cross-checked byte-for-byte against Buffer.from in the
31
+ // same test suite.
32
+ //
33
+ // REQUIRES NOTHING: a grep of this source finds no CommonJS require call and no bare-name import.
34
+ // (Intentional — this property is asserted by test/trustledger.browser-core.test.js.)
35
+
36
+ // ---- FIPS 180-4 round constants: first 32 bits of the fractional parts of the cube roots of the first
37
+ // 64 primes (2..311). Published, fixed, independently checkable against the standard. ----------------------
38
+ const K = [
39
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
40
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
41
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
42
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
43
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
44
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
45
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
46
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
47
+ ];
48
+
49
+ // 32-bit right-rotate (result kept unsigned via >>> 0 at the call sites' final masking).
50
+ function rotr(x, n) {
51
+ return ((x >>> n) | (x << (32 - n))) >>> 0;
52
+ }
53
+
54
+ // SHA-256 over `bytes` (Uint8Array/Buffer/array of byte values), returning a 32-byte Uint8Array.
55
+ function sha256Bytes(bytes) {
56
+ const len = bytes.length;
57
+
58
+ // ---- pad: 0x80, zero fill to 56 mod 64, then the 64-bit big-endian BIT length --------------------------
59
+ const total = Math.ceil((len + 9) / 64) * 64;
60
+ const msg = new Uint8Array(total); // zero-filled by construction
61
+ for (let i = 0; i < len; i++) msg[i] = bytes[i] & 0xff;
62
+ msg[len] = 0x80;
63
+ // Bit length as two 32-bit big-endian words. len < 2^53 in JS; the high word is floor(len*8 / 2^32)
64
+ // = floor(len / 2^29), the low word is (len*8) mod 2^32 (which is exactly what << gives).
65
+ const hiBits = Math.floor(len / 0x20000000);
66
+ const loBits = (len << 3) >>> 0;
67
+ msg[total - 8] = (hiBits >>> 24) & 0xff;
68
+ msg[total - 7] = (hiBits >>> 16) & 0xff;
69
+ msg[total - 6] = (hiBits >>> 8) & 0xff;
70
+ msg[total - 5] = hiBits & 0xff;
71
+ msg[total - 4] = (loBits >>> 24) & 0xff;
72
+ msg[total - 3] = (loBits >>> 16) & 0xff;
73
+ msg[total - 2] = (loBits >>> 8) & 0xff;
74
+ msg[total - 1] = loBits & 0xff;
75
+
76
+ // ---- FIPS 180-4 initial hash value ---------------------------------------------------------------------
77
+ let h0 = 0x6a09e667, h1 = 0xbb67ae85, h2 = 0x3c6ef372, h3 = 0xa54ff53a;
78
+ let h4 = 0x510e527f, h5 = 0x9b05688c, h6 = 0x1f83d9ab, h7 = 0x5be0cd19;
79
+
80
+ const w = new Array(64);
81
+
82
+ // ---- compress each 64-byte block -----------------------------------------------------------------------
83
+ for (let off = 0; off < total; off += 64) {
84
+ // message schedule: 16 big-endian words from the block, expanded to 64
85
+ for (let i = 0; i < 16; i++) {
86
+ const b = off + i * 4;
87
+ w[i] = ((msg[b] << 24) | (msg[b + 1] << 16) | (msg[b + 2] << 8) | msg[b + 3]) >>> 0;
88
+ }
89
+ for (let i = 16; i < 64; i++) {
90
+ const s0 = (rotr(w[i - 15], 7) ^ rotr(w[i - 15], 18) ^ (w[i - 15] >>> 3)) >>> 0;
91
+ const s1 = (rotr(w[i - 2], 17) ^ rotr(w[i - 2], 19) ^ (w[i - 2] >>> 10)) >>> 0;
92
+ w[i] = (w[i - 16] + s0 + w[i - 7] + s1) >>> 0;
93
+ }
94
+
95
+ let a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7;
96
+
97
+ for (let i = 0; i < 64; i++) {
98
+ const S1 = (rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25)) >>> 0;
99
+ const ch = ((e & f) ^ (~e & g)) >>> 0;
100
+ const temp1 = (h + S1 + ch + K[i] + w[i]) >>> 0;
101
+ const S0 = (rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22)) >>> 0;
102
+ const maj = ((a & b) ^ (a & c) ^ (b & c)) >>> 0;
103
+ const temp2 = (S0 + maj) >>> 0;
104
+ h = g;
105
+ g = f;
106
+ f = e;
107
+ e = (d + temp1) >>> 0;
108
+ d = c;
109
+ c = b;
110
+ b = a;
111
+ a = (temp1 + temp2) >>> 0;
112
+ }
113
+
114
+ h0 = (h0 + a) >>> 0;
115
+ h1 = (h1 + b) >>> 0;
116
+ h2 = (h2 + c) >>> 0;
117
+ h3 = (h3 + d) >>> 0;
118
+ h4 = (h4 + e) >>> 0;
119
+ h5 = (h5 + f) >>> 0;
120
+ h6 = (h6 + g) >>> 0;
121
+ h7 = (h7 + h) >>> 0;
122
+ }
123
+
124
+ // ---- emit the 8 words big-endian ------------------------------------------------------------------------
125
+ const out = new Uint8Array(32);
126
+ const hs = [h0, h1, h2, h3, h4, h5, h6, h7];
127
+ for (let i = 0; i < 8; i++) {
128
+ out[i * 4] = (hs[i] >>> 24) & 0xff;
129
+ out[i * 4 + 1] = (hs[i] >>> 16) & 0xff;
130
+ out[i * 4 + 2] = (hs[i] >>> 8) & 0xff;
131
+ out[i * 4 + 3] = hs[i] & 0xff;
132
+ }
133
+ return out;
134
+ }
135
+
136
+ // Lowercase hex (no 0x prefix) of a byte array — matches crypto's .digest("hex").
137
+ function toHex(bytes) {
138
+ let s = "";
139
+ for (let i = 0; i < bytes.length; i++) {
140
+ const b = bytes[i] & 0xff;
141
+ s += (b < 16 ? "0" : "") + b.toString(16);
142
+ }
143
+ return s;
144
+ }
145
+
146
+ /**
147
+ * WHATWG/Node-compatible UTF-8 encoder for a JS string: surrogate pairs are combined into their
148
+ * astral code point; LONE surrogates are replaced with U+FFFD (byte-for-byte what BOTH
149
+ * Buffer.from(s, "utf8") and TextEncoder emit). Pure; no TextEncoder, no Buffer.
150
+ * @param {string} str the JS (UTF-16) string to encode
151
+ * @returns {Uint8Array} the UTF-8 bytes
152
+ */
153
+ function utf8Bytes(str) {
154
+ if (typeof str !== "string") {
155
+ throw new TypeError("utf8Bytes requires a string");
156
+ }
157
+ const out = [];
158
+ for (let i = 0; i < str.length; i++) {
159
+ let cp = str.charCodeAt(i);
160
+ if (cp >= 0xd800 && cp <= 0xdbff) {
161
+ // high surrogate: pair with a following low surrogate, else U+FFFD
162
+ const next = i + 1 < str.length ? str.charCodeAt(i + 1) : 0;
163
+ if (next >= 0xdc00 && next <= 0xdfff) {
164
+ cp = 0x10000 + ((cp - 0xd800) << 10) + (next - 0xdc00);
165
+ i++;
166
+ } else {
167
+ cp = 0xfffd;
168
+ }
169
+ } else if (cp >= 0xdc00 && cp <= 0xdfff) {
170
+ // lone low surrogate
171
+ cp = 0xfffd;
172
+ }
173
+ if (cp < 0x80) {
174
+ out.push(cp);
175
+ } else if (cp < 0x800) {
176
+ out.push(0xc0 | (cp >> 6), 0x80 | (cp & 0x3f));
177
+ } else if (cp < 0x10000) {
178
+ out.push(0xe0 | (cp >> 12), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f));
179
+ } else {
180
+ out.push(
181
+ 0xf0 | (cp >> 18),
182
+ 0x80 | ((cp >> 12) & 0x3f),
183
+ 0x80 | ((cp >> 6) & 0x3f),
184
+ 0x80 | (cp & 0x3f)
185
+ );
186
+ }
187
+ }
188
+ return Uint8Array.from(out);
189
+ }
190
+
191
+ /**
192
+ * SHA-256 over a byte buffer.
193
+ * @param {Uint8Array|Buffer|number[]} bytes input bytes
194
+ * @returns {Uint8Array} the 32-byte digest
195
+ */
196
+ function sha256(bytes) {
197
+ if (
198
+ !(bytes instanceof Uint8Array) &&
199
+ !Array.isArray(bytes) &&
200
+ !(typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(bytes))
201
+ ) {
202
+ throw new TypeError("sha256 requires a Uint8Array/Buffer/byte-array of input bytes");
203
+ }
204
+ return sha256Bytes(bytes);
205
+ }
206
+
207
+ /**
208
+ * SHA-256 over a byte buffer, returned as a lowercase hex string WITHOUT a 0x prefix
209
+ * (matching crypto.createHash("sha256").update(bytes).digest("hex"), for drop-in cross-checking).
210
+ * @param {Uint8Array|Buffer|number[]} bytes input bytes
211
+ * @returns {string} 64-char lowercase hex
212
+ */
213
+ function sha256Hex(bytes) {
214
+ return toHex(sha256(bytes));
215
+ }
216
+
217
+ /**
218
+ * SHA-256 of a JS string's UTF-8 bytes, as lowercase hex — the exact drop-in for
219
+ * crypto.createHash("sha256").update(str, "utf8").digest("hex") (the one call close.js makes).
220
+ * @param {string} str the string to hash as UTF-8
221
+ * @returns {string} 64-char lowercase hex
222
+ */
223
+ function sha256HexUtf8(str) {
224
+ return toHex(sha256Bytes(utf8Bytes(str)));
225
+ }
226
+
227
+ module.exports = { sha256, sha256Hex, sha256HexUtf8, utf8Bytes };