@ar.io/proof 0.1.0 → 0.1.1
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 +104 -52
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,54 +1,106 @@
|
|
|
1
1
|
# @ar.io/proof
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
##
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
3
|
+
Verify [ar.io verification-stack](https://github.com/ar-io) provenance records — **with no ar.io code or service in the trust path**.
|
|
4
|
+
|
|
5
|
+
This is the TypeScript verification kernel for the *Verifiable Event Envelope* family: the signed JSON records that tools like the [`ariod` verification agent](https://github.com/ar-io/ar-io-agent) and the [MLflow plugin](https://github.com/ar-io/ar-io-mlflow) anchor permanently to Arweave. Given an envelope (fetched from any Arweave gateway), this package answers: *is it authentic, and does it commit to the bytes I'm holding?*
|
|
6
|
+
|
|
7
|
+
- **RFC 8785 (JCS)** canonicalization
|
|
8
|
+
- **SHA-256** payload binding (WebCrypto)
|
|
9
|
+
- **Ed25519** signature verification ([`@noble/ed25519`](https://github.com/paulmillr/noble-ed25519))
|
|
10
|
+
- **RFC 9162** binary Merkle inclusion proofs (checkpoint leaves)
|
|
11
|
+
- Zero config, two small dependencies, ESM, browser + Node ≥ 20
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @ar.io/proof
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Verify an envelope
|
|
20
|
+
|
|
21
|
+
Fetch the raw transaction from any Arweave gateway and verify it client-side:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { verifyEnvelope } from "@ar.io/proof";
|
|
25
|
+
|
|
26
|
+
const env = await (await fetch("https://arweave.net/raw/<tx_id>")).json();
|
|
27
|
+
const result = await verifyEnvelope(env);
|
|
28
|
+
|
|
29
|
+
result.ok; // spec_version + payload_hash + Ed25519 all passed
|
|
30
|
+
result.signatureOk; // Ed25519 over the signed scope, against env.public_key
|
|
31
|
+
result.payloadHashOk; // SHA-256(JCS(payload)) === env.payload_hash
|
|
32
|
+
result.errors; // [] when ok — machine-readable reasons otherwise
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`verifyEnvelope` never throws on hostile input — a malformed envelope (or a lying gateway) yields `ok: false` with reasons, not an exception.
|
|
36
|
+
|
|
37
|
+
## Bind an envelope to bytes you hold (reverse provenance)
|
|
38
|
+
|
|
39
|
+
The check that defeats a lying gateway: Arweave *tags* are unsigned search hints, so after finding a candidate envelope, confirm it actually commits to your artifact's hash:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { sha256Hex, verifyEnvelope, contentHashes } from "@ar.io/proof";
|
|
43
|
+
|
|
44
|
+
const myHash = await sha256Hex(fileBytes); // 64-char lowercase hex
|
|
45
|
+
|
|
46
|
+
const result = await verifyEnvelope(env, myHash);
|
|
47
|
+
result.contentHashOk; // true ⇔ the envelope commits to exactly these bytes
|
|
48
|
+
result.contentRole; // how it commits: e.g. the registered baseline,
|
|
49
|
+
// an observed (tampered) hash, …
|
|
50
|
+
|
|
51
|
+
contentHashes(env); // all content hashes an envelope commits to, by event type
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Verify a Merkle inclusion proof
|
|
55
|
+
|
|
56
|
+
Agents close daily checkpoints over per-cycle leaves (RFC 9162, §2.1 domain separation — not the Bitcoin duplicate-leaf variant). Verify a leaf's inclusion against an anchored root:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { leafHash, verifyInclusion, hexToBytes } from "@ar.io/proof";
|
|
60
|
+
|
|
61
|
+
const ok = await verifyInclusion(
|
|
62
|
+
await leafHash(leafBytes), // Uint8Array leaf hash
|
|
63
|
+
leafIndex, // 0-based position
|
|
64
|
+
totalLeaves,
|
|
65
|
+
auditPath.map(hexToBytes), // sibling hashes, leaf → root
|
|
66
|
+
hexToBytes(expectedRootHex),
|
|
67
|
+
);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## API
|
|
71
|
+
|
|
72
|
+
| Export | What it does |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `verifyEnvelope(env, expectedContentHash?)` | The three load-bearing checks (spec-version registry, payload-hash recompute, Ed25519 over the signed scope) + optional content bind. Returns `VerificationResult`. |
|
|
75
|
+
| `contentHashes(env)` | The content hash(es) an envelope commits to, by event type — the reverse-provenance join keys. |
|
|
76
|
+
| `specVersionSupported(v)` | Fail-closed accept-check: `ario.agent/v1` and additive minors (`ario.agent/v1.<n>`). Unknown majors/profiles are rejected. |
|
|
77
|
+
| `jcs(value)` | RFC 8785 canonical JSON bytes. |
|
|
78
|
+
| `sha256Hex(bytes)` / `sha256Bytes(bytes)` | SHA-256 via WebCrypto. |
|
|
79
|
+
| `ed25519Verify(sig, msg, pubKey)` | Raw Ed25519 verification. |
|
|
80
|
+
| `leafHash` / `nodeHash` / `merkleRoot` / `auditPath` / `verifyInclusion` / `EMPTY_TREE_ROOT_HEX` | RFC 9162 binary Merkle tree primitives. |
|
|
81
|
+
| `utf8` / `bytesToHex` / `hexToBytes` | Encoding helpers. |
|
|
82
|
+
| `Envelope` / `VerificationResult` / `ContentRole` / `Subject` | Types. |
|
|
83
|
+
|
|
84
|
+
### Signed scope
|
|
85
|
+
|
|
86
|
+
The primary signature covers `JCS(envelope minus signature minus co_signatures)` ([envelope-spec](https://github.com/ar-io/ar-io-proof/blob/main/specs/envelope-spec.md) §2/§7.1). The reserved `co_signatures` carve-out lets countersignatures be added later without invalidating the primary signature.
|
|
87
|
+
|
|
88
|
+
## Why you can trust it (without trusting us)
|
|
89
|
+
|
|
90
|
+
Three **independent implementations** of this kernel exist — this package, the Python [`ar-io-proof`](https://pypi.org/project/ar-io-proof/) (PyPI), and the Go reference ([`ar-io-agent/pkg/proof`](https://github.com/ar-io/ar-io-agent/tree/main/pkg/proof), MIT-carved) — and every one is conformance-gated **byte-for-byte** in CI against the shared, frozen [`test-vectors-v1.0` corpus](https://github.com/ar-io/ar-io-proof/tree/main/test-vectors) (per-file SHA-256 pins). The [proof-checker web app](https://github.com/ar-io/ar-io-proof-checker) additionally runs this kernel and a WASM build of the Go reference against each other live, asserting identical verdicts across the corpus plus adversarial negatives.
|
|
91
|
+
|
|
92
|
+
That mutual gate is the point: anyone can verify ar.io provenance records with **no ar.io code in the trust path** — write your own verifier against the [public specs](https://github.com/ar-io/ar-io-proof/tree/main/specs) and the corpus will tell you if it's conformant.
|
|
93
|
+
|
|
94
|
+
## What this package deliberately does NOT do
|
|
95
|
+
|
|
96
|
+
- **Single-envelope scope.** Chain walking (`previous_hash`), checkpoint reconciliation, and gateway/transport logic are consumer-layer concerns composed above the kernel.
|
|
97
|
+
- **Provenance is history, not endorsement.** A verified envelope proves *these bytes have this signed, anchored history* — never "safe," "approved," or "currently in production."
|
|
98
|
+
- **Key identity is out-of-band.** The kernel proves the signature matches `env.public_key`; binding that key to a real-world identity is yours to establish.
|
|
99
|
+
|
|
100
|
+
## Requirements
|
|
101
|
+
|
|
102
|
+
ESM-only. Needs WebCrypto (`globalThis.crypto.subtle`): any modern browser, Node.js ≥ 20 (≥ 19 works), Deno, Bun, workers.
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
MIT — verification must be open.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ar.io/proof",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "TypeScript kernel of the ar.io verification stack: RFC 8785 (JCS) canonicalization, SHA-256, and Ed25519 verification for Verifiable Event Envelopes (ario.agent/v1 profile). Conformance-gated byte-for-byte against the test-vectors-v1.0 corpus.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|