ma-did
A Rust implementation of the
間 (did:ma) DID method
— a modern, lean decentralized identifier method providing
secure identities as a foundation for secure messaging.
What It Provides
- DID parsing and validation —
did:ma:<ipns>with optional#fragmentfor sub-identities within a namespace - DID documents —
Document,VerificationMethod, andProoftypes conforming to W3C DID v1.1 - Cryptographic key types —
Ed25519 signing keys (
SigningKey) and X25519 encryption keys (EncryptionKey) withMultikeyencoding - Multiformat pipeline — multibase (Base58btc) + multicodec encoding/decoding for public keys and signatures
- Identity generation —
one-call
generate_identity()orgenerate_identity_from_secret()produces keys, verification methods, and a signed document - Document proofs —
MultiformatSignature2023proof type (BLAKE3 + Ed25519 over CBOR) - Signed messages —
Messagewith BLAKE3 content hashing, Ed25519 signature, TTL, and replay-window freshness checks - Encrypted envelopes —
Envelopeusing ephemeral X25519 key agreement with XChaCha20-Poly1305 AEAD - Serialization —
JSON (
marshal/unmarshal) and CBOR (to_cbor/from_cbor) for both documents and messages - Method-specific extension —
optional
manamespace on documents for application-defined fields - WASM support —
compiles to
wasm32-unknown-unknownwith JS time sources
Specification
This crate implements the formal did:ma method
specification documents at
bahner/ma-spec:
- DID Method Specification — method syntax, CRUD operations, verifiable data registry
- DID Document Format —
document structure,
Multikeyverification methods, proof type - Extension Fields Format —
method-specific
manamespace - Messaging Format — signed CBOR messages, encryption envelopes, replay protection
References
- W3C DID Core v1.1 — Decentralized Identifiers specification
- Nano ID —
DID URL fragment generation and validation
(
[A-Za-z0-9_-]+) - Multibase / Multicodec — key and signature encoding
- BLAKE3 — content hashing for proofs and messages
- IPNS — DID method-specific identifier
Project Layout
src/constants.rs: method name, version, BLAKE3 labelssrc/did.rs: DID model and validationsrc/doc.rs: DID document, proof, and verification method modelsrc/error.rs: crate error typessrc/identity.rs: key + document generation helpersrc/key.rs: key generation, multibase encoding, Ed25519/X25519 key typessrc/lib.rs: public exportssrc/msg.rs: message, headers, envelope, and replay guardsrc/multiformat.rs: multibase/multicodec encoding and decoding pipeline
Build
Usage
[]
= "0.5"
Release Notes
0.5.0
- Improved API safety with
#[must_use]on commonly dropped return values. - Fixed message timestamp tests and aligned examples with current behavior.
- Internal multiformat encoding cleanup for clearer error boundaries.
Migration Notes (0.4 -> 0.5)
- If your project uses
-D warnings, new#[must_use]attributes may surface ignored-result warnings. Update call sites to use, store, or explicitly discard return values as needed. - Public crate API remains source-compatible for normal
ma_didusage. Themultiformatmodule is internal (mod multiformat) and not exported from crate root.
Identity and documents
use ;
// Generate a complete identity from an application-managed secret
let secret = ;
let identity = generate_identity_from_secret.unwrap;
// The document is already signed and valid
identity.document.verify.unwrap;
identity.document.validate.unwrap;
// Serialize to JSON or CBOR
let json = identity.document.marshal.unwrap;
let cbor = identity.document.to_cbor.unwrap;
If you already have an IPNS identifier from elsewhere, you can still call
generate_identity(ipns) directly as the explicit lower-level path. If not,
let the application supply the secret and use
generate_identity_from_secret(secret) to derive it.
DID validation
use Did;
// Validate any DID (bare or URL)
validate.unwrap;
validate.unwrap;
// Validate specifically a bare DID identity (no fragment)
validate_identity.unwrap;
// Validate specifically a DID URL (requires fragment)
validate_url.unwrap;
Messages
use ;
let alice = generate_identity_from_secret.unwrap;
let bob = generate_identity_from_secret.unwrap;
// Reconstruct signing key from stored private key bytes
let alice_sign_url = new_url.unwrap;
let alice_signing_key = from_private_key_bytes.unwrap;
// Create a signed message
let msg = new.unwrap;
// Verify message signature against sender's document
msg.verify_with_document.unwrap;
// Encrypt for recipient as an Envelope
let envelope = msg.enclose_for.unwrap;
License
GPL-3.0-only