Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Hyperledger Identus SDK for Rust

Chain-neutral Rust foundations for decentralized identity, verifiable credentials, and wallet products.

Pre-release software: the active develop line and 0.1.0-rc.1 trains are experimental. A registry receipt—not this handbook—proves whether a crate is published. No crate is production-supported, certified, or a final SemVer commitment.

This handbook answers three practical questions:

  1. What reusable capabilities belong in SDK-Rust?
  2. Why are the crypto foundation and DID capabilities separate release trains?
  3. What evidence and human decisions remain before each candidate can advance?

The short version

CrateOne responsibilityDeliberately outside
identus-deriveGenerate recurring validated-newtype and port-marker scaffolding at compile time.Runtime SSI, protocol, chain, storage, and product policy.
identus-coreProvide chain-neutral errors, time, URL, component metadata, and foundational capability types.Cryptographic algorithms, DID methods, transports, custody, and wallet policy.
identus-cryptoProvide reusable bytes-in/bytes-out cryptographic primitives and explicit entropy injection.Key custody, hardware/KMS policy, JOSE/protocol policy, ledgers, and wallet decisions.

The dependency direction is intentional: crypto builds on core; core uses the derive tooling; neither foundation may depend on a blockchain, wallet product, or downstream repository.

The next independent train is candidate-only. identus-did supplies generic DID values, document models, and resolver ports. identus-did-resolver-http is the optional Axum host adapter. It adds no DID method, ledger, chain, wallet, or product policy.

Start here

SDK-Rust is the generic Rust foundation shared by Identus ecosystem products. It is not a wallet application, blockchain SDK, cloud service, or umbrella that automatically owns every SSI protocol.

Ownership rule

Reusable, chain-neutral domain primitives, cryptographic utilities, protocol engines, ports, validation, and conformance evidence belong in SDK-Rust. Method, ledger, runtime, custody, consent, trust, persistence, user experience, deployment, and certification policy remain with their owning downstream.

That distinction allows Midnight Identity, NeoPRISM/Cardano, Lace ID Portal, Oxid, and future products to share foundations without forcing one chain or product model into the others.

Maturity vocabulary

TermMeaning here
ImplementedCode and tests exist; the public surface may still change.
CandidateA reproducible artifact is available for review; publication status is proven only by its registry receipt.
Experimental 0.xSemVer applies with an explicit migration policy and support window.
SupportedThe documented compiler, targets, features, and support period are an effective promise.
CertifiedAn external assessment or certification exists; tests alone never imply this.

The first three packages—identus-derive, identus-core, and identus-crypto—are release-activated 0.1.0-rc.1 packages. The independent identus-did and identus-did-resolver-http train is candidate-only: its release-shaped archives are prepared in an isolated temporary workspace, but its canonical manifests remain version 0.0.0 with publish = false. Every other workspace package remains 0.0.0, unpublished, and outside either candidate closure.

Branches

  • develop is the protected integration and documentation source.
  • main is intentionally reserved and is not populated by site publication.
  • Releases require a separately approved exact revision and protected process.

For the repository-level contract, see Governance, constraints, and the release policy.

The first crypto release train

The first published prerelease is a three-package closure at 0.1.0-rc.1:

identus-crypto =0.1.0-rc.1
    ├── identus-core =0.1.0-rc.1
    └── identus-derive =0.1.0-rc.1

identus-core =0.1.0-rc.1
    └── identus-derive =0.1.0-rc.1

identus-derive is included because it generates foundational type behavior at compile time. identus-core gives the crypto crate stable chain-neutral error, metadata, URL, and clock contracts. identus-crypto is the independently useful consumer capability that justified preparing the closure first.

Why not release the whole monorepo?

The workspace also contains implemented experimental components and quarantined placeholders. Releasing all of them together would convert package presence into accidental API, support, and namespace promises. The isolated train keeps the first review cohesive. DID follows its own candidate-only train; credentials, protocols, bindings, and wallet ports remain on their own evidence-driven timelines.

