@x402jp/delivery-receipt-verify 0.0.0-stage → 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.
package/README.md CHANGED
@@ -1,3 +1,3 @@
1
- # Temporary Holding Version
1
+ # @x402jp/delivery-receipt-verify
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ x402 の Delivery Receipt(買い手側の検証と再取得。実行時の依存なし)。使い方・仕様は https://github.com/kato9292929/delivery-receipt を参照。
@@ -0,0 +1,148 @@
1
+ /**
2
+ * @x402jp/delivery-receipt-verify
3
+ *
4
+ * Buyer-side verifier for x402 Delivery Receipts.
5
+ *
6
+ * This file is intentionally self-contained: it depends only on `node:crypto`
7
+ * and the global `fetch`, so it can be vendor-copied into another repository
8
+ * as a single file. See docs/spec.md for the protocol.
9
+ */
10
+ import { type KeyObject } from "node:crypto";
11
+ export declare const RECEIPT_VERSION: 1;
12
+ /** Response header carrying the encoded receipt. */
13
+ export declare const RECEIPT_HEADER = "X-Delivery-Receipt";
14
+ /** Request header a buyer sets (with the payment_id) to ask for a refetch. */
15
+ export declare const REFETCH_HEADER = "X-Payment-Refetch";
16
+ /** Path of the seller's public key document. */
17
+ export declare const WELL_KNOWN_PATH = "/.well-known/x402-receipt.json";
18
+ /** Minimum refetch window a seller may advertise (24h). */
19
+ export declare const MIN_REFETCH_WINDOW_S = 86400;
20
+ /** Default refetch window / retention (7 days). */
21
+ export declare const DEFAULT_REFETCH_WINDOW_S = 604800;
22
+ export type Delivery = "first" | "refetch";
23
+ /** Every receipt field except `sig`; this is what gets signed. */
24
+ export interface ReceiptPayload {
25
+ v: 1;
26
+ /** Solana: transfer tx signature. EVM: EIP-3009 authorization nonce (0x + 64 hex). */
27
+ payment_id: string;
28
+ /** CAIP-2 network id, e.g. "eip155:8453" or "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp". */
29
+ network: string;
30
+ /** Absolute URL of the paid resource. */
31
+ resource: string;
32
+ /** Lowercase hex sha256 of the exact response body bytes. */
33
+ body_sha256: string;
34
+ /** Body length in bytes. */
35
+ content_length: number;
36
+ /** ISO 8601 UTC timestamp of when this receipt was signed. */
37
+ issued_at: string;
38
+ delivery: Delivery;
39
+ key_id: string;
40
+ }
41
+ export interface Receipt extends ReceiptPayload {
42
+ /** base64url (no padding) Ed25519 signature over canonicalJson(payload). */
43
+ sig: string;
44
+ }
45
+ export interface WellKnownKey {
46
+ key_id: string;
47
+ alg: "Ed25519";
48
+ /** base64url (no padding) of the raw 32-byte Ed25519 public key. */
49
+ public_key: string;
50
+ /** ISO 8601. Receipts are valid under this key only if issued_at < revoked_at. */
51
+ revoked_at?: string;
52
+ }
53
+ export interface WellKnown {
54
+ keys: WellKnownKey[];
55
+ refetch_window_s: number;
56
+ refetch_header: string;
57
+ }
58
+ export type VerifyFailureReason = "receipt_missing" | "receipt_bad_signature" | "receipt_hash_mismatch" | "receipt_key_unknown";
59
+ export type VerifyResult = {
60
+ ok: true;
61
+ receipt: Receipt;
62
+ } | {
63
+ ok: false;
64
+ reason: VerifyFailureReason;
65
+ detail?: string;
66
+ };
67
+ export type RefetchFailureReason = "refetch_expired" | "refetch_refused" | VerifyFailureReason;
68
+ export type RefetchResult = {
69
+ ok: true;
70
+ body: Uint8Array;
71
+ receipt: Receipt;
72
+ status: number;
73
+ } | {
74
+ ok: false;
75
+ reason: RefetchFailureReason;
76
+ status?: number;
77
+ detail?: string;
78
+ };
79
+ export type FetchLike = (input: string | URL, init?: RequestInit) => Promise<Response>;
80
+ export interface VerifyReceiptInput {
81
+ /** Raw value of the X-Delivery-Receipt header (null when absent). */
82
+ header: string | null | undefined;
83
+ /** Exact response body bytes as received. */
84
+ body: Uint8Array;
85
+ wellKnown: WellKnown;
86
+ /** Optional bindings the caller expects the receipt to carry. */
87
+ expect?: {
88
+ payment_id?: string;
89
+ resource?: string;
90
+ };
91
+ }
92
+ export interface RefetchInput {
93
+ url: string;
94
+ /**
95
+ * The ORIGINAL payment header(s) sent with the first request, e.g.
96
+ * `{ "PAYMENT-SIGNATURE": "<base64>" }` (x402 v2) or `{ "X-PAYMENT": "<base64>" }` (v1).
97
+ */
98
+ paymentHeaders: Record<string, string>;
99
+ paymentId: string;
100
+ /** Seller key document; fetched from `<origin>/.well-known/x402-receipt.json` when omitted. */
101
+ wellKnown?: WellKnown;
102
+ fetch?: FetchLike;
103
+ /** Extra request headers (e.g. Accept). */
104
+ headers?: Record<string, string>;
105
+ /** Additionally require receipt.resource to equal this value. */
106
+ expectResource?: string;
107
+ }
108
+ /** base64url without padding. */
109
+ export declare function base64urlEncode(bytes: Uint8Array): string;
110
+ /** Strict base64url decode (no padding, no '+' or '/'). Throws on invalid input. */
111
+ export declare function base64urlDecode(s: string): Uint8Array;
112
+ /** Lowercase hex sha256. */
113
+ export declare function sha256Hex(bytes: Uint8Array | string): string;
114
+ /**
115
+ * Canonical JSON: object keys sorted (recursively, by UTF-16 code unit order,
116
+ * which equals alphabetical order for ASCII keys), no whitespace. Array order is
117
+ * preserved; `undefined` object members are omitted as in JSON.stringify.
118
+ */
119
+ export declare function canonicalJson(value: unknown): string;
120
+ /** The exact bytes that are signed: UTF-8 canonical JSON of every field except `sig`. */
121
+ export declare function receiptSigningBytes(receipt: ReceiptPayload | Receipt): Uint8Array;
122
+ /** Encode a receipt as the X-Delivery-Receipt header value (base64url of its JSON). */
123
+ export declare function encodeReceipt(receipt: Receipt): string;
124
+ /** Decode and shape-check an X-Delivery-Receipt header value. Throws on malformed input. */
125
+ export declare function decodeReceipt(header: string): Receipt;
126
+ /** Import a base64url raw 32-byte Ed25519 public key. */
127
+ export declare function importEd25519PublicKey(publicKeyB64u: string): KeyObject;
128
+ /** Shape-check a parsed well-known document. Throws on malformed input. */
129
+ export declare function parseWellKnown(doc: unknown): WellKnown;
130
+ /** Fetch and validate `<origin>/.well-known/x402-receipt.json`. */
131
+ export declare function fetchWellKnown(origin: string, opts?: {
132
+ fetch?: FetchLike;
133
+ }): Promise<WellKnown>;
134
+ /**
135
+ * Verify a receipt against the exact body bytes and the seller's key document.
136
+ *
137
+ * Check order: presence -> key lookup -> signature -> revocation -> body hash -> expectations.
138
+ * An `expect` mismatch is reported as `receipt_bad_signature` (the receipt does not
139
+ * attest to what the caller asked for) with a `detail`.
140
+ */
141
+ export declare function verifyReceipt(input: VerifyReceiptInput): VerifyResult;
142
+ /**
143
+ * Re-fetch already-paid content by re-sending the original payment header plus
144
+ * `X-Payment-Refetch: <payment_id>`, then verify the returned receipt.
145
+ *
146
+ * 410 -> refetch_expired; any other non-200 (including 402) -> refetch_refused.
147
+ */
148
+ export declare function refetch(input: RefetchInput): Promise<RefetchResult>;
package/dist/index.js ADDED
@@ -0,0 +1,261 @@
1
+ /**
2
+ * @x402jp/delivery-receipt-verify
3
+ *
4
+ * Buyer-side verifier for x402 Delivery Receipts.
5
+ *
6
+ * This file is intentionally self-contained: it depends only on `node:crypto`
7
+ * and the global `fetch`, so it can be vendor-copied into another repository
8
+ * as a single file. See docs/spec.md for the protocol.
9
+ */
10
+ import { createHash, createPublicKey, verify as cryptoVerify } from "node:crypto";
11
+ // ---------------------------------------------------------------------------
12
+ // Constants
13
+ // ---------------------------------------------------------------------------
14
+ export const RECEIPT_VERSION = 1;
15
+ /** Response header carrying the encoded receipt. */
16
+ export const RECEIPT_HEADER = "X-Delivery-Receipt";
17
+ /** Request header a buyer sets (with the payment_id) to ask for a refetch. */
18
+ export const REFETCH_HEADER = "X-Payment-Refetch";
19
+ /** Path of the seller's public key document. */
20
+ export const WELL_KNOWN_PATH = "/.well-known/x402-receipt.json";
21
+ /** Minimum refetch window a seller may advertise (24h). */
22
+ export const MIN_REFETCH_WINDOW_S = 86_400;
23
+ /** Default refetch window / retention (7 days). */
24
+ export const DEFAULT_REFETCH_WINDOW_S = 604_800;
25
+ // ---------------------------------------------------------------------------
26
+ // Encoding helpers
27
+ // ---------------------------------------------------------------------------
28
+ const B64URL_RE = /^[A-Za-z0-9_-]*$/;
29
+ /** base64url without padding. */
30
+ export function base64urlEncode(bytes) {
31
+ return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString("base64url");
32
+ }
33
+ /** Strict base64url decode (no padding, no '+' or '/'). Throws on invalid input. */
34
+ export function base64urlDecode(s) {
35
+ if (!B64URL_RE.test(s) || s.length % 4 === 1)
36
+ throw new Error("invalid base64url");
37
+ return new Uint8Array(Buffer.from(s, "base64url"));
38
+ }
39
+ /** Lowercase hex sha256. */
40
+ export function sha256Hex(bytes) {
41
+ return createHash("sha256").update(bytes).digest("hex");
42
+ }
43
+ /**
44
+ * Canonical JSON: object keys sorted (recursively, by UTF-16 code unit order,
45
+ * which equals alphabetical order for ASCII keys), no whitespace. Array order is
46
+ * preserved; `undefined` object members are omitted as in JSON.stringify.
47
+ */
48
+ export function canonicalJson(value) {
49
+ if (value === null)
50
+ return "null";
51
+ switch (typeof value) {
52
+ case "string":
53
+ case "boolean":
54
+ return JSON.stringify(value);
55
+ case "number":
56
+ if (!Number.isFinite(value))
57
+ throw new Error("canonicalJson: non-finite number");
58
+ return JSON.stringify(value);
59
+ case "object": {
60
+ if (Array.isArray(value)) {
61
+ return "[" + value.map((v) => (v === undefined ? "null" : canonicalJson(v))).join(",") + "]";
62
+ }
63
+ const obj = value;
64
+ const keys = Object.keys(obj)
65
+ .filter((k) => obj[k] !== undefined)
66
+ .sort();
67
+ return "{" + keys.map((k) => JSON.stringify(k) + ":" + canonicalJson(obj[k])).join(",") + "}";
68
+ }
69
+ default:
70
+ throw new Error(`canonicalJson: unsupported type ${typeof value}`);
71
+ }
72
+ }
73
+ /** The exact bytes that are signed: UTF-8 canonical JSON of every field except `sig`. */
74
+ export function receiptSigningBytes(receipt) {
75
+ const { sig: _sig, ...payload } = receipt;
76
+ return new Uint8Array(Buffer.from(canonicalJson(payload), "utf8"));
77
+ }
78
+ /** Encode a receipt as the X-Delivery-Receipt header value (base64url of its JSON). */
79
+ export function encodeReceipt(receipt) {
80
+ return base64urlEncode(new Uint8Array(Buffer.from(canonicalJson(receipt), "utf8")));
81
+ }
82
+ const ISO_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/;
83
+ const HEX64_RE = /^[0-9a-f]{64}$/;
84
+ /** Decode and shape-check an X-Delivery-Receipt header value. Throws on malformed input. */
85
+ export function decodeReceipt(header) {
86
+ const json = Buffer.from(base64urlDecode(header.trim())).toString("utf8");
87
+ const r = JSON.parse(json);
88
+ if (typeof r !== "object" || r === null || Array.isArray(r))
89
+ throw new Error("receipt: not an object");
90
+ if (r.v !== 1)
91
+ throw new Error("receipt: unsupported version");
92
+ for (const k of ["payment_id", "network", "resource", "body_sha256", "issued_at", "key_id", "sig"]) {
93
+ if (typeof r[k] !== "string" || r[k].length === 0)
94
+ throw new Error(`receipt: bad ${k}`);
95
+ }
96
+ if (!HEX64_RE.test(r.body_sha256))
97
+ throw new Error("receipt: bad body_sha256");
98
+ if (!Number.isSafeInteger(r.content_length) || r.content_length < 0) {
99
+ throw new Error("receipt: bad content_length");
100
+ }
101
+ if (!ISO_RE.test(r.issued_at) || Number.isNaN(Date.parse(r.issued_at))) {
102
+ throw new Error("receipt: bad issued_at");
103
+ }
104
+ if (r.delivery !== "first" && r.delivery !== "refetch")
105
+ throw new Error("receipt: bad delivery");
106
+ return r;
107
+ }
108
+ /** Import a base64url raw 32-byte Ed25519 public key. */
109
+ export function importEd25519PublicKey(publicKeyB64u) {
110
+ const raw = base64urlDecode(publicKeyB64u);
111
+ if (raw.length !== 32)
112
+ throw new Error("Ed25519 public key must be 32 bytes");
113
+ return createPublicKey({ key: { kty: "OKP", crv: "Ed25519", x: publicKeyB64u }, format: "jwk" });
114
+ }
115
+ // ---------------------------------------------------------------------------
116
+ // Well-known document
117
+ // ---------------------------------------------------------------------------
118
+ /** Shape-check a parsed well-known document. Throws on malformed input. */
119
+ export function parseWellKnown(doc) {
120
+ const d = doc;
121
+ if (!d || typeof d !== "object" || !Array.isArray(d.keys))
122
+ throw new Error("well-known: missing keys");
123
+ for (const k of d.keys) {
124
+ if (!k || typeof k.key_id !== "string" || typeof k.public_key !== "string" || k.alg !== "Ed25519") {
125
+ throw new Error("well-known: bad key entry");
126
+ }
127
+ if (k.revoked_at !== undefined && Number.isNaN(Date.parse(k.revoked_at))) {
128
+ throw new Error("well-known: bad revoked_at");
129
+ }
130
+ }
131
+ if (typeof d.refetch_window_s !== "number" || d.refetch_window_s < MIN_REFETCH_WINDOW_S) {
132
+ throw new Error("well-known: refetch_window_s must be >= 86400");
133
+ }
134
+ if (typeof d.refetch_header !== "string")
135
+ throw new Error("well-known: missing refetch_header");
136
+ return d;
137
+ }
138
+ /** Fetch and validate `<origin>/.well-known/x402-receipt.json`. */
139
+ export async function fetchWellKnown(origin, opts = {}) {
140
+ const f = opts.fetch ?? globalThis.fetch;
141
+ const url = new URL(WELL_KNOWN_PATH, origin);
142
+ const res = await f(url, { headers: { accept: "application/json" } });
143
+ if (res.status !== 200)
144
+ throw new Error(`well-known: HTTP ${res.status}`);
145
+ return parseWellKnown(await res.json());
146
+ }
147
+ // ---------------------------------------------------------------------------
148
+ // Verification
149
+ // ---------------------------------------------------------------------------
150
+ /**
151
+ * Verify a receipt against the exact body bytes and the seller's key document.
152
+ *
153
+ * Check order: presence -> key lookup -> signature -> revocation -> body hash -> expectations.
154
+ * An `expect` mismatch is reported as `receipt_bad_signature` (the receipt does not
155
+ * attest to what the caller asked for) with a `detail`.
156
+ */
157
+ export function verifyReceipt(input) {
158
+ const { header, body, wellKnown, expect } = input;
159
+ if (header === null || header === undefined || header.trim() === "") {
160
+ return { ok: false, reason: "receipt_missing" };
161
+ }
162
+ let receipt;
163
+ try {
164
+ receipt = decodeReceipt(header);
165
+ }
166
+ catch (e) {
167
+ return { ok: false, reason: "receipt_bad_signature", detail: `malformed: ${e.message}` };
168
+ }
169
+ const key = wellKnown.keys.find((k) => k.key_id === receipt.key_id);
170
+ if (!key || key.alg !== "Ed25519")
171
+ return { ok: false, reason: "receipt_key_unknown", detail: "unknown key_id" };
172
+ let pub;
173
+ try {
174
+ pub = importEd25519PublicKey(key.public_key);
175
+ }
176
+ catch {
177
+ return { ok: false, reason: "receipt_key_unknown", detail: "unusable public key" };
178
+ }
179
+ let sigOk = false;
180
+ try {
181
+ const sig = base64urlDecode(receipt.sig);
182
+ sigOk = sig.length === 64 && cryptoVerify(null, receiptSigningBytes(receipt), pub, sig);
183
+ }
184
+ catch {
185
+ sigOk = false;
186
+ }
187
+ if (!sigOk)
188
+ return { ok: false, reason: "receipt_bad_signature" };
189
+ if (key.revoked_at !== undefined && !(Date.parse(receipt.issued_at) < Date.parse(key.revoked_at))) {
190
+ return { ok: false, reason: "receipt_key_unknown", detail: "issued at or after key revocation" };
191
+ }
192
+ if (receipt.content_length !== body.byteLength || sha256Hex(body) !== receipt.body_sha256) {
193
+ return { ok: false, reason: "receipt_hash_mismatch" };
194
+ }
195
+ if (expect?.payment_id !== undefined && !samePaymentId(expect.payment_id, receipt.payment_id)) {
196
+ return { ok: false, reason: "receipt_bad_signature", detail: "payment_id mismatch" };
197
+ }
198
+ if (expect?.resource !== undefined && expect.resource !== receipt.resource) {
199
+ return { ok: false, reason: "receipt_bad_signature", detail: "resource mismatch" };
200
+ }
201
+ return { ok: true, receipt };
202
+ }
203
+ /** EVM nonces are hex and compared case-insensitively; Solana signatures are case-sensitive base58. */
204
+ function samePaymentId(a, b) {
205
+ if (a.startsWith("0x") && b.startsWith("0x"))
206
+ return a.toLowerCase() === b.toLowerCase();
207
+ return a === b;
208
+ }
209
+ // ---------------------------------------------------------------------------
210
+ // Refetch
211
+ // ---------------------------------------------------------------------------
212
+ /**
213
+ * Re-fetch already-paid content by re-sending the original payment header plus
214
+ * `X-Payment-Refetch: <payment_id>`, then verify the returned receipt.
215
+ *
216
+ * 410 -> refetch_expired; any other non-200 (including 402) -> refetch_refused.
217
+ */
218
+ export async function refetch(input) {
219
+ const f = input.fetch ?? globalThis.fetch;
220
+ const headers = {
221
+ ...(input.headers ?? {}),
222
+ ...input.paymentHeaders,
223
+ [REFETCH_HEADER]: input.paymentId,
224
+ };
225
+ let res;
226
+ try {
227
+ res = await f(input.url, { method: "GET", headers });
228
+ }
229
+ catch (e) {
230
+ return { ok: false, reason: "refetch_refused", detail: `network error: ${e.message}` };
231
+ }
232
+ if (res.status === 410) {
233
+ await res.body?.cancel().catch(() => { });
234
+ return { ok: false, reason: "refetch_expired", status: 410 };
235
+ }
236
+ if (res.status !== 200) {
237
+ await res.body?.cancel().catch(() => { });
238
+ return { ok: false, reason: "refetch_refused", status: res.status };
239
+ }
240
+ const body = new Uint8Array(await res.arrayBuffer());
241
+ const header = res.headers.get(RECEIPT_HEADER);
242
+ let wellKnown = input.wellKnown;
243
+ if (!wellKnown) {
244
+ try {
245
+ wellKnown = await fetchWellKnown(new URL(input.url).origin, { fetch: f });
246
+ }
247
+ catch (e) {
248
+ return { ok: false, reason: "receipt_key_unknown", status: 200, detail: e.message };
249
+ }
250
+ }
251
+ const v = verifyReceipt({
252
+ header,
253
+ body,
254
+ wellKnown,
255
+ expect: { payment_id: input.paymentId, resource: input.expectResource },
256
+ });
257
+ if (!v.ok)
258
+ return { ...v, status: 200 };
259
+ return { ok: true, body, receipt: v.receipt, status: 200 };
260
+ }
261
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,41 @@
1
1
  {
2
2
  "name": "@x402jp/delivery-receipt-verify",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Zero-dependency verifier for x402 Delivery Receipts (buyer side).",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "engines": {
14
+ "node": ">=20"
15
+ },
16
+ "scripts": {
17
+ "test": "node --test --import tsx test/*.test.ts",
18
+ "build": "tsc -p tsconfig.build.json"
19
+ },
20
+ "main": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "files": [
23
+ "dist",
24
+ "README.md"
25
+ ],
26
+ "publishConfig": {
27
+ "access": "public",
28
+ "provenance": true
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/kato9292929/delivery-receipt.git",
33
+ "directory": "packages/verify"
34
+ },
35
+ "keywords": [
36
+ "x402",
37
+ "delivery-receipt",
38
+ "usdc",
39
+ "payments"
40
+ ]
41
+ }