{"id":50776604,"url":"https://github.com/cardanowall/cip309-rs","last_synced_at":"2026-06-12T00:02:38.151Z","repository":{"id":362058771,"uuid":"1256469643","full_name":"cardanowall/cip309-rs","owner":"cardanowall","description":"Rust SDK for CIP-309 (crate: cardanowall) — a byte-parity twin of the TypeScript and Python implementations.","archived":false,"fork":false,"pushed_at":"2026-06-02T11:24:57.000Z","size":596,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-02T12:31:16.188Z","etag":null,"topics":["blockchain","cardano","cip-309","proof-of-existence","rust","sdk","timestamping"],"latest_commit_sha":null,"homepage":"https://cip309.org","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cardanowall.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-01T20:07:17.000Z","updated_at":"2026-06-02T11:38:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cardanowall/cip309-rs","commit_stats":null,"previous_names":["cardanowall/cip309-rs"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/cardanowall/cip309-rs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cardanowall%2Fcip309-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cardanowall%2Fcip309-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cardanowall%2Fcip309-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cardanowall%2Fcip309-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cardanowall","download_url":"https://codeload.github.com/cardanowall/cip309-rs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cardanowall%2Fcip309-rs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34222711,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-11T02:00:06.485Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blockchain","cardano","cip-309","proof-of-existence","rust","sdk","timestamping"],"created_at":"2026-06-12T00:02:38.072Z","updated_at":"2026-06-12T00:02:38.141Z","avatar_url":"https://github.com/cardanowall.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cardanowall — Rust SDK for the Label 309 Proof-of-Existence standard\n\n`cardanowall` is the Rust implementation of the Label 309 Proof-of-Existence (PoE)\ntoolkit: a standalone structural validator, a public verifier, a recipient\nverifier with sealed-PoE decryption, and a gateway-agnostic HTTP client. It is a\n**byte-parity sibling** of the TypeScript (`@cardanowall/sdk-ts`) and Python\n(`cardanowall-sdk`) SDKs — it independently reproduces the same canonical-CBOR\nbytes, validation verdicts, and cryptographic outputs, proven against the same\nshared cross-implementation test vectors.\n\nNothing in this crate trusts a publisher or an issuer server. A proof verifies\nfrom a Cardano transaction's metadata, an optional copy of the content bytes, and\na public blockchain explorer. The HTTP layer is blocking (`reqwest` in blocking\nmode) and secure-by-default: every outbound call flows through one egress point\nthat enforces a protocol/method allowlist, a deny-host policy, bounded response\nbodies and timeouts, and an SSRF guard for user-supplied URLs.\n\nThe companion `cardanowall` CLI binary is a separate crate built on top of this\nSDK.\n\n## What it is\n\n- **A standalone verifier** with three roles, all service-independent:\n  - **Structural validator** — `poe_standard::validate_poe_record`, a pure\n    function over canonical-CBOR bytes. No I/O, no signatures, no decryption.\n  - **Public verifier** — `verifier::verify_tx` resolves a transaction, extracts\n    the label-309 record, validates it structurally, and verifies record-level\n    signatures.\n  - **Recipient verifier** — the public verifier plus an X25519 private key:\n    decrypts a sealed PoE and recomputes plaintext hashes.\n- **A gateway-agnostic client** (`client::Label309Client`) for any Label 309\n  gateway: you pass an explicit base URL and an optional opaque bearer key.\n- **The cryptographic building blocks** — hash, KDF, COSE, sealed-PoE,\n  recipient encoding, Merkle, and seed-derived identity helpers.\n\n## Install\n\nPre-1.0 and not yet published to crates.io. Build from the workspace, or depend\non it by path/git:\n\n```toml\n# Cargo.toml — by git, until published\n[dependencies]\ncardanowall = { git = \"https://github.com/cardanowall/label-309-rs\" }\n```\n\nOnce published to crates.io the line will be:\n\n```toml\n# once published\n[dependencies]\ncardanowall = \"0.1\"\n```\n\nThe crate requires the OS CSPRNG for the secure-by-default sealed-PoE wrap and\nuses `rustls` for TLS (no system OpenSSL needed).\n\n## Quick start\n\n### Hash content (byte-identical across the SDK family)\n\n```rust\nuse cardanowall::hash::{dual_hash, SHA2_256_ID, BLAKE2B_256_ID};\nuse cardanowall::hex;\n\nlet digests = dual_hash(b\"contract v3\");\nprintln!(\"{} = {}\", SHA2_256_ID, hex::encode(\u0026digests.sha256));\nprintln!(\"{} = {}\", BLAKE2B_256_ID, hex::encode(\u0026digests.blake2b256));\n```\n\nFor large or streamed input, `hash::dual_hash_stream` computes both digests\nwithout holding the whole input in memory.\n\n### Validate a record structurally (pure, no I/O)\n\n```rust\nuse cardanowall::poe_standard::{validate_poe_record, ValidateResult};\n\n// `record_bytes` is the canonical-CBOR record, reassembled from the\n// label-309 bytes-chunk array (records are tag-259-wrapped on the wire).\nmatch validate_poe_record(\u0026record_bytes) {\n    ValidateResult::Valid { record, issues } =\u003e {\n        // `issues` may carry warnings/info; the record is structurally sound.\n        println!(\"valid record, {} issue(s)\", issues.len());\n        let _ = record;\n    }\n    ValidateResult::Invalid { issues } =\u003e {\n        for issue in issues {\n            eprintln!(\"{}: {}\", issue.code.as_str(), issue.message);\n        }\n    }\n}\n```\n\n### Verify a transaction end to end (public verifier)\n\n```rust\nuse cardanowall::verifier::{verify_tx, ExitCode, Verdict, VerifyTxInput};\n\nlet mut input = VerifyTxInput::new(\"aabbccdd…\");        // lowercase tx hash, no 0x\ninput.cardano_gateway_chain = Some(vec![\n    \"https://api.koios.rest/api/v1\".to_string(),\n]);\n\nlet report = verify_tx(\u0026input);\nmatch report.verdict {\n    Verdict::Valid =\u003e println!(\"valid, exit {}\", report.exit_code.as_u8()),\n    Verdict::Pending =\u003e println!(\"not yet final: {} confirmations\", report.num_confirmations),\n    Verdict::Failed =\u003e eprintln!(\"failed, exit {}\", report.exit_code.as_u8()),\n}\nassert!(matches!(report.exit_code, ExitCode::Ok | ExitCode::InsufficientDepth | ExitCode::Integrity | ExitCode::Network));\n```\n\n`verify_tx` never panics: a malformed record, a missing label-309 entry, or a\ngateway failure each produce a `VerifyReport` with the corresponding verdict and\nexit code (`0` ok, `1` integrity, `2` network, `3` insufficient depth). The\nreport carries a per-call HTTP audit trail in `report.http_calls`.\n\n### Recipient verifier: decrypt a sealed PoE\n\n`VerifyTxInput` accepts out-of-band recipient keys; the verifier then decrypts\nthe sealed item and recomputes the plaintext hashes as part of the verdict:\n\n```rust\nuse cardanowall::verifier::{verify_tx, Decryption, Verdict, VerifyTxInput};\n\nlet mut input = VerifyTxInput::new(\"aabbccdd…\");\ninput.cardano_gateway_chain = Some(vec![\"https://api.koios.rest/api/v1\".to_string()]);\ninput.decryption = Some(vec![Decryption::Recipient {\n    item_index: 0,\n    recipient_secret_key: recipient_x25519_or_xwing_secret, // Vec\u003cu8\u003e\n}]);\n\nlet report = verify_tx(\u0026input);\nassert_eq!(report.verdict, Verdict::Valid);\n```\n\n### Sign a record off-host from a master seed\n\nThe seed-derived signer holds the Ed25519 secret in-memory and exposes only the\npublic key and the 64-byte signature, so the gateway never sees a private key:\n\n```rust\nuse cardanowall::client::Signer;\nuse cardanowall::seed_derive::signer_from_seed;\n\nlet seed = [0u8; 32];                       // the 32-byte master identity seed\nlet signer = signer_from_seed(\u0026seed)?;       // SeedDeriveError on wrong length\nlet pubkey = signer.signer_pubkey();         // raw 32-byte Ed25519 public key\nlet signature = signer.sign(\u0026sig_structure_bytes)?; // 64-byte Ed25519 signature\n# Ok::\u003c(), cardanowall::seed_derive::SeedDeriveError\u003e(())\n```\n\n`seed_derive::derive_ed25519_keypair`, `derive_x25519_keypair`, and\n`derive_mlkem768x25519_keypair` (hybrid post-quantum X-Wing) expose the same\ndeterministic identity keys directly.\n\n### Talk to a gateway (any Label 309 deployment)\n\nThe client targets no default host. You name the gateway with an explicit\n`base_url`; the optional `api_key` is an opaque bearer forwarded verbatim as\n`Authorization: Bearer …` (never validated or parsed). With no key the client is\nanonymous and read-only.\n\n```rust\nuse cardanowall::client::{Label309Client, Label309ClientConfig};\n\nlet client = Label309Client::new(Label309ClientConfig {\n    base_url: Some(\"https://gateway.example\".to_string()),\n    api_key: Some(\"opaque-bearer-token\".to_string()),\n})?;\n\nlet balance = client.account().balance()?;        // AccountBalance\nlet record = client.records().get(\"aabbccdd…\")?;  // RecordResource, by tx hash\n# Ok::\u003c(), Box\u003cdyn std::error::Error\u003e\u003e(())\n```\n\n`cardanowall.com` is one example deployment; this SDK works against any gateway\nthat implements the Label 309 surface. A missing or empty `base_url` is the one\nillegal config and raises `InvalidClientConfigError` from the constructor.\n\n## API overview\n\n| Module                                   | Surface                                                                                                                                                                                                       |\n| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `hash`                                   | `sha256`, `blake2b256`, `dual_hash`, `dual_hash_stream`; `SHA2_256_ID`, `BLAKE2B_256_ID`                                                                                                                      |\n| `poe_standard`                           | `validate_poe_record`, `encode_poe_record`, `encode_record_body_for_signing`, `chunk_bytes` / `bytes_chunk_array_concat`, `chunk_uri` / `reconstruct_chunked_uri`; `PoeRecord`, `ValidateResult`, `ErrorCode` |\n| `verifier`                               | `verify_tx`, `VerifyTxInput`, `VerifyReport`, `Verdict`, `ExitCode`, `Profile`, `Decryption`; `verify_record_signatures`, `extract_label_309_metadata`, `resolve_cardano_tx`, `verify_report_to_dict`         |\n| `client`                                 | `Label309Client`, `Label309ClientConfig`; namespaces `poe()` / `records()` / `inbox()` / `account()`; `Signer`, off-host signing helpers, `HttpError`, `ProblemDetails`                                       |\n| `seed_derive`                            | `signer_from_seed`, `derive_ed25519_keypair`, `derive_x25519_keypair`, `derive_mlkem768x25519_keypair`, `derive_bookmark_key`                                                                                 |\n| `sealed_poe`                             | `ecies_sealed_poe_wrap_secure`, `ecies_sealed_poe_unwrap`, `ecies_sealed_poe_trial_decrypt`, envelope/slots/kem/aead                                                                                          |\n| `recipient`                              | `encode_age_x25519_recipient`, `encode_age_xwing_recipient`, `parse_age_recipient`, bech32 helpers                                                                                                            |\n| `merkle`                                 | `merkle_root`, `merkle_inclusion_proof`, `verify_inclusion`, `encode_leaves_list` / `decode_leaves_list`                                                                                                      |\n| `kdf`                                    | `hkdf_sha256`                                                                                                                                                                                                 |\n| `cbor`, `cose`, `hex`, `ids`, `webhooks` | canonical CBOR, COSE_Sign1, hex, wire identifiers, webhook signature verification                                                                                                                             |\n\nThe crate denies `unsafe_code` and missing docs; `cargo doc` is the exhaustive,\nalways-current reference.\n\n### Conformance profiles\n\nThe verifier reports a record at the highest profile it could check, in strict\nsuperset order: `core` (hash / uris / merkle) → `signed` (adds record-level\n`sigs[]`) → `sealed` (adds the `enc` envelope structure) → `recipient-sealed`\n(adds byte-level decryption with a recipient key, the default). A lower-profile\nverifier that meets a higher-profile field emits an info issue and continues; it\nnever reports the record invalid.\n\n## Cross-implementation parity\n\nThis crate is a **byte-parity twin** of `@cardanowall/sdk-ts` and\n`cardanowall-sdk` (Python). The three implementations are tested against the same\nshared known-answer-test vectors and a captured mainnet record corpus:\n\n- the **canonical CBOR** of an encoded record is identical bit-for-bit;\n- `validate_poe_record` returns the **same verdict and error codes**;\n- `verify_tx`'s report serialises (via `verify_report_to_dict`) to the\n  **byte-identical JSON** the TS and Python SDKs emit for the same transaction;\n- the **seed-derivation** `info` labels and outputs match, so one master seed\n  yields the same identity keys in every SDK;\n- the sealed-PoE wrap/unwrap and the X-Wing (ML-KEM-768 + X25519) hybrid KEM\n  produce identical wire bytes.\n\nPicking Rust, TypeScript, or Python is an ergonomics decision, not a\ncompatibility one.\n\n## Standard and service independence\n\nA Label 309 proof is verifiable with no cooperation from whoever published it:\n\n1. fetch the transaction's label-309 metadata from any public Cardano explorer;\n2. reassemble and structurally validate the record (`validate_poe_record`);\n3. verify record-level signatures and, for a sealed PoE, decrypt with the\n   recipient key and recompute plaintext hashes.\n\n`verify_tx` performs all three. No issuer server is contacted, and a deny-host\npolicy lets a verifier prove this by blocking any vendor host outright. The\nrecords are stored on-chain as a CBOR bytes-chunk array under metadata label 309\n(tag-259-wrapped); reassemble before validating — the helpers in `poe_standard`\ndo this for you.\n\n## Relation to the other packages\n\n- **`@cardanowall/crypto-core`** — closed-catalogue cryptographic primitives\n  (hash, KDF, signature, KEM, AEAD, CBOR, COSE, sealed-PoE, Merkle, recipient\n  encoding, seed derivation). The portable building blocks.\n- **`@cardanowall/poe-standard`** — the Label 309 wire-format library: record\n  schema, canonical-CBOR encoder, pure structural validator, error-code\n  catalogue.\n- **`@cardanowall/sdk-ts`** — the browser + Node TypeScript SDK: verifier,\n  agnostic client, off-host signing, seed-derived identity helpers.\n- **`cardanowall-sdk`** — the Python SDK: a byte-identical parity twin of\n  `sdk-ts`.\n- **`cardanowall` (this crate)** — the Rust SDK: the byte-parity twin in Rust,\n  blocking HTTP, secure-by-default egress. The `cardanowall` CLI is a separate\n  crate built on it.\n\n## License\n\nApache-2.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcardanowall%2Fcip309-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcardanowall%2Fcip309-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcardanowall%2Fcip309-rs/lists"}