The separate DID candidate train reuses the released foundation without changing this train’s immutable tag or publication receipt.

Candidate and publication mechanics

The three canonical package manifests carry 0.1.0-rc.1; every unrelated workspace member retains the 0.0.0, publish = false default. The candidate tool creates a temporary three-member workspace, uses exact internal requirements, and assembles every Cargo archive twice. It verifies normalized contents, extracted archive closure, feature profiles, public API, SemVer, SBOMs, checksums, tool versions, source identity, and limitations.

Candidate preparation is deliberately not publication. The descriptor states publication = "release-gated": upload occurs only from a signed exact tag through the protected crates-io environment, with an independent maintainer approval and an immutable publication receipt. The namespace- creating train uses a short-lived bootstrap token; every later train uses crates.io trusted publishing through OIDC.

The credential-bearing job repeats the signed-tag, exact-SHA, and protected develop ancestry checks after environment approval. Candidate artifacts are scoped to the workflow run rather than an individual attempt, so a failed job can be retried without rebuilding or substituting evidence. Existing packages and release assets are reused only when their checksums and release identity match exactly; disagreement fails closed.

Read ADR 0134, ADR 0113, and the candidate descriptor for the executable contract.

DID candidate train

M5 prepares two chain-neutral packages as an independent 0.1.0-rc.1 candidate:

identus-did-resolver-http =0.1.0-rc.1
    ├── identus-did =0.1.0-rc.1
    └── identus-core =0.1.0-rc.1

identus-did =0.1.0-rc.1
    ├── identus-core =0.1.0-rc.1
    └── identus-derive =0.1.0-rc.1 (build-time)

Responsibilities and boundary

PackageOwnsDoes not own
identus-didValidated DID and DID URL values, DID documents, verification methods, services, resolver-facing models, and generic resolver ports.DID methods, ledger access, networking, persistence, key custody, trust, consent, or wallet policy.
identus-did-resolver-httpAxum request/response mapping, DID resolution content negotiation, and optional openapi schema types.A resolver implementation, DID method, deployment topology, authentication, rate limiting, or product policy.

The HTTP package is an optional host adapter, not a required facade. Consumers that need only domain values or implement their own transport select identus-did directly. DID method and chain adapters depend on the generic ports from outside this candidate boundary.

Candidate state

The canonical workspace manifests are still version 0.0.0 with publish = false. The candidate tool stages release-shaped archives in an external scratch workspace without changing those manifests. Its reserved future tag is identus-did-v0.1.0-rc.1; no tag, GitHub release, publication workflow, or crates.io artifact is claimed here.

The exact protected source revision for this review is:

cda086f3e7fe72d251c1f896bccdcf5dd1bc8c16

Use the source-adoption instructions to evaluate it. A library that will itself be published to crates.io cannot retain a Git dependency and must wait for registry-published packages.

Reproducible evidence

Two clean preparations reproduced the same candidate archives and evidence:

Evidenceidentus-did SHA-256identus-did-resolver-http SHA-256
Cargo archiveec9ed5be2f8d716d1395cdea347ec71f19def355617579a7ad26cfc14681f7a7875801cbcd2bb5b1e378ca4f84903f1f58949da7447cea7e586f172845eb8434
Public API origin3412a7dce4b5699afda75ad5c9a0bb4f6f5fbb5cb3256e187a2d107fb26763dd9c432f0d0c3d5db92da3aa88aed05164aa2adf483c11be84b9239c9973179df6
Normalized CycloneDX 1.5371096ba00a08803548b67afcff8df15c10a228fbcd0bfbcf6297e742e4751759f1734f3e400850c58dddc13ed36ea52d71050be899788ec988926b0ca1b5349

The committed API snapshots establish the origin for later SemVer comparison. Because this is the first candidate, compatibility is explicitly not-applicable-first-candidate; no self-comparison was used to manufacture a green result. The SBOMs describe dependencies and licenses but do not replace Cargo-deny, advisory review, provenance, or security assessment.

