zklicensing 0.1.0-beta.2 → 0.1.0-beta.4
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 +335 -97
- package/build/appsLookup.d.ts +14 -0
- package/build/appsLookup.d.ts.map +1 -0
- package/build/appsLookup.js +12 -0
- package/build/appsLookup.js.map +1 -0
- package/build/archiveBootstrap.d.ts +15 -1
- package/build/archiveBootstrap.d.ts.map +1 -0
- package/build/archiveBootstrap.js +62 -9
- package/build/archiveBootstrap.js.map +1 -0
- package/build/bindClient.d.ts +51 -0
- package/build/bindClient.d.ts.map +1 -0
- package/build/bindClient.js +115 -0
- package/build/bindClient.js.map +1 -0
- package/build/buyClient.d.ts +10 -3
- package/build/buyClient.d.ts.map +1 -0
- package/build/buyClient.js +33 -15
- package/build/buyClient.js.map +1 -0
- package/build/contractInterface.d.ts +11 -5
- package/build/contractInterface.d.ts.map +1 -0
- package/build/contractInterface.js +82 -17
- package/build/contractInterface.js.map +1 -0
- package/build/countryStats.d.ts +6 -1
- package/build/countryStats.d.ts.map +1 -0
- package/build/countryStats.js +33 -9
- package/build/countryStats.js.map +1 -0
- package/build/deployClient.d.ts.map +1 -0
- package/build/deployClient.js +1 -1
- package/build/deployClient.js.map +1 -0
- package/build/deviceIdentity.d.ts +68 -0
- package/build/deviceIdentity.d.ts.map +1 -0
- package/build/deviceIdentity.js +209 -0
- package/build/deviceIdentity.js.map +1 -0
- package/build/freezeClient.d.ts.map +1 -0
- package/build/freezeClient.js +1 -1
- package/build/freezeClient.js.map +1 -0
- package/build/generationClient.d.ts +1 -0
- package/build/generationClient.d.ts.map +1 -0
- package/build/generationClient.js +2 -2
- package/build/generationClient.js.map +1 -0
- package/build/index.d.ts +27 -37
- package/build/index.d.ts.map +1 -0
- package/build/index.js +85 -116
- package/build/index.js.map +1 -0
- package/build/licenseLeaf.d.ts +76 -0
- package/build/licenseLeaf.d.ts.map +1 -0
- package/build/licenseLeaf.js +189 -0
- package/build/licenseLeaf.js.map +1 -0
- package/build/licenseRecord.d.ts +20 -1
- package/build/licenseRecord.d.ts.map +1 -0
- package/build/licenseRecord.js +1 -1
- package/build/licenseRecord.js.map +1 -0
- package/build/licenseStore.d.ts +17 -2
- package/build/licenseStore.d.ts.map +1 -0
- package/build/licenseStore.js +167 -7
- package/build/licenseStore.js.map +1 -0
- package/build/manifestVerify.d.ts.map +1 -0
- package/build/manifestVerify.js +8 -3
- package/build/manifestVerify.js.map +1 -0
- package/build/migrateClient.d.ts +6 -21
- package/build/migrateClient.d.ts.map +1 -0
- package/build/migrateClient.js +30 -17
- package/build/migrateClient.js.map +1 -0
- package/build/onChainRoot.d.ts +67 -0
- package/build/onChainRoot.d.ts.map +1 -0
- package/build/onChainRoot.js +87 -0
- package/build/onChainRoot.js.map +1 -0
- package/build/ownershipLicenseHash.d.ts +25 -0
- package/build/ownershipLicenseHash.d.ts.map +1 -0
- package/build/ownershipLicenseHash.js +29 -0
- package/build/ownershipLicenseHash.js.map +1 -0
- package/build/ownershipSignature.d.ts +122 -0
- package/build/ownershipSignature.d.ts.map +1 -0
- package/build/ownershipSignature.js +244 -0
- package/build/ownershipSignature.js.map +1 -0
- package/build/proveErrors.d.ts +35 -0
- package/build/proveErrors.d.ts.map +1 -0
- package/build/proveErrors.js +49 -0
- package/build/proveErrors.js.map +1 -0
- package/build/refundClient.d.ts +2 -11
- package/build/refundClient.d.ts.map +1 -0
- package/build/refundClient.js +35 -17
- package/build/refundClient.js.map +1 -0
- package/build/renewClient.d.ts +4 -1
- package/build/renewClient.d.ts.map +1 -0
- package/build/renewClient.js +11 -4
- package/build/renewClient.js.map +1 -0
- package/build/seatName.d.ts +8 -0
- package/build/seatName.d.ts.map +1 -0
- package/build/seatName.js +136 -0
- package/build/seatName.js.map +1 -0
- package/build/statsClient.d.ts +47 -4
- package/build/statsClient.d.ts.map +1 -0
- package/build/statsClient.js +44 -5
- package/build/statsClient.js.map +1 -0
- package/build/trustAnchorVerify.d.ts +48 -0
- package/build/trustAnchorVerify.d.ts.map +1 -0
- package/build/trustAnchorVerify.js +431 -0
- package/build/trustAnchorVerify.js.map +1 -0
- package/build/trustAnchorVerifyCli.d.ts +35 -0
- package/build/trustAnchorVerifyCli.d.ts.map +1 -0
- package/build/trustAnchorVerifyCli.js +177 -0
- package/build/trustAnchorVerifyCli.js.map +1 -0
- package/build/txBroadcastClient.d.ts +26 -0
- package/build/txBroadcastClient.d.ts.map +1 -0
- package/build/txBroadcastClient.js +20 -0
- package/build/txBroadcastClient.js.map +1 -0
- package/build/unbindClient.d.ts +56 -0
- package/build/unbindClient.d.ts.map +1 -0
- package/build/unbindClient.js +113 -0
- package/build/unbindClient.js.map +1 -0
- package/build/vendorAccountClient.d.ts +56 -0
- package/build/vendorAccountClient.d.ts.map +1 -0
- package/build/vendorAccountClient.js +47 -0
- package/build/vendorAccountClient.js.map +1 -0
- package/build/verifyCore.d.ts +1 -1
- package/build/verifyCore.d.ts.map +1 -0
- package/build/verifyCore.js +11 -4
- package/build/verifyCore.js.map +1 -0
- package/build/verifyOffline.d.ts +85 -0
- package/build/verifyOffline.d.ts.map +1 -0
- package/build/verifyOffline.js +139 -0
- package/build/verifyOffline.js.map +1 -0
- package/build/verifyService.d.ts.map +1 -0
- package/build/verifyService.js +582 -455
- package/build/verifyService.js.map +1 -0
- package/build/verifyWithAncestors.d.ts +18 -0
- package/build/verifyWithAncestors.d.ts.map +1 -0
- package/build/verifyWithAncestors.js +119 -0
- package/build/verifyWithAncestors.js.map +1 -0
- package/build/zipToState.d.ts +2 -0
- package/build/zipToState.d.ts.map +1 -0
- package/build/zipToState.js +94 -0
- package/build/zipToState.js.map +1 -0
- package/package.json +57 -13
- package/src/appsLookup.ts +48 -0
- package/src/archiveBootstrap.ts +342 -0
- package/src/bindClient.ts +175 -0
- package/src/buyClient.ts +304 -0
- package/src/contractInterface.d.ts +61 -0
- package/src/contractInterface.ts +313 -0
- package/src/countryStats.ts +171 -0
- package/src/deployClient.ts +388 -0
- package/src/deviceIdentity.ts +249 -0
- package/src/freezeClient.ts +117 -0
- package/src/generationClient.ts +165 -0
- package/src/index.ts +329 -0
- package/src/licenseLeaf.ts +221 -0
- package/src/licenseRecord.ts +108 -0
- package/src/licenseStore.ts +538 -0
- package/src/manifestVerify.ts +111 -0
- package/src/migrateClient.ts +84 -0
- package/src/onChainRoot.ts +107 -0
- package/src/ownershipLicenseHash.ts +31 -0
- package/src/ownershipSignature.ts +354 -0
- package/src/proveErrors.ts +70 -0
- package/src/refundClient.ts +158 -0
- package/src/renewClient.ts +214 -0
- package/src/seatName.ts +165 -0
- package/src/statsClient.ts +235 -0
- package/src/trustAnchorVerify.ts +548 -0
- package/src/trustAnchorVerifyCli.ts +179 -0
- package/src/txBroadcastClient.ts +48 -0
- package/src/unbindClient.ts +149 -0
- package/src/vendorAccountClient.ts +110 -0
- package/src/verifyCore.ts +92 -0
- package/src/verifyOffline.ts +212 -0
- package/src/verifyService.ts +969 -0
- package/src/verifyWithAncestors.ts +153 -0
- package/src/zipToState.ts +94 -0
- package/build/licenseProof.d.ts +0 -26
- package/build/licenseProof.js +0 -41
- package/build/ownership.d.ts +0 -34
- package/build/ownership.js +0 -147
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export type Finding = {
|
|
2
|
+
/** Machine-readable check identifier, stable across releases. */
|
|
3
|
+
name: string;
|
|
4
|
+
/** True iff the check passed. */
|
|
5
|
+
ok: boolean;
|
|
6
|
+
/** Human-readable one-line summary or reason. */
|
|
7
|
+
detail: string;
|
|
8
|
+
};
|
|
9
|
+
export type TrustAnchorReport = {
|
|
10
|
+
/** True iff every finding is ok. */
|
|
11
|
+
ok: boolean;
|
|
12
|
+
origin: string;
|
|
13
|
+
/** Address that was checked. Echoed from opts.address. */
|
|
14
|
+
address: string;
|
|
15
|
+
/** appId as declared in the signed manifest payload. Undefined if the fetch/signature failed. */
|
|
16
|
+
appId?: string;
|
|
17
|
+
/** Generation index the address maps to in the signed manifest (1-based). */
|
|
18
|
+
generation?: number;
|
|
19
|
+
findings: Finding[];
|
|
20
|
+
};
|
|
21
|
+
export interface VerifyTrustAnchorOpts {
|
|
22
|
+
/** Vendor origin, e.g. `https://store.example.com`. HTTPS required. */
|
|
23
|
+
origin: string;
|
|
24
|
+
/** zkApp address (base58 PublicKey) — the manifest lives at `/.well-known/zklicensing/<address>.json`. */
|
|
25
|
+
address: string;
|
|
26
|
+
/** Platform manifest Ed25519 public keys (base64). Comma-list from `VITE_MANIFEST_PUBKEYS`. */
|
|
27
|
+
pinnedPublicKeysBase64: readonly string[];
|
|
28
|
+
/** Mina GraphQL endpoint for on-chain reads. Ignored when `skipChainChecks` is true. */
|
|
29
|
+
minaGraphqlUrl?: string;
|
|
30
|
+
/** Optional Mina networkId — 'mainnet' or 'testnet'. Defaults to 'mainnet'. */
|
|
31
|
+
minaNetworkId?: 'mainnet' | 'testnet' | 'devnet';
|
|
32
|
+
/** Fetch timeout in ms for the manifest fetch. Default 15000. */
|
|
33
|
+
fetchTimeoutMs?: number;
|
|
34
|
+
/** When true, skips all `chain_*` checks. Useful for manifest-only audits. */
|
|
35
|
+
skipChainChecks?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* When true, runs an extra `manifest_matches_backend` finding: fetch the
|
|
38
|
+
* same signed payload from `https://zklicensing.com/apps/by-address/{address}`,
|
|
39
|
+
* verify it against the same pinned keys, then byte-compare canonicalized
|
|
40
|
+
* payloads (minus `signature`, `publicKey`, `issuedAt`, `app`). Catches a
|
|
41
|
+
* vendor serving a stale/rolled-back manifest even when its own signature
|
|
42
|
+
* is still valid. Not on by default — adds a second network fetch and
|
|
43
|
+
* couples the verifier to zklicensing.com being reachable.
|
|
44
|
+
*/
|
|
45
|
+
crossCheck?: boolean;
|
|
46
|
+
}
|
|
47
|
+
export declare function verifyTrustAnchor(opts: VerifyTrustAnchorOpts): Promise<TrustAnchorReport>;
|
|
48
|
+
//# sourceMappingURL=trustAnchorVerify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trustAnchorVerify.d.ts","sourceRoot":"","sources":["../src/trustAnchorVerify.ts"],"names":[],"mappings":"AAyDA,MAAM,MAAM,OAAO,GAAG;IACpB,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,oCAAoC;IACpC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,iGAAiG;IACjG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAC;IACf,0GAA0G;IAC1G,OAAO,EAAE,MAAM,CAAC;IAChB,+FAA+F;IAC/F,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,wFAAwF;IACxF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACjD,iEAAiE;IACjE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA8PD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA6L/F"}
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
// Copyright (c) 2025-2026 zkLicensing project developers
|
|
2
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
3
|
+
/**
|
|
4
|
+
* trustAnchorVerify.ts
|
|
5
|
+
*
|
|
6
|
+
* End-to-end trust-anchor verification for a single zkLicensing app.
|
|
7
|
+
*
|
|
8
|
+
* Given a vendor origin + a zkApp address + one or more pinned platform
|
|
9
|
+
* manifest public keys, this module performs the full "does this vendor
|
|
10
|
+
* page point at a real zkLicensing deployment for this vendor?" pipeline
|
|
11
|
+
* that the trust-anchor page walks a human buyer through — mechanically,
|
|
12
|
+
* with structured findings suitable for CI, monitoring, or a
|
|
13
|
+
* wallet/extension consumer.
|
|
14
|
+
*
|
|
15
|
+
* The verifier is address-keyed: buyers see zkApp addresses in their
|
|
16
|
+
* wallet popup, not opaque platform appIds, so the primary lookup is by
|
|
17
|
+
* address. The signed manifest served at
|
|
18
|
+
* `<origin>/.well-known/zklicensing/<zkAppAddress>.json` carries the
|
|
19
|
+
* appId inside its signed payload, so callers never need to know the
|
|
20
|
+
* appId out-of-band.
|
|
21
|
+
*
|
|
22
|
+
* Pipeline (each step yields a discrete Finding — no boolean collapse):
|
|
23
|
+
*
|
|
24
|
+
* 1. manifest_fetch — GET https://<origin>/.well-known/zklicensing/<address>.json
|
|
25
|
+
* 2. manifest_signature — Ed25519 verify against caller-provided pinned keys
|
|
26
|
+
* 3. manifest_address_in_generations — opts.address appears in the signed generations[]
|
|
27
|
+
* 3b. manifest_matches_backend — (opt-in, opts.crossCheck) vendor payload equals
|
|
28
|
+
* zklicensing.com/apps/by-address/<address> after
|
|
29
|
+
* independent signature-verify against same pins
|
|
30
|
+
* 4. chain_account_exists — fetchAccount succeeds at the address
|
|
31
|
+
* 5. chain_zkapp_uri_match — on-chain zkappUri equals opts.origin
|
|
32
|
+
* 6. chain_vk_hash_pinned — on-chain verification-key hash equals CANONICAL_VK_HASHES[generation]
|
|
33
|
+
* 7. chain_set_zkapp_uri_impossible — permissions.setZkappUri === Permissions.impossible()
|
|
34
|
+
* 8. chain_set_permissions_impossible — permissions.setPermissions === Permissions.impossible() (meta-freeze)
|
|
35
|
+
* 9. chain_set_verification_key_locked — permissions.setVerificationKey.auth === Permissions.impossible()
|
|
36
|
+
* 10. chain_send_proof_only — permissions.send === Permissions.proof()
|
|
37
|
+
* 11. chain_edit_state_proof_only — permissions.editState === Permissions.proof()
|
|
38
|
+
*
|
|
39
|
+
* Steps 5 + 7 close the URI-binding loop: (5) proves the contract claims
|
|
40
|
+
* this origin, (7) proves nobody can rewrite that claim. Steps 8–11 verify
|
|
41
|
+
* the rest of LicensingApp.init()'s permission matrix — catching the case
|
|
42
|
+
* where a deployer used the correct VK but skipped/altered init(), leaving
|
|
43
|
+
* default `signature()` permissions that would still let the deploy key
|
|
44
|
+
* drain escrow, rewrite state, or swap the circuit.
|
|
45
|
+
*
|
|
46
|
+
* o1js is a peer dependency — this file imports it dynamically so callers
|
|
47
|
+
* that only want the manifest checks (no chain reads) can construct one
|
|
48
|
+
* with `skipChainChecks: true` and avoid the o1js install.
|
|
49
|
+
*
|
|
50
|
+
* The pinned pubkey list is caller-supplied — the SDK ships NO baked-in
|
|
51
|
+
* pin. Source it from https://zklicensing.com/trustanchor.html (published
|
|
52
|
+
* next to each generation's VK hash). See the SDK README for details.
|
|
53
|
+
*/
|
|
54
|
+
import { verifyManifestSignature, canonicalize } from './manifestVerify.js';
|
|
55
|
+
// Production keeper is mounted under /api/keeper on zklicensing.com — the
|
|
56
|
+
// bare /apps/... paths return 404 (they're not the app route, they're an
|
|
57
|
+
// unrelated marketing route). This is the concrete URL prefix, not just an
|
|
58
|
+
// origin.
|
|
59
|
+
const BACKEND_URL_PREFIX = 'https://zklicensing.com/api/keeper';
|
|
60
|
+
const DEFAULT_FETCH_TIMEOUT_MS = 15000;
|
|
61
|
+
function normalizeOrigin(origin) {
|
|
62
|
+
return origin.replace(/\/+$/, '');
|
|
63
|
+
}
|
|
64
|
+
// Strip trailing slash / path from a URL so we can compare against zkappUri,
|
|
65
|
+
// which vendors typically set to their bare origin.
|
|
66
|
+
function urlOrigin(url) {
|
|
67
|
+
try {
|
|
68
|
+
const u = new URL(url);
|
|
69
|
+
return `${u.protocol}//${u.host}`;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function fetchManifest(origin, address, timeoutMs) {
|
|
76
|
+
const originOk = origin.startsWith('https://');
|
|
77
|
+
if (!originOk) {
|
|
78
|
+
return { name: 'manifest_fetch', ok: false, detail: 'origin must be https://' };
|
|
79
|
+
}
|
|
80
|
+
let manifestUrl;
|
|
81
|
+
try {
|
|
82
|
+
manifestUrl = new URL(`/.well-known/zklicensing/${encodeURIComponent(address)}.json`, origin).href;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return { name: 'manifest_fetch', ok: false, detail: 'origin is not a valid URL' };
|
|
86
|
+
}
|
|
87
|
+
const controller = new AbortController();
|
|
88
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
89
|
+
try {
|
|
90
|
+
const resp = await fetch(manifestUrl, { signal: controller.signal, redirect: 'follow' });
|
|
91
|
+
if (!resp.ok) {
|
|
92
|
+
return { name: 'manifest_fetch', ok: false, detail: `HTTP ${resp.status} from ${manifestUrl}` };
|
|
93
|
+
}
|
|
94
|
+
const text = await resp.text();
|
|
95
|
+
let parsed;
|
|
96
|
+
try {
|
|
97
|
+
parsed = JSON.parse(text);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return { name: 'manifest_fetch', ok: false, detail: 'response is not valid JSON' };
|
|
101
|
+
}
|
|
102
|
+
return { name: 'manifest_fetch', ok: true, detail: `fetched ${manifestUrl}`, body: parsed };
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
return { name: 'manifest_fetch', ok: false, detail: `fetch failed: ${err?.message ?? String(err)}` };
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
clearTimeout(timer);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Split a raw manifest JSON into { signature, payload }. The keeper writes the
|
|
112
|
+
// payload fields at the top level plus { signature, publicKey } — we ignore
|
|
113
|
+
// publicKey (never trust the payload's self-declared key; only the
|
|
114
|
+
// caller-pinned list is authoritative). The same signed bytes are served at
|
|
115
|
+
// every /.well-known/zklicensing/<address>.json — one file per generation
|
|
116
|
+
// address, all carrying the same appId in the payload.
|
|
117
|
+
function splitManifest(raw) {
|
|
118
|
+
if (!raw || typeof raw !== 'object')
|
|
119
|
+
return { signature: null, payload: null };
|
|
120
|
+
const r = raw;
|
|
121
|
+
const signature = typeof r.signature === 'string' ? r.signature : null;
|
|
122
|
+
const { signature: _s, publicKey: _p, ...rest } = r;
|
|
123
|
+
const payload = rest;
|
|
124
|
+
if (typeof payload.appId !== 'string' ||
|
|
125
|
+
typeof payload.current !== 'number' ||
|
|
126
|
+
!Array.isArray(payload.generations) ||
|
|
127
|
+
typeof payload.issuedAt !== 'string') {
|
|
128
|
+
return { signature, payload: null };
|
|
129
|
+
}
|
|
130
|
+
return { signature, payload };
|
|
131
|
+
}
|
|
132
|
+
// Optional cross-check against the zkLicensing backend's own copy of the
|
|
133
|
+
// signed generation list. Fetches `https://zklicensing.com/apps/by-address/
|
|
134
|
+
// {address}`, verifies its signature against the same caller-pinned keys (so
|
|
135
|
+
// a compromised backend URL cannot lie), strips signature/publicKey/issuedAt/
|
|
136
|
+
// app, and byte-compares canonicalized payloads against the vendor's
|
|
137
|
+
// `.well-known` copy. `issuedAt` is stripped because the backend re-stamps on
|
|
138
|
+
// every call; `app` is stripped because it is an unsigned envelope field the
|
|
139
|
+
// by-address endpoint tacks on.
|
|
140
|
+
async function checkBackendMatch(args) {
|
|
141
|
+
const name = 'manifest_matches_backend';
|
|
142
|
+
const url = `${BACKEND_URL_PREFIX}/apps/by-address/${encodeURIComponent(args.address)}`;
|
|
143
|
+
const controller = new AbortController();
|
|
144
|
+
const timer = setTimeout(() => controller.abort(), args.timeoutMs);
|
|
145
|
+
let body;
|
|
146
|
+
try {
|
|
147
|
+
const resp = await fetch(url, { signal: controller.signal, redirect: 'follow' });
|
|
148
|
+
if (!resp.ok)
|
|
149
|
+
return { name, ok: false, detail: `backend HTTP ${resp.status} from ${url}` };
|
|
150
|
+
body = await resp.json();
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
return { name, ok: false, detail: `backend fetch failed: ${err?.message ?? String(err)}` };
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
clearTimeout(timer);
|
|
157
|
+
}
|
|
158
|
+
if (!body || typeof body !== 'object') {
|
|
159
|
+
return { name, ok: false, detail: 'backend response is not a JSON object' };
|
|
160
|
+
}
|
|
161
|
+
const { signature, publicKey: _pub, app: _app, ...backendPayload } = body;
|
|
162
|
+
if (typeof signature !== 'string') {
|
|
163
|
+
return { name, ok: false, detail: 'backend response missing signature' };
|
|
164
|
+
}
|
|
165
|
+
const kSigOk = await verifyManifestSignature(backendPayload, signature, args.pinnedPublicKeysBase64);
|
|
166
|
+
if (!kSigOk) {
|
|
167
|
+
return { name, ok: false, detail: 'backend response signature does not verify against pinned keys' };
|
|
168
|
+
}
|
|
169
|
+
const { issuedAt: _kIA, ...kRest } = backendPayload;
|
|
170
|
+
const { issuedAt: _vIA, ...vRest } = args.vendorPayload;
|
|
171
|
+
if (canonicalize(kRest) !== canonicalize(vRest)) {
|
|
172
|
+
return { name, ok: false, detail: 'vendor manifest content diverges from backend record (stale or drifted)' };
|
|
173
|
+
}
|
|
174
|
+
return { name, ok: true, detail: `vendor payload matches backend /apps/by-address/${args.address}` };
|
|
175
|
+
}
|
|
176
|
+
// Converts an o1js-decoded Permission (three booleans) back to its canonical
|
|
177
|
+
// enum string. Mirrors the switch inside o1js's own AuthRequired.toJSON — kept
|
|
178
|
+
// inline because o1js doesn't publicly export it.
|
|
179
|
+
function permToString(p) {
|
|
180
|
+
const b = (v) => (typeof v?.toBoolean === 'function' ? v.toBoolean() : Boolean(v)) ? 1 : 0;
|
|
181
|
+
const key = `${b(p?.constant)}${b(p?.signatureNecessary)}${b(p?.signatureSufficient)}`;
|
|
182
|
+
switch (key) {
|
|
183
|
+
case '110': return 'Impossible';
|
|
184
|
+
case '101': return 'None';
|
|
185
|
+
case '000': return 'Proof';
|
|
186
|
+
case '011': return 'Signature';
|
|
187
|
+
case '001': return 'Either';
|
|
188
|
+
default: return undefined;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Reads the on-chain facts needed to close the trust loop for a single
|
|
192
|
+
// zkApp address. o1js is imported dynamically so this file can be pulled in
|
|
193
|
+
// by callers that don't need chain reads (e.g. an offline manifest audit).
|
|
194
|
+
async function readChainState(address, minaGraphqlUrl, minaNetworkId) {
|
|
195
|
+
let o1js;
|
|
196
|
+
try {
|
|
197
|
+
o1js = await import('o1js');
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
return {
|
|
201
|
+
accountFound: false,
|
|
202
|
+
fetchError: `o1js not installed — chain checks require o1js as a peer dep (${err?.message ?? err})`,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
// setActiveInstance mutates o1js global state. This is acceptable for a
|
|
207
|
+
// one-shot CLI; long-lived hosts should confine the call to their own
|
|
208
|
+
// network singleton and not use this helper.
|
|
209
|
+
const network = o1js.Mina.Network({
|
|
210
|
+
networkId: minaNetworkId === 'mainnet' ? 'mainnet' : 'testnet',
|
|
211
|
+
mina: minaGraphqlUrl,
|
|
212
|
+
});
|
|
213
|
+
o1js.Mina.setActiveInstance(network);
|
|
214
|
+
const publicKey = o1js.PublicKey.fromBase58(address);
|
|
215
|
+
const { account, error } = await o1js.fetchAccount({ publicKey });
|
|
216
|
+
if (!account) {
|
|
217
|
+
const detail = error
|
|
218
|
+
? `${error.statusCode ?? ''} ${error.statusText ?? ''} ${error.errors ? JSON.stringify(error.errors) : ''}`.trim() || JSON.stringify(error)
|
|
219
|
+
: 'no account and no error returned';
|
|
220
|
+
return { accountFound: false, fetchError: `fetchAccount(${address}) via ${minaGraphqlUrl}: ${detail}` };
|
|
221
|
+
}
|
|
222
|
+
const zkappUri = account.zkapp?.zkappUri;
|
|
223
|
+
const vkHash = account.zkapp?.verificationKey?.hash?.toString?.();
|
|
224
|
+
const perms = account.permissions;
|
|
225
|
+
const setVkAuth = permToString(perms?.setVerificationKey?.auth);
|
|
226
|
+
const rawTxnVersion = perms?.setVerificationKey?.txnVersion;
|
|
227
|
+
const setVkTxnVersion = rawTxnVersion?.toString ? Number(rawTxnVersion.toString()) : undefined;
|
|
228
|
+
return {
|
|
229
|
+
accountFound: true,
|
|
230
|
+
zkappUri,
|
|
231
|
+
vkHash,
|
|
232
|
+
setZkappUriIsImpossible: permToString(perms?.setZkappUri) === 'Impossible',
|
|
233
|
+
setPermissionsIsImpossible: permToString(perms?.setPermissions) === 'Impossible',
|
|
234
|
+
setVerificationKeyAuth: setVkAuth,
|
|
235
|
+
setVerificationKeyTxnVersion: Number.isFinite(setVkTxnVersion) ? setVkTxnVersion : undefined,
|
|
236
|
+
sendIsProof: permToString(perms?.send) === 'Proof',
|
|
237
|
+
editStateIsProof: permToString(perms?.editState) === 'Proof',
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
return { accountFound: false, fetchError: err?.message ?? String(err) };
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
async function loadCanonicalVkHashes() {
|
|
245
|
+
try {
|
|
246
|
+
const m = await import('./contractInterface.js');
|
|
247
|
+
return m.CANONICAL_VK_HASHES ?? null;
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
export async function verifyTrustAnchor(opts) {
|
|
254
|
+
const origin = normalizeOrigin(opts.origin);
|
|
255
|
+
const address = opts.address;
|
|
256
|
+
const findings = [];
|
|
257
|
+
const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;
|
|
258
|
+
// 1. manifest_fetch
|
|
259
|
+
const fetchResult = await fetchManifest(origin, address, timeoutMs);
|
|
260
|
+
findings.push({ name: fetchResult.name, ok: fetchResult.ok, detail: fetchResult.detail });
|
|
261
|
+
if (!fetchResult.ok) {
|
|
262
|
+
return { ok: false, origin, address, findings };
|
|
263
|
+
}
|
|
264
|
+
const { signature, payload } = splitManifest(fetchResult.body);
|
|
265
|
+
// 2. manifest_signature
|
|
266
|
+
if (!signature || !payload) {
|
|
267
|
+
findings.push({ name: 'manifest_signature', ok: false, detail: 'manifest missing signature or payload fields' });
|
|
268
|
+
return { ok: false, origin, address, findings };
|
|
269
|
+
}
|
|
270
|
+
const sigOk = await verifyManifestSignature(payload, signature, opts.pinnedPublicKeysBase64);
|
|
271
|
+
findings.push({
|
|
272
|
+
name: 'manifest_signature',
|
|
273
|
+
ok: sigOk,
|
|
274
|
+
detail: sigOk
|
|
275
|
+
? `Ed25519 verified against pinned key (1 of ${opts.pinnedPublicKeysBase64.length})`
|
|
276
|
+
: 'signature does not verify against any pinned key',
|
|
277
|
+
});
|
|
278
|
+
if (!sigOk) {
|
|
279
|
+
return { ok: false, origin, address, findings };
|
|
280
|
+
}
|
|
281
|
+
// appId is trusted only after signature verifies — it comes from the signed
|
|
282
|
+
// payload, not the caller.
|
|
283
|
+
const appId = payload.appId;
|
|
284
|
+
// 3. manifest_address_in_generations
|
|
285
|
+
const entry = payload.generations.find((g) => g.zkAppAddress === address);
|
|
286
|
+
findings.push({
|
|
287
|
+
name: 'manifest_address_in_generations',
|
|
288
|
+
ok: !!entry,
|
|
289
|
+
detail: entry
|
|
290
|
+
? `address maps to gen ${entry.gen} (${entry.status})`
|
|
291
|
+
: `address ${address} not in manifest generations for app "${appId}"`,
|
|
292
|
+
});
|
|
293
|
+
const generation = entry?.gen;
|
|
294
|
+
// 3b. manifest_matches_backend (opt-in)
|
|
295
|
+
if (opts.crossCheck) {
|
|
296
|
+
findings.push(await checkBackendMatch({
|
|
297
|
+
address,
|
|
298
|
+
vendorPayload: payload,
|
|
299
|
+
pinnedPublicKeysBase64: opts.pinnedPublicKeysBase64,
|
|
300
|
+
timeoutMs,
|
|
301
|
+
}));
|
|
302
|
+
}
|
|
303
|
+
if (opts.skipChainChecks) {
|
|
304
|
+
const allOk = findings.every((f) => f.ok);
|
|
305
|
+
return { ok: allOk, origin, appId, address, generation, findings };
|
|
306
|
+
}
|
|
307
|
+
if (!opts.minaGraphqlUrl) {
|
|
308
|
+
findings.push({ name: 'chain_account_exists', ok: false, detail: 'minaGraphqlUrl is required for chain checks' });
|
|
309
|
+
return { ok: false, origin, appId, address, generation, findings };
|
|
310
|
+
}
|
|
311
|
+
// 4-11: chain reads
|
|
312
|
+
const state = await readChainState(address, opts.minaGraphqlUrl, opts.minaNetworkId ?? 'mainnet');
|
|
313
|
+
findings.push({
|
|
314
|
+
name: 'chain_account_exists',
|
|
315
|
+
ok: state.accountFound,
|
|
316
|
+
detail: state.accountFound ? `account ${address.slice(0, 12)}… found` : (state.fetchError ?? 'account not found'),
|
|
317
|
+
});
|
|
318
|
+
if (!state.accountFound) {
|
|
319
|
+
return { ok: false, origin, appId, address, generation, findings };
|
|
320
|
+
}
|
|
321
|
+
const onChainOrigin = state.zkappUri ? urlOrigin(state.zkappUri) : null;
|
|
322
|
+
const originClean = urlOrigin(origin);
|
|
323
|
+
const uriOk = !!state.zkappUri && !!onChainOrigin && !!originClean && onChainOrigin === originClean;
|
|
324
|
+
findings.push({
|
|
325
|
+
name: 'chain_zkapp_uri_match',
|
|
326
|
+
ok: uriOk,
|
|
327
|
+
detail: state.zkappUri
|
|
328
|
+
? (uriOk ? `zkappUri "${state.zkappUri}" origin matches` : `zkappUri "${state.zkappUri}" origin ≠ "${originClean ?? origin}"`)
|
|
329
|
+
: 'zkappUri is empty on chain',
|
|
330
|
+
});
|
|
331
|
+
const canonicalVks = await loadCanonicalVkHashes();
|
|
332
|
+
const expectedVk = generation !== undefined ? canonicalVks?.[generation] : undefined;
|
|
333
|
+
const vkOk = !!state.vkHash && !!expectedVk && state.vkHash === expectedVk;
|
|
334
|
+
findings.push({
|
|
335
|
+
name: 'chain_vk_hash_pinned',
|
|
336
|
+
ok: vkOk,
|
|
337
|
+
detail: vkOk
|
|
338
|
+
? `gen ${generation} hash matches CANONICAL_VK_HASHES[${generation}]`
|
|
339
|
+
: !expectedVk
|
|
340
|
+
? `no CANONICAL_VK_HASHES entry for gen ${generation ?? '?'}`
|
|
341
|
+
: `on-chain vkHash "${state.vkHash?.slice(0, 16)}…" ≠ pinned "${expectedVk.slice(0, 16)}…"`,
|
|
342
|
+
});
|
|
343
|
+
findings.push({
|
|
344
|
+
name: 'chain_set_zkapp_uri_impossible',
|
|
345
|
+
ok: !!state.setZkappUriIsImpossible,
|
|
346
|
+
detail: state.setZkappUriIsImpossible
|
|
347
|
+
? 'permissions.setZkappUri = impossible (zkappUri is frozen)'
|
|
348
|
+
: 'permissions.setZkappUri ≠ impossible — vendor could rewrite the URI',
|
|
349
|
+
});
|
|
350
|
+
// The meta-freeze: without this, every other permission lock below is
|
|
351
|
+
// reversible with a single signature. Priority #1 among the extras.
|
|
352
|
+
findings.push({
|
|
353
|
+
name: 'chain_set_permissions_impossible',
|
|
354
|
+
ok: !!state.setPermissionsIsImpossible,
|
|
355
|
+
detail: state.setPermissionsIsImpossible
|
|
356
|
+
? 'permissions.setPermissions = impossible (permission matrix is meta-frozen)'
|
|
357
|
+
: 'permissions.setPermissions ≠ impossible — every other lock could be relaxed later',
|
|
358
|
+
});
|
|
359
|
+
// setVerificationKey lock, with hardfork-aware softening.
|
|
360
|
+
//
|
|
361
|
+
// The contract deploys with VerificationKey.impossibleDuringCurrentVersion(),
|
|
362
|
+
// which stores {auth: Impossible, txnVersion: <chain's txnVersion at deploy
|
|
363
|
+
// time>}. After a Mina hardfork the chain's current txnVersion advances
|
|
364
|
+
// past the stored value and the effective enforcement falls back to
|
|
365
|
+
// signature() — but the deploy key was discarded (LicensingApp.ts:546-547),
|
|
366
|
+
// so no one can sign the fallback update.
|
|
367
|
+
//
|
|
368
|
+
// The keeper records the deploy-time txnVersion in the signed manifest as
|
|
369
|
+
// deployTxnVersion. We accept two states as OK, provided the on-chain
|
|
370
|
+
// stored txnVersion still matches the manifest-recorded value (which proves
|
|
371
|
+
// no one has re-set the permission since deploy):
|
|
372
|
+
//
|
|
373
|
+
// - auth = Impossible → normal, pre-hardfork state
|
|
374
|
+
// - auth = Signature → post-hardfork fallback (see above)
|
|
375
|
+
//
|
|
376
|
+
// Any mismatch — different txnVersion, or auth is some other string, or
|
|
377
|
+
// deployTxnVersion missing from an old manifest — falls back to the strict
|
|
378
|
+
// rule (auth === 'Impossible').
|
|
379
|
+
const onChainAuth = state.setVerificationKeyAuth;
|
|
380
|
+
const onChainTxnVersion = state.setVerificationKeyTxnVersion;
|
|
381
|
+
const manifestDeployTxnVersion = entry?.deployTxnVersion;
|
|
382
|
+
let vkLockOk = false;
|
|
383
|
+
let vkLockDetail;
|
|
384
|
+
if (manifestDeployTxnVersion !== undefined && onChainTxnVersion !== undefined && onChainTxnVersion === manifestDeployTxnVersion) {
|
|
385
|
+
if (onChainAuth === 'Impossible') {
|
|
386
|
+
vkLockOk = true;
|
|
387
|
+
vkLockDetail = `permissions.setVerificationKey.auth = impossible (circuit cannot be swapped; txnVersion ${onChainTxnVersion} matches deploy)`;
|
|
388
|
+
}
|
|
389
|
+
else if (onChainAuth === 'Signature') {
|
|
390
|
+
vkLockOk = true;
|
|
391
|
+
vkLockDetail = `permissions.setVerificationKey.auth = signature (post-hardfork fallback; deploy key was destroyed at deploy time; txnVersion ${onChainTxnVersion} matches deploy)`;
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
vkLockDetail = `permissions.setVerificationKey.auth = "${onChainAuth ?? '?'}" — expected impossible or signature`;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
else if (manifestDeployTxnVersion === undefined) {
|
|
398
|
+
// Older manifest without deployTxnVersion — fall back to strict.
|
|
399
|
+
vkLockOk = onChainAuth === 'Impossible';
|
|
400
|
+
vkLockDetail = vkLockOk
|
|
401
|
+
? 'permissions.setVerificationKey.auth = impossible (circuit cannot be swapped; manifest omits deployTxnVersion — strict rule applied)'
|
|
402
|
+
: `permissions.setVerificationKey.auth = "${onChainAuth ?? '?'}" ≠ impossible — vendor could swap the circuit (manifest omits deployTxnVersion — strict rule applied)`;
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
vkLockDetail = `on-chain setVerificationKey.txnVersion (${onChainTxnVersion ?? 'unknown'}) ≠ manifest deployTxnVersion (${manifestDeployTxnVersion}) — permission may have been re-set since deploy`;
|
|
406
|
+
}
|
|
407
|
+
findings.push({
|
|
408
|
+
name: 'chain_set_verification_key_locked',
|
|
409
|
+
ok: vkLockOk,
|
|
410
|
+
detail: vkLockDetail,
|
|
411
|
+
});
|
|
412
|
+
// send + editState must be proof() (not signature()): withdrawals and Merkle
|
|
413
|
+
// root advances only happen via a valid LicensingApp proof.
|
|
414
|
+
findings.push({
|
|
415
|
+
name: 'chain_send_proof_only',
|
|
416
|
+
ok: !!state.sendIsProof,
|
|
417
|
+
detail: state.sendIsProof
|
|
418
|
+
? 'permissions.send = proof() (escrow only leaves via a refund proof)'
|
|
419
|
+
: 'permissions.send ≠ proof() — vendor could drain escrow with a signature',
|
|
420
|
+
});
|
|
421
|
+
findings.push({
|
|
422
|
+
name: 'chain_edit_state_proof_only',
|
|
423
|
+
ok: !!state.editStateIsProof,
|
|
424
|
+
detail: state.editStateIsProof
|
|
425
|
+
? 'permissions.editState = proof() (Merkle root advances only via a proof)'
|
|
426
|
+
: 'permissions.editState ≠ proof() — vendor could rewrite the license root',
|
|
427
|
+
});
|
|
428
|
+
const allOk = findings.every((f) => f.ok);
|
|
429
|
+
return { ok: allOk, origin, appId, address, generation, findings };
|
|
430
|
+
}
|
|
431
|
+
//# sourceMappingURL=trustAnchorVerify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trustAnchorVerify.js","sourceRoot":"","sources":["../src/trustAnchorVerify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* trustAnchorVerifyCli.ts
|
|
4
|
+
*
|
|
5
|
+
* Command-line front-end for verifyTrustAnchor(). Ships as the `zklicensing-verify-trust`
|
|
6
|
+
* bin — the sibling of `zklicensing-verify` (which is the verifyService HTTP daemon).
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* zklicensing-verify-trust \
|
|
10
|
+
* --origin https://store.example.com \
|
|
11
|
+
* --address B62q... \
|
|
12
|
+
* --pinned-key <base64-ed25519-pubkey> \
|
|
13
|
+
* [--mina-graphql https://api.minascan.io/node/mainnet/v1/graphql] \
|
|
14
|
+
* [--mina-network-id mainnet|testnet|devnet] \
|
|
15
|
+
* [--skip-chain-checks] \
|
|
16
|
+
* [--json]
|
|
17
|
+
*
|
|
18
|
+
* The manifest lives at `<origin>/.well-known/zklicensing/<address>.json` —
|
|
19
|
+
* one file per generation address, all signed by the same platform key. The
|
|
20
|
+
* appId is read out of the signed payload; callers never need to know it
|
|
21
|
+
* out-of-band, which lets buyers verify from just the address their wallet
|
|
22
|
+
* shows them (including addresses for retired generations).
|
|
23
|
+
*
|
|
24
|
+
* Exit codes:
|
|
25
|
+
* 0 — every finding passed
|
|
26
|
+
* 1 — one or more findings failed
|
|
27
|
+
* 2 — invalid arguments
|
|
28
|
+
*
|
|
29
|
+
* --pinned-key is required and may be repeated; the CLI ships NO baked-in
|
|
30
|
+
* pin. Source it from https://zklicensing.com/trustanchor.html (published
|
|
31
|
+
* next to each generation's VK hash). See the SDK README for details.
|
|
32
|
+
*/
|
|
33
|
+
import { type Finding } from './trustAnchorVerify.js';
|
|
34
|
+
export type { Finding };
|
|
35
|
+
//# sourceMappingURL=trustAnchorVerifyCli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trustAnchorVerifyCli.d.ts","sourceRoot":"","sources":["../src/trustAnchorVerifyCli.ts"],"names":[],"mappings":";AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAqB,KAAK,OAAO,EAA0B,MAAM,wBAAwB,CAAC;AA8IjG,YAAY,EAAE,OAAO,EAAE,CAAC"}
|