xoonya 3.1.8 → 3.1.10
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.
- package/README.md +70 -802
- package/RELEASE_NOTES.md +2 -9
- package/START_HERE.md +21 -21
- package/lib/external_proof_verify.js +189 -0
- package/package.json +14 -4
- package/proof_sdk.js +6692 -6561
- package/scripts/verify_external_proof_signature.js +128 -0
- package/scripts/verify_paid_execute.js +133 -0
- package/scripts/verify_paywall_flag.js +86 -0
- package/server.js +4430 -4223
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
`xoonya` 3.1.
|
|
1
|
+
`xoonya` 3.1.10 refreshes the public README and package metadata to lead with the proven capabilities: deterministic and post-quantum (Ed25519 + ML-DSA-65 hybrid) verification of the native XNYA machine-evidence format, demonstrated live via the paid x402 lane.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Highlights:
|
|
6
|
-
|
|
7
|
-
- keeps the deterministic hash, sign, and verify core, the verification-class and strict-mode behavior, and the trust-root options unchanged
|
|
8
|
-
- keeps the conformance and forgery-resistance vectors and the full verifier suite passing
|
|
9
|
-
- keeps the canonical `https://naxytra.com/xoonya` public product URL and the synchronized package posture intact
|
|
10
|
-
- tracks the runtime's discovery-description refresh so the proof and runtime packages stay on one release number
|
|
3
|
+
There is no change to the proof engine, verification behavior, vectors, or any route — this is a documentation and packaging refresh for public outreach.
|
package/START_HERE.md
CHANGED
|
@@ -4,7 +4,7 @@ This is the shortest reliable path for understanding and using the public `xoony
|
|
|
4
4
|
|
|
5
5
|
The phase program is now complete, so this file is the right starting point for a closed and release-shaped proof system rather than an in-flight milestone build.
|
|
6
6
|
|
|
7
|
-
The product-side implementation, proof posture, and bounded hybrid verification work for the widened `3.0.0` finish line are now complete. The remaining step is the synchronized public `3.0.0` release cut, publish, deploy, and verification sequence documented in
|
|
7
|
+
The product-side implementation, proof posture, and bounded hybrid verification work for the widened `3.0.0` finish line are now complete. The remaining step is the synchronized public `3.0.0` release cut, publish, deploy, and verification sequence documented in NAXYTRA_3_0_0_RELEASE_CONTRACT.md and PUBLISH_PLAN.md.
|
|
8
8
|
|
|
9
9
|
If you are arriving from the broader public discovery layer, the canonical entry points are:
|
|
10
10
|
|
|
@@ -68,13 +68,13 @@ This is the fastest way to see the intended proof-side package story end-to-end.
|
|
|
68
68
|
|
|
69
69
|
If you want the clearest cross-repo adoption path instead of the broad package tour, continue with:
|
|
70
70
|
|
|
71
|
-
-
|
|
71
|
+
- CARRIED_HANDOFF_DEMO.md
|
|
72
72
|
|
|
73
73
|
If you want the shortest neutral external-adoption bundle, continue with:
|
|
74
74
|
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
75
|
+
- PARTNER_READY_PATH.md
|
|
76
|
+
- PUBLIC_DEMO_SCRIPT.md
|
|
77
|
+
- EXAMPLE_PATHS.md
|
|
78
78
|
- `node examples/partner_proof_walkthrough.js`
|
|
79
79
|
|
|
80
80
|
## 3. Verify The Whole Package
|
|
@@ -91,8 +91,8 @@ This is the production-confidence check for the published proof package surface.
|
|
|
91
91
|
|
|
92
92
|
For long-term product understanding, read:
|
|
93
93
|
|
|
94
|
-
-
|
|
95
|
-
-
|
|
94
|
+
- FINAL_CONTRACT.md
|
|
95
|
+
- SERVICE_CONTRACT.md
|
|
96
96
|
- `GET /openapi.json`
|
|
97
97
|
- `GET /asyncapi.json`
|
|
98
98
|
- `GET /cloudevents.json`
|
|
@@ -117,23 +117,23 @@ For long-term product understanding, read:
|
|
|
117
117
|
- `GET /v1/result-package-trust`
|
|
118
118
|
- `GET /v1/event-systems`
|
|
119
119
|
- `GET /v1/integrations`
|
|
120
|
-
-
|
|
121
|
-
-
|
|
122
|
-
-
|
|
123
|
-
-
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
127
|
-
-
|
|
120
|
+
- PROGRAM_STATUS.md
|
|
121
|
+
- OPERATOR_START_HERE.md
|
|
122
|
+
- OPERATIONS_RUNBOOK.md
|
|
123
|
+
- PROGRAM_COMPLETE_RELEASE.md
|
|
124
|
+
- WHY_XYTARA_XOONYA.md
|
|
125
|
+
- CARRIED_HANDOFF_DEMO.md
|
|
126
|
+
- PARTNER_READY_PATH.md
|
|
127
|
+
- TERMINOLOGY.md
|
|
128
128
|
|
|
129
129
|
## 5. If You Are Integrating From Outside
|
|
130
130
|
|
|
131
131
|
Continue with:
|
|
132
132
|
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
-
|
|
133
|
+
- CROSS_RUNTIME_POSTURE.md
|
|
134
|
+
- integrations/PROOF_INTEGRATION_PROCESS.md
|
|
135
|
+
- PARTNER_READY_PATH.md
|
|
136
|
+
- COMPATIBILITY_NOTE.md
|
|
137
137
|
|
|
138
138
|
## 6. Production Reading Rule
|
|
139
139
|
|
|
@@ -155,5 +155,5 @@ If you want the shortest CLI-first read of the package after install, use:
|
|
|
155
155
|
|
|
156
156
|
Use:
|
|
157
157
|
|
|
158
|
-
-
|
|
159
|
-
-
|
|
158
|
+
- PROGRAM_STATUS.md
|
|
159
|
+
- OPERATOR_START_HERE.md
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// Cryptographic verification of IMPORTED external proofs.
|
|
4
|
+
//
|
|
5
|
+
// xoonya binds external proof material into its own bundles. This module lets it
|
|
6
|
+
// additionally VERIFY the external material's own signature — reporting the
|
|
7
|
+
// cryptographic FACTS it can establish, without over-claiming trust.
|
|
8
|
+
//
|
|
9
|
+
// Honesty model (important): from a single self-contained request, xoonya can
|
|
10
|
+
// only establish that "a signature is valid under key K" (signature_valid) and
|
|
11
|
+
// report K's fingerprint (signing_key_ref). It CANNOT establish that K is the
|
|
12
|
+
// legitimate issuer/attester, nor revocation or DID-resolution status. Trust in K
|
|
13
|
+
// is the consumer's decision. The only way a caller gets a trust-anchored result
|
|
14
|
+
// (expected_key_match=true) is by DECLARING, out of band, the key fingerprint they
|
|
15
|
+
// already trust (expected_key_ref) and having the signer match it. A key supplied
|
|
16
|
+
// in the same request — or a self-asserted key embedded in the proof — is NOT, by
|
|
17
|
+
// itself, treated as trusted.
|
|
18
|
+
//
|
|
19
|
+
// Dependency-free (node crypto). Supports compact JWS (EdDSA, ES256/384/512,
|
|
20
|
+
// ES256K, RS256/384/512, PS256/384/512) and generic detached signatures. Private
|
|
21
|
+
// key material (e.g. a JWK with a `d` component) is refused.
|
|
22
|
+
|
|
23
|
+
const crypto = require("crypto");
|
|
24
|
+
|
|
25
|
+
function b64urlToBuffer(s) {
|
|
26
|
+
const str = String(s || "").replace(/-/g, "+").replace(/_/g, "/");
|
|
27
|
+
const pad = str.length % 4 === 0 ? "" : "=".repeat(4 - (str.length % 4));
|
|
28
|
+
return Buffer.from(str + pad, "base64");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// alg -> { hash, kind, keyType?/curve? } ; curve/keyType bind the declared alg to
|
|
32
|
+
// the actual key so the reported alg describes how it was really validated.
|
|
33
|
+
const JWS_ALG = {
|
|
34
|
+
EdDSA: { hash: null, kind: "eddsa", keyType: "ed25519" },
|
|
35
|
+
ES256: { hash: "sha256", kind: "ecdsa", curve: "prime256v1" },
|
|
36
|
+
ES384: { hash: "sha384", kind: "ecdsa", curve: "secp384r1" },
|
|
37
|
+
ES512: { hash: "sha512", kind: "ecdsa", curve: "secp521r1" },
|
|
38
|
+
ES256K: { hash: "sha256", kind: "ecdsa", curve: "secp256k1" },
|
|
39
|
+
RS256: { hash: "sha256", kind: "rsa" },
|
|
40
|
+
RS384: { hash: "sha384", kind: "rsa" },
|
|
41
|
+
RS512: { hash: "sha512", kind: "rsa" },
|
|
42
|
+
PS256: { hash: "sha256", kind: "rsapss" },
|
|
43
|
+
PS384: { hash: "sha384", kind: "rsapss" },
|
|
44
|
+
PS512: { hash: "sha512", kind: "rsapss" }
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
function isPrivateJwk(obj) {
|
|
48
|
+
return Boolean(obj && typeof obj === "object" && !Buffer.isBuffer(obj) && typeof obj.d === "string" && obj.d.length > 0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Build a PUBLIC KeyObject from PEM / base64 DER SPKI / public JWK. Refuses
|
|
52
|
+
// private key material. Returns null on any problem.
|
|
53
|
+
function toPublicKeyObject(input) {
|
|
54
|
+
if (!input) return null;
|
|
55
|
+
try {
|
|
56
|
+
if (typeof input === "object" && !Buffer.isBuffer(input)) {
|
|
57
|
+
if (isPrivateJwk(input)) return null; // never accept private material
|
|
58
|
+
return crypto.createPublicKey({ key: input, format: "jwk" });
|
|
59
|
+
}
|
|
60
|
+
const s = String(input).trim();
|
|
61
|
+
if (/BEGIN (EC |RSA |DSA |OPENSSH |PGP )?PRIVATE KEY/.test(s)) return null;
|
|
62
|
+
if (s.includes("BEGIN ")) return crypto.createPublicKey({ key: s, format: "pem" });
|
|
63
|
+
return crypto.createPublicKey({ key: Buffer.from(s, "base64"), format: "der", type: "spki" });
|
|
64
|
+
} catch (_) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function keyRef(keyObject) {
|
|
70
|
+
try {
|
|
71
|
+
const spki = keyObject.export({ type: "spki", format: "der" });
|
|
72
|
+
const algo = keyObject.asymmetricKeyType || "key";
|
|
73
|
+
return `${algo}-spki-sha256:` + crypto.createHash("sha256").update(spki).digest("hex");
|
|
74
|
+
} catch (_) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// The declared alg must be consistent with the actual key type/curve.
|
|
80
|
+
function keyMatchesAlg(keyObject, alg) {
|
|
81
|
+
const spec = JWS_ALG[alg];
|
|
82
|
+
if (!spec || !keyObject) return false;
|
|
83
|
+
const t = keyObject.asymmetricKeyType;
|
|
84
|
+
if (spec.kind === "eddsa") return t === "ed25519";
|
|
85
|
+
if (spec.kind === "ecdsa") {
|
|
86
|
+
if (t !== "ec") return false;
|
|
87
|
+
const details = keyObject.asymmetricKeyDetails || {};
|
|
88
|
+
return details.namedCurve === spec.curve;
|
|
89
|
+
}
|
|
90
|
+
if (spec.kind === "rsa" || spec.kind === "rsapss") return t === "rsa" || t === "rsa-pss";
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function verifyWithAlg(alg, signingInput, signature, keyObject) {
|
|
95
|
+
const spec = JWS_ALG[alg];
|
|
96
|
+
if (!spec || !keyObject) return false;
|
|
97
|
+
if (!keyMatchesAlg(keyObject, alg)) return false; // bind declared alg to the key
|
|
98
|
+
const data = Buffer.isBuffer(signingInput) ? signingInput : Buffer.from(String(signingInput), "utf8");
|
|
99
|
+
try {
|
|
100
|
+
if (spec.kind === "eddsa") return crypto.verify(null, data, keyObject, signature);
|
|
101
|
+
if (spec.kind === "ecdsa") return crypto.verify(spec.hash, data, { key: keyObject, dsaEncoding: "ieee-p1363" }, signature);
|
|
102
|
+
if (spec.kind === "rsa") return crypto.verify(spec.hash, data, keyObject, signature);
|
|
103
|
+
if (spec.kind === "rsapss") {
|
|
104
|
+
return crypto.verify(spec.hash, data, { key: keyObject, padding: crypto.constants.RSA_PKCS1_PSS_PADDING, saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST }, signature);
|
|
105
|
+
}
|
|
106
|
+
} catch (_) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function trustResult(signatureValid, keyObject, keySource, expectedKeyRef, alg, extra) {
|
|
113
|
+
const kref = keyRef(keyObject);
|
|
114
|
+
const expected = typeof expectedKeyRef === "string" && expectedKeyRef.trim() ? expectedKeyRef.trim() : null;
|
|
115
|
+
const expectedMatch = expected ? kref === expected : null;
|
|
116
|
+
return {
|
|
117
|
+
ok: true,
|
|
118
|
+
signature_valid: signatureValid === true,
|
|
119
|
+
signing_key_ref: kref,
|
|
120
|
+
key_source: keySource,
|
|
121
|
+
expected_key_ref: expected,
|
|
122
|
+
// true only when the caller declared a trusted key fingerprint AND the signer
|
|
123
|
+
// matches it; null when no expectation was declared. Trust in signing_key_ref
|
|
124
|
+
// is otherwise the consumer's decision.
|
|
125
|
+
expected_key_match: expectedMatch,
|
|
126
|
+
trust_anchored: signatureValid === true && expectedMatch === true,
|
|
127
|
+
alg,
|
|
128
|
+
...(extra || {})
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Verify a compact JWS. opts = { trusted_public_key?, expected_key_ref? }.
|
|
133
|
+
function verifyJws(jwsCompact, opts) {
|
|
134
|
+
const o = opts && typeof opts === "object" ? opts : {};
|
|
135
|
+
const parts = String(jwsCompact || "").split(".");
|
|
136
|
+
if (parts.length !== 3) return { ok: false, reason: "jws_malformed" };
|
|
137
|
+
const [protectedB64, payloadB64, signatureB64] = parts;
|
|
138
|
+
let header;
|
|
139
|
+
try {
|
|
140
|
+
header = JSON.parse(b64urlToBuffer(protectedB64).toString("utf8"));
|
|
141
|
+
} catch (_) {
|
|
142
|
+
return { ok: false, reason: "jws_header_invalid" };
|
|
143
|
+
}
|
|
144
|
+
const alg = header && typeof header.alg === "string" ? header.alg : null;
|
|
145
|
+
if (alg === "none") return { ok: false, reason: "jws_alg_none_rejected" };
|
|
146
|
+
if (!alg || !JWS_ALG[alg]) return { ok: false, reason: "jws_alg_unsupported", alg: alg || null };
|
|
147
|
+
// Refuse unknown critical extensions and non-standard signing-input variants.
|
|
148
|
+
if (Array.isArray(header.crit) && header.crit.length > 0) return { ok: false, reason: "jws_crit_unsupported" };
|
|
149
|
+
if (header.b64 === false) return { ok: false, reason: "jws_unencoded_payload_unsupported" };
|
|
150
|
+
|
|
151
|
+
const trustedKey = o.trusted_public_key ? toPublicKeyObject(o.trusted_public_key) : null;
|
|
152
|
+
const embeddedKey = !trustedKey && header.jwk ? toPublicKeyObject(header.jwk) : null;
|
|
153
|
+
const keyObject = trustedKey || embeddedKey;
|
|
154
|
+
if (!keyObject) return { ok: false, reason: "no_public_key" };
|
|
155
|
+
|
|
156
|
+
const valid = verifyWithAlg(alg, `${protectedB64}.${payloadB64}`, b64urlToBuffer(signatureB64), keyObject);
|
|
157
|
+
return trustResult(valid, keyObject, trustedKey ? "caller_supplied" : "embedded_self_asserted", o.expected_key_ref, alg, {
|
|
158
|
+
header,
|
|
159
|
+
payload_b64url: payloadB64
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Verify a detached signature over `material`. opts = { material, signature,
|
|
164
|
+
// signature_encoding?, public_key, algorithm, expected_key_ref? }.
|
|
165
|
+
function verifyDetachedSignature(opts) {
|
|
166
|
+
const o = opts && typeof opts === "object" ? opts : {};
|
|
167
|
+
const alg = typeof o.algorithm === "string" ? o.algorithm : null;
|
|
168
|
+
if (!alg || !JWS_ALG[alg]) return { ok: false, reason: "algorithm_unsupported", alg: alg || null };
|
|
169
|
+
const keyObject = toPublicKeyObject(o.public_key);
|
|
170
|
+
if (!keyObject) return { ok: false, reason: "no_public_key" };
|
|
171
|
+
if (o.material === undefined || o.material === null) return { ok: false, reason: "material_required" };
|
|
172
|
+
const material = Buffer.isBuffer(o.material) ? o.material : Buffer.from(String(o.material), "utf8");
|
|
173
|
+
let signature;
|
|
174
|
+
try {
|
|
175
|
+
const enc = o.signature_encoding === "hex" ? "hex" : o.signature_encoding === "base64url" ? null : "base64";
|
|
176
|
+
signature = enc ? Buffer.from(String(o.signature || ""), enc) : b64urlToBuffer(o.signature);
|
|
177
|
+
} catch (_) {
|
|
178
|
+
return { ok: false, reason: "signature_invalid" };
|
|
179
|
+
}
|
|
180
|
+
if (signature.length === 0) return { ok: false, reason: "signature_invalid" };
|
|
181
|
+
const valid = verifyWithAlg(alg, material, signature, keyObject);
|
|
182
|
+
return trustResult(valid, keyObject, "caller_supplied", o.expected_key_ref, alg);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function looksLikeCompactJws(s) {
|
|
186
|
+
return typeof s === "string" && /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(s.trim());
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
module.exports = { verifyJws, verifyDetachedSignature, toPublicKeyObject, isPrivateJwk, looksLikeCompactJws };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xoonya",
|
|
3
|
-
"version": "3.1.
|
|
4
|
-
"description": "Deterministic proof and review engine for receipts, handoffs, governance, and
|
|
3
|
+
"version": "3.1.10",
|
|
4
|
+
"description": "Deterministic proof and review engine with post-quantum verification (Ed25519 + ML-DSA-65 hybrid) for receipts, handoffs, governance, and the native XNYA machine-evidence format. Verified live via the paid x402 lane.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"xoonya": "bin/xoonya.js",
|
|
@@ -69,13 +69,23 @@
|
|
|
69
69
|
"proof-bundle",
|
|
70
70
|
"deterministic",
|
|
71
71
|
"machine",
|
|
72
|
-
"evidence"
|
|
72
|
+
"evidence",
|
|
73
|
+
"post-quantum",
|
|
74
|
+
"ml-dsa",
|
|
75
|
+
"slh-dsa",
|
|
76
|
+
"pqc",
|
|
77
|
+
"xnya",
|
|
78
|
+
"ed25519",
|
|
79
|
+
"x402"
|
|
73
80
|
],
|
|
74
81
|
"scripts": {
|
|
75
82
|
"start": "node server.js",
|
|
76
83
|
"verify:package": "node scripts/verify_all.js",
|
|
77
84
|
"verify:conformance": "node scripts/verify_vectors.js",
|
|
78
85
|
"verify:external-proof-import-gate": "node scripts/verify_external_proof_import_gate.js",
|
|
86
|
+
"verify:external-proof-signature": "node scripts/verify_external_proof_signature.js",
|
|
87
|
+
"verify:paid-execute": "node scripts/verify_paid_execute.js",
|
|
88
|
+
"verify:paywall-flag": "node scripts/verify_paywall_flag.js",
|
|
79
89
|
"verify:integrations": "node scripts/verify_integrations.js",
|
|
80
90
|
"verify:tooling": "node scripts/verify_tooling.js",
|
|
81
91
|
"verify:reference-python": "node scripts/verify_reference_python.js",
|
|
@@ -92,7 +102,7 @@
|
|
|
92
102
|
"verify:service": "node scripts/verify_service.js",
|
|
93
103
|
"verify:forgery-resistance": "node scripts/verify_forgery_resistance.js",
|
|
94
104
|
"verify:release-candidate": "node scripts/verify_release_candidate.js",
|
|
95
|
-
"verify:all": "node scripts/verify_all.js && node scripts/verify_external_proof_import_gate.js && node scripts/verify_integrations.js && node scripts/verify_tooling.js && node scripts/verify_vectors.js && node scripts/verify_reference_python.js && node scripts/verify_reference_promotion_gate.js && node scripts/verify_reference_rust_scaffold.js && node scripts/verify_native_hybrid_design_gate.js && node scripts/verify_verification_services.js && node scripts/verify_trust_portability.js && node scripts/verify_control_plane_contracts.js && node scripts/verify_control_plane_routes.js && node scripts/verify_examples.js && node scripts/verify_service.js && node scripts/verify_forgery_resistance.js",
|
|
105
|
+
"verify:all": "node scripts/verify_all.js && node scripts/verify_external_proof_import_gate.js && node scripts/verify_integrations.js && node scripts/verify_tooling.js && node scripts/verify_vectors.js && node scripts/verify_reference_python.js && node scripts/verify_reference_promotion_gate.js && node scripts/verify_reference_rust_scaffold.js && node scripts/verify_native_hybrid_design_gate.js && node scripts/verify_verification_services.js && node scripts/verify_trust_portability.js && node scripts/verify_control_plane_contracts.js && node scripts/verify_control_plane_routes.js && node scripts/verify_examples.js && node scripts/verify_service.js && node scripts/verify_forgery_resistance.js && node scripts/verify_external_proof_signature.js && node scripts/verify_paid_execute.js && node scripts/verify_paywall_flag.js",
|
|
96
106
|
"prepublishOnly": "npm run verify:release-candidate"
|
|
97
107
|
}
|
|
98
108
|
}
|