Primary evidence:

Compiler and target contract

PackageLinux + macOSBrowser WASMAndroid ARM64iOS ARM64
identus-didPrimary tests + MSRV compile checksCompile-checkedCompile-checkedCompile-checked
identus-did-resolver-httpPrimary tests + MSRV compile checksNot supportedNot supportedNot supported

The matrix always exercises the staged 0.1.0-rc.1 sources and their exact internal dependency versions. Portable rows use cargo check with Rust 1.98.1 and 1.89.0; they make no browser, device, simulator, binding, packaging, performance, or certification claim. The HTTP adapter is host-only by design. Weekly/manual slow CI produces four attempt-scoped lane receipts and accepts their aggregate only when source revision, compiler identities, target rows, outcomes, and staged lockfile agree.

Promotion gates

Candidate assembly and documentation do not authorize publication. The matrix implementation is tracked in #387, but only a natural or explicitly approved manual slow run at the final revision constitutes release evidence. M5 then requires an independent exact-SHA decision in #388. Administrator-owned trusted-publishing hardening remains tracked by #344.

See release readiness for the consolidated gate table.

Candidate crates

Each candidate crate has one reason to exist and a visible boundary. The separation is designed for low coupling, high cohesion, minimal feature cones, and independent future evolution.

Crypto foundation train

CrateKindRuntime dependency direction
identus-deriveProcedural macroBuild-time only
identus-coreFoundation values and portsDepends on identus-derive and Serde
identus-cryptoCryptographic primitivesDepends on identus-core and identus-derive; algorithms are feature-gated

The release train is not a layered facade where consumers must always import all three. A consumer normally selects the highest-level crate it needs; Cargo resolves its exact internal closure.

DID candidate train

CrateKindRuntime dependency direction
identus-didGeneric DID domain and portsDepends on released identus-core; uses identus-derive at build time
identus-did-resolver-httpOptional Axum HTTP adapterDepends on identus-did, released identus-core, and host HTTP libraries

These two packages are candidate-only and source-evaluated. They are not available from crates.io merely because a staged 0.1.0-rc.1 archive and public-API origin exist. See the DID candidate review.

identus-derive

identus-derive is compile-time tooling for repetitive, security-sensitive domain-type structure.

It owns

  • #[derive(Newtype)] for supported single-field string, byte, and numeric tuple structs;
  • generated constructors, accessors, conversions, display behavior, optional Serde integration, and fallible parsing appropriate to each category;
  • #[identus::port], an inert capability marker that enforces the SDK’s port-trait naming convention;
  • validation of generated output against forbidden unsafe constructs before tokens leave the macro.

It does not own

  • business or protocol validation rules;
  • a runtime object model;
  • cryptography, serialization formats, storage, transport, or chains;
  • arbitrary code generation for downstream convenience.

The consuming type declares its domain constraint. The macro standardizes the safe shape; it does not decide what a valid DID, credential, key, or wallet policy means.

Why it is a separate crate

Rust procedural macros compile for the build host and require a dedicated proc-macro package. Keeping that compiler surface separate also prevents syn, quote, and proc-macro2 from becoming runtime dependencies of SDK consumers.

Review focus

  • Diagnostics and generated public APIs are compatibility surfaces.
  • Generated code must inherit the repository’s no-unsafe policy.
  • Compile-fail fixtures are part of the contract, not incidental tests.
  • Runtime crates should expose explicit types rather than re-exporting the macro crate as a broad facade.

Source

identus-core

identus-core holds small chain-neutral values and capability contracts that multiple SDK components need without depending on a protocol or product.

It owns

  • stable component metadata;
  • capability identifiers and error codes;
  • redaction-safe IdentusError, ErrorKind, and IdentusResult contracts;
  • bounded generic URLs;
  • wall and monotonic clock ports plus millisecond time/duration values.

The public error value stores static public fields. Its display form contains a stable code and public message, not secrets or internal debugging context.

