oxirs-did 0.1.0-rc.2

W3C DID and Verifiable Credentials implementation with Signed RDF Graphs for OxiRS
Documentation

oxirs-did

W3C DID and Verifiable Credentials implementation with Signed RDF Graphs

Crates.io docs.rs

Full implementation of W3C Decentralized Identifiers (DID) and Verifiable Credentials (VC) specifications, with support for cryptographically signed RDF graphs.

Features

  • DID Core 1.0: W3C Recommendation compliant
  • VC Data Model 2.0: Verifiable Credentials with Ed25519 proofs
  • did:key: Deterministic DIDs from public keys (no network)
  • did:web: HTTPS-based DID resolution (optional)
  • RDFC-1.0: RDF Dataset Canonicalization for graph signing
  • Ed25519Signature2020: Cryptographic proof suite

Standards Compliance

Quick Start

DID Creation and Resolution

use oxirs_did::{Did, DidResolver};
use oxirs_did::proof::ed25519::Ed25519Signer;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Generate Ed25519 keypair
    let signer = Ed25519Signer::generate();
    let public_key = signer.public_key_bytes();

    // Create did:key from public key
    let did = Did::new_key_ed25519(&public_key)?;
    println!("DID: {}", did);
    // Output: did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK

    // Resolve DID to DID Document
    let resolver = DidResolver::new();
    let doc = resolver.resolve(&did).await?;

    println!("DID Document: {}", serde_json::to_string_pretty(&doc)?);

    Ok(())
}

Issue Verifiable Credential

use oxirs_did::{Did, VerifiableCredential, VcIssuer};
use oxirs_did::proof::ed25519::Ed25519Signer;
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Issuer identity
    let issuer_signer = Ed25519Signer::generate();
    let issuer_did = Did::new_key_ed25519(&issuer_signer.public_key_bytes())?;

    // Create credential
    let mut vc = VerifiableCredential::new(
        issuer_did.clone(),
        json!({
            "id": "did:key:z6Mk...",
            "email": "alice@example.com",
            "role": "Researcher"
        }),
    )
    .with_type("EmailCredential")
    .with_expiration_days(365);

    // Issue (sign) the credential
    let issuer = VcIssuer::new(issuer_signer);
    issuer.issue(&mut vc, None).await?;

    println!("{}", serde_json::to_string_pretty(&vc)?);

    Ok(())
}

Verify Credential

use oxirs_did::{DidResolver, VcVerifier, VerifiableCredential};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let resolver = DidResolver::new();
    let verifier = VcVerifier::new(resolver);

    // Parse VC from JSON
    let vc: VerifiableCredential = serde_json::from_str(vc_json)?;

    // Verify
    let result = verifier.verify(&vc).await?;

    if result.valid {
        println!("✓ Credential is VALID");
        println!("  Issued by: {}", result.issuer.unwrap());
    } else {
        println!("✗ Credential is INVALID");
        for error in &result.errors {
            println!("  - {}", error);
        }
    }

    Ok(())
}

Sign RDF Graph

use oxirs_did::signed_graph::{SignedGraph, RdfTriple};
use oxirs_did::proof::ed25519::Ed25519Signer;
use oxirs_did::{Did, DidResolver};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create signer
    let signer = Ed25519Signer::generate();
    let did = Did::new_key_ed25519(&signer.public_key_bytes())?;

    // Create RDF graph
    let triples = vec![
        RdfTriple::iri(
            "http://data.example/entity-1",
            "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
            "http://schema.org/Dataset"
        ),
    ];

    // Sign graph
    let graph = SignedGraph::new(
        "http://data.example/research-2025",
        triples,
        did.clone()
    );
    let signed = graph.sign(&signer)?;

    println!("Graph hash: {}", signed.hash()?);

    // Verify later
    let resolver = DidResolver::new();
    let valid = signed.verify(&resolver).await?;
    println!("Verification: {}", if valid.valid { "" } else { "" });

    Ok(())
}

DID Methods

did:key (Default)

No network required, deterministic from public key:

did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
         └─ Base58btc(0xed01 + Ed25519_public_key)

did:web (Optional, feature = "did-web")

HTTPS-based resolution:

did:web:example.com
→ https://example.com/.well-known/did.json

did:web:example.com:users:alice
→ https://example.com/users/alice/did.json

did:web:example.com%3A8080
→ https://example.com:8080/.well-known/did.json

Feature Flags

[dependencies]
oxirs-did = { version = "0.1", features = ["did-web", "signed-graphs"] }

Available features:

  • did-key (default) - did:key method
  • did-web - did:web method (requires reqwest)
  • did-ebsi - European Blockchain Services Infrastructure
  • vc-data-model-2 (default) - W3C VC 2.0
  • signed-graphs - RDF graph signing/verification
  • key-management - Key storage

Use Cases

  • Trustworthy AI: Sign training datasets for provenance tracking
  • IoT Identity: Decentralized identity for edge devices
  • Supply Chain: Verifiable product certifications
  • Research Data: Signed datasets for reproducibility
  • Federated Systems: Self-sovereign identity across systems

Dependencies

  • ed25519-dalek - Ed25519 signatures
  • multibase, bs58 - Multiformat encoding
  • sha2 - Cryptographic hashing
  • scirs2-core - Secure random number generation

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.