dtg-credentials
Repo: github.com/OpenVTC/dtg-credentials
A Rust library implementing the Decentralized Trust Graph credential types. It provides the data structures and signing/verification logic for the Verifiable Credentials that form the edges of the trust graph.
What It Implements
The DTG Core Credentials specification from the Trust over IP Foundation’s DTG Working Group Credentials Task Force — v1.0 Working Draft 01 since crate version 0.2.0 (August 2026; 0.1.x tracked the informal v0.3). See DTG Credential Types for the full taxonomy.
Architecture
The library is compact — two source files and an example:
lib.rs— Core types:DTGCredentialwrapper,DTGCommon(W3C VC structure, including the WD01taskContextproperty),DTGCredentialTypeenum,CredentialSubjectvariants (Basic, Endorsement, Witness; RCard deprecated), signing/verification methods, VWC digest helpers (digest_multibase(),verify_digest())create.rs— Builder methods for each credential type (new_vmc,new_vrc,new_vic,new_vpc,new_vec,new_vwc;new_rcarddeprecated)
Usage
// Create a Persona Credential
let credential = DTGCredential::new_vpc(issuer_did, subject_did, valid_from, valid_until);
// Sign it
credential.sign(&secret, None).await?;
// Verify it
credential.verify_proof_with_public_key(&public_key)?;The library supports both W3C VC 1.1 and 2.0, handling field name differences (issuanceDate/validFrom, expirationDate/validUntil) transparently via serde deserialization.
Dependencies
affinidi-data-integrity— W3C Data Integrity proof creation/verification (EdDSA JCS 2022)affinidi-secrets-resolver— key managementserde— JSON serialization with camelCase and untagged enum dispatchserde_json_canonicalizer(JCS / RFC 8785),sha2,multibase— VWC digest computation (since 0.2.0)
Provenance
Originally developed under LF-Decentralized-Trust-labs, migrated to the OpenVTC GitHub organization in spring 2026. Published on crates.io since 0.1.1 (2026-03-29; 0.1.0 was never published). MSRV 1.95.
Recent Development
After a quiet spring, the crate made its first semantic move in August 2026: 0.2.0 tracks the spec’s v1.0 Working Draft 01 (see dtg-credential-spec) — and in doing so fixed a live interoperability bug. It is part of the coordinated Cypress release (coordinated-releases; the Cypress and VTI-Cypress-RC-1 tags both point at the 0.2.0 HEAD; Banyan = RC-0 = 0.1.3). The VTI (#916) and openvtc (#205) moved onto 0.2 the same day — VMC/VEC/VIC bytes are unchanged, so the bump was painless for them.
v0.2.0 — 2026-08-10 — track DTG Core Credentials WD01 (#8, feat!; release notes #9)
taskContextadded toDTGCommon(+ accessors). This was a real bug, not just a schema catch-up:DTGCommonlacked the field and had nodeny_unknown_fields, so serde silently droppedtaskContexton deserialise — and becausesign()serialises the credential, issuers signed a document missing the field while verifiers hashed a different document than the one that was signed.- BREAKING:
new_vwc(issuer, subject, valid_from, valid_until, task_context: String, digest: Option<String>, witness_context); deserialising aWitnessCredentialwithouttaskContextfails with the newDTGCredentialError::MissingTaskContext; newCanonicalization(String)error. - New VWC digest helpers
digest_multibase()/verify_digest()— the digest covers the referenced VRC exactly as it stands, including itsproof, over its JCS canonical form. DTGCredentialType::RCard,CredentialSubject::RCard,CredentialSubjectRCardandnew_rcard()deprecated (not removed) — the relationship card left the spec for a planned VDS companion.- ⚠ VWC digest divergence (flagged in the README/CHANGELOG, unresolved). WD01 says the digest MUST be encoded as
sha256:+ lowercase hex; the crate encodes it as a multibase base58btc multihash (z…), following the W3CdigestMultibaseconvention. Same SHA-256 over the same JCS bytes — only the string encoding differs — but string comparison fails both ways, soverify_digest()rejects spec-conformant VWCs and conformant verifiers reject crate-produced ones. To be raised with the DTGWG. A second, undeclared gap: the crate still treatsdigestasOption(written against the PR #7 state); spec PR #14 two days later made it REQUIRED, so a VWC built withdigest: Noneis now non-conformant. - History reconstructed: 0.1.2 and 0.1.3 had been published but never recorded; the async
sign()change actually shipped in 0.1.1 (2026-03-29); placeholder dates replaced with crates.io dates; four rustdoc bare-URL warnings fixed.
v0.1.3 — 2026-06-07 — data-integrity 0.7 / TDK 0.7
affinidi-data-integrity0.6 → 0.7affinidi-tdk0.6 → 0.7 (dev-dep)sign_and_verifyexample migrated to the new TDK config builder (TDKConfigBuilder::new()→TDKConfig::builder())- MSRV bumped to 1.95.0
v0.1.2 — 2026-04-30
- Bumped to
affinidi-data-integrity0.6 and migrated to its new API - CODEOWNERS for
@OpenVTC/openvtc-maintainers
v0.1.1 and earlier — 2026-04 and prior
- Dependency updates:
affinidi-data-integrity0.4 → 0.5,affinidi-tdk0.5 → 0.6 sign()made async to align with upstream changes- Repository URL migration from LF-Decentralized-Trust-labs to OpenVTC
- Crate publishing enablement
See also: dtg-credentials-overview, decentralized-trust-graph, verifiable-credentials