It does not own

  • a catch-all prelude or umbrella SDK facade;
  • cryptographic algorithms or secret-bearing key types;
  • DID/VC/protocol wire models;
  • network clients, persistence, telemetry, trust, custody, or wallet policy;
  • chain or runtime integration.

Dependency role

identus-core uses identus-derive for shared type conventions and Serde for the bounded values that require serialization. Higher crates depend inward on core; core must never depend outward on those components.

Example: public error boundary

use identus_core::{CapabilityId, ErrorCode, ErrorKind, IdentusError};

let error = IdentusError::public(
    ErrorCode::new("invalid_input"),
    ErrorKind::InvalidInput,
    CapabilityId::new("example"),
    "input is invalid",
);

assert_eq!(error.to_string(), "invalid_input: input is invalid");

Source

identus-crypto

identus-crypto provides reusable primitive operations on key material. Its contract is bytes-in/bytes-out cryptography with typed boundaries—not custody, wallet orchestration, or protocol policy.

Capability surface

  • Ed25519 signing and verification;
  • X25519 key agreement material and Ed25519-to-X25519 conversion;
  • secp256k1 and P-256 keys, signing, and verification;
  • SHA-256/SHA-512 and supporting HMAC/PBKDF2 paths;
  • BIP-39, secp256k1 BIP-32, SLIP-0010, and Cardano V2 Ed25519-BIP32;
  • bounded hex, Base64URL, public JWK, JWK thumbprint, and public COSE Key representations;
  • caller-injected SecureRandom for key generation and mnemonic creation.

Feature policy

Algorithms and encodings are feature-gated. Consumers should disable defaults and select the smallest reviewed capability cone when they do not need the full suite.

FeatureAdds
hashSHA-256 and SHA-512 digest values/functions
ed25519Ed25519 key and signature operations; public JWK support
x25519X25519 keys; conversion also requires hash
secp256k1K-256 key and ECDSA operations
secp256r1P-256 key and ECDSA operations
jwk / jwk-thumbprintBounded public JWK values and RFC 7638 thumbprints
coseBounded public COSE Key values
derivationBIP-39, BIP-32/SLIP-0010, HMAC, and required curves
cardano-bip32Cardano V2 extended Ed25519 keys
kmp-compatExplicit legacy KMP/Apollo interop path

Security boundary

Secret-bearing SDK types redact diagnostics and use zeroization where their owned representation permits it. The workspace forbids first-party unsafe code. Entropy is explicit and fallible; the production adapter lives outside the primitive crate.

Consumers still own:

  • non-exportable key handles and hardware/KMS integration;
  • secure storage, backup, recovery, access control, and consent;
  • algorithm/profile negotiation and protocol verification policy;
  • side-channel and platform hardening appropriate to their threat model;
  • rate, message-size, and work budgets at the calling boundary.

Example: minimal hashing

use identus_crypto::sha256;

let digest = sha256(b"bounded public input");
assert_eq!(digest.as_array().len(), 32);

Before registry publication, evaluation uses a full immutable Git revision and an explicit feature set. See Adoption.

Source

Architecture

SDK-Rust uses an inward dependency direction: products and chain adapters may depend on generic components, while generic components cannot import product, chain, runtime, deployment, or UI policy.

The first release candidate intentionally covers only the lowest cohesive three-crate closure.

Dependency direction

Arrows mean “depends on.” Dependency direction always points toward the more stable, generic center:

  1. wallets, identity products, and chain families select SDK components;
  2. protocol/domain components select primitive foundations;
  3. identus-crypto depends on identus-core;
  4. identus-core and identus-crypto use identus-derive at compile time.

The reverse direction is forbidden. In particular, the three-crate release train cannot depend on Midnight, Compact, Cardano/PRISM, consumer repositories, wallet storage implementations, or product trust/custody policy.

This allows downstreams to evolve independently while sharing evidence-backed foundations.

Ownership boundaries

SDK-Rust owns

  • generic primitives and domain values;
  • reusable cryptographic operations and bounded representations;
  • protocol-neutral ports and validation contracts;
  • conformance and compatibility evidence attached to those surfaces.

Chain and identity repositories own

  • DID method semantics and operation construction;
  • ledger clients, indexing, submission, synchronization, and finality;
  • Compact contracts, proving systems, and chain-native cryptosuites;
  • chain deployment and operational policy.

Wallet and application products own

  • key custody, secure storage, consent, account recovery, and authorization;
  • trust decisions, credential selection, user experience, and telemetry;
  • backend deployment, availability, privacy, and regulatory controls;
  • the decision to adopt an SDK revision or release.

An SDK abstraction is reusable only when these product and chain decisions can remain outside it.

Evidence and release flow

The repository separates ordinary integration from production promotion:

  • Fast line: one required Ubuntu build/lint/test/factory gate for pull requests into develop.
  • Slow line: weekly/manual target, binding, fuzz, coverage, package, performance, and platform evidence on an exact protected revision.
  • Candidate gate: deterministic packages, API/SemVer review, SBOMs, checksums, provenance, source closure, consumer evidence, and documentation.
  • Human release gate: one release manager and a second maintainer approve the exact receipt before a tag or registry upload.

Documentation publication is evidence before the release decision. It does not advance the candidate by itself.

Adoption before publication

Every implemented SDK-Rust package can be evaluated from source; packages that are not published require this channel. A consumer pins the full commit reachable from protected develop, chooses features explicitly, and commits its lockfile.

identus-crypto = {
  git = "https://github.com/hyperledger-identus/sdk-rust",
  rev = "FULL_40_HEX_REVIEWED_COMMIT",
  default-features = false,
  features = [ "hash" ],
}

The placeholder must be replaced with the exact reviewed revision. Do not use develop, a tag that does not exist, a pull-request ref, or a short SHA.

The current DID candidate may be evaluated at the exact protected merge that contains its verified candidate evidence:

identus-did = {
  git = "https://github.com/hyperledger-identus/sdk-rust",
  rev = "cda086f3e7fe72d251c1f896bccdcf5dd1bc8c16",
}

identus-did-resolver-http = {
  git = "https://github.com/hyperledger-identus/sdk-rust",
  rev = "cda086f3e7fe72d251c1f896bccdcf5dd1bc8c16",
  default-features = false,
  features = [ "openapi" ],
}

Select the resolver package only when the consumer needs the Axum HTTP adapter; select openapi only when it needs generated schema support. The reserved candidate identity identus-did-v0.1.0-rc.1 is not a created tag or a registry receipt. Do not add a misleading version = "0.0.0" constraint.

Adoption receipt

Record:

  • old and new exact SDK revisions;
  • selected packages and features;
  • compiler and tested targets;
  • Cargo and Nix lock/hash changes;
  • dependency/feature-tree delta;
  • unit, conformance, integration, advisory, and license results;
  • public/wire compatibility and rollback.

The first planned M3 consumer is a minimal hash-only downstream canary. It is owned and implemented entirely downstream: this repository accepts only generic evidence and does not import consumer names, primitives, or policy. NeoPRISM provides a broader source-pinned cryptography integration reference.

The crypto train’s registry receipt and the DID train’s exact source revision are different evidence channels. Source evaluation provides no crates.io checksum, stable SemVer support promise, LTS period, certification, or production warranty.

Release readiness

The first 0.1.0-rc.1 train for identus-derive, identus-core, and identus-crypto was published from approved source 21cfc28321f76f1d14a2483d536d302017674a18. Final 0.1.0 is not implied by that prerelease.

M3 release record

GateStatusEvidence owner
Reproducible isolated candidatePublished from the approved exact candidaterelease v0.1.0-rc.1, ADRs 0113/0134
Functional cryptography foundationComplete within its recorded limitations#286
Public architecture/release handbookDeployed#324
Durable crate names and first-publish bootstrapPublished; tokenless ownership/recovery hardening remains open#3, #344
Release compiler/support matrixComplete for the published candidate#325, ADR 0133
Independent downstream canaryExact-source canary green; downstream registry refresh remains externally owned#326
Natural weekly slow evidenceComplete at 19d0362038c3f2af6898624ea04347e3cd4648f7run 35555024293
Exact candidate slow receiptComplete for the published sourcerun 35887204030
Two-person approval and protected publicationComplete; bootstrap publication receipt retainedrun 35990705278, #326

Approval questions

Engineers reviewing later crypto trains should reuse these questions:

  1. Are the three crate responsibilities cohesive and appropriately separated?
  2. Is the public API small enough for an experimental SemVer commitment?
  3. Does the compiler/target promise match consumer needs and maintenance cost?
  4. Is the selected dependency and unsafe/native cone acceptable?
  5. Can a downstream adopt or reject the candidate without tribal knowledge?
  6. Is any release blocker absent from the evidence table?

The approval and publication record is issue #326. That issue remains open for post-bootstrap hardening, not because the first publication is unapproved. Future approval must again bind an exact source revision and candidate receipt; it cannot be inferred from this page or from a green documentation deployment.

M5 DID candidate status

The separate M5 target is 0.1.0-rc.1 for identus-did and identus-did-resolver-http. It is candidate-only and has no publication workflow or registry claim.

GateStatusEvidence owner
Independent train identity and deterministic archivesComplete#382, ADR 0153
Public API origins and normalized CycloneDX evidenceComplete#384, ADR 0154
Engineer-facing architecture and adoption handbookImplemented in this source revision; deployment receipt remains on the issue#386
Rust/target qualificationOpen#387
Final exact-SHA candidate approvalOpen; follows all prior gates#388
Trusted-publishing administrationSeparate administrator-owned hardening#344

Reviewers should start with the DID candidate train. A green site build proves documentation integrity only; it does not complete the open target, approval, registry, tag, or publication gates.

Governance and contribution

SDK-Rust is AI-first but evidence-gated. Agents may plan, implement, review, push, and merge routine issue-linked work into protected develop after the required checks pass. Humans retain authority over release, publication, repository administration, security disclosure, legal-risk acceptance, and promotion to main.

Specification-driven flow

issue → research → constraints → OpenSpec contract → preflight
      → implementation → verification → review → protected develop
      → production evidence → human release decision

Important repository references:

Documentation changes use the same issue, OpenSpec, signed/DCO commit, local review, exact-head CI, and protected merge controls as code changes.

Current limitations

The handbook is intentionally explicit about what has not been proven.

  • Only identus-derive, identus-core, and identus-crypto are activated for the protected 0.1.0-rc.1 crates.io train; use its registry receipt to determine live publication state.
  • identus-did and identus-did-resolver-http have isolated, reproducible 0.1.0-rc.1 candidate archives but no crates.io release. Their canonical manifests remain 0.0.0 with publish = false; evaluate them only by exact source revision.
  • Every package outside those two train closures also remains 0.0.0 with publish = false.
  • Rust 1.89.0 is the 0.1.x release MSRV; Rust 1.98.1 remains the primary and compatibility-etalon compiler.
  • WASM, iOS, and Android cryptography evidence is currently compile-oriented; it is not a blanket browser/device/runtime support claim.
  • Experimental DID language-binding evidence does not automatically support the crypto or DID release train on those platforms.
  • DID candidate API snapshots are a diffable compatibility origin, not a stable API promise. Candidate SBOMs are dependency evidence, not an advisory scan, signed provenance, vulnerability-free claim, or certification.
  • Test vectors, fuzzing, coverage, static analysis, and review reduce risk but are not security or compliance certification.
  • The SDK does not provide key custody, hardware/KMS management, secure wallet storage, trust policy, consent, chain integration, or product operations.
  • Consumer adoption remains independently owned and reversible.
  • Apollo deprecation and downstream duplicate removal require later releases, adoption evidence, and maintainer governance.

The machine-readable constraint index and component evidence remain normative: