pdtf-core (Rust)
Native Rust implementation of the PDTF 2.0 core library. Designed for performance-critical workloads and as the foundation for cross-language bindings.
[dependencies]pdtf-core = { git = "https://github.com/property-data-standards-co/core-rs" }Repository: property-data-standards-co/core-rs
Architecture
Section titled “Architecture”core-rs/├── crates/pdtf-core/ # Core Rust library│ ├── src/│ │ ├── keys/ # Ed25519 key generation, did:key encoding│ │ ├── signer/ # DataIntegrityProof creation (eddsa-jcs-2022)│ │ ├── validator/ # Proof verification│ │ ├── did/ # DID resolution (did:key, did:web, URN)│ │ ├── status/ # Bitstring Status List│ │ └── tir/ # Trusted Issuer Registry client│ └── tests/│ └── cross_language.rs # Shared vector validation├── bindings/│ ├── python/ # PyO3 bindings│ ├── dotnet-ffi/ # C-ABI FFI layer│ └── dotnet/ # C# wrapper + tests└── test-vectors/ └── vectors.json # Shared cross-language test vectorsModules
Section titled “Modules”keys::ed25519
Section titled “keys::ed25519”Ed25519 key generation, did:key derivation, and multibase encoding.
use pdtf_core::keys::ed25519::{generate_keypair, derive_did_key, public_key_to_multibase};
let kp = generate_keypair();let did = derive_did_key(kp.verifying_key.as_bytes())?;// did:key:z6Mk...
let multibase = public_key_to_multibase(kp.verifying_key.as_bytes())?;// z6Mk...
// Round-triplet recovered = did_key_to_public_key(&did)?;assert_eq!(recovered.as_slice(), kp.verifying_key.as_bytes());signer::proof
Section titled “signer::proof”Create and verify DataIntegrityProof using eddsa-jcs-2022.
use pdtf_core::signer::proof::{create_proof, verify_proof, CreateProofOptions};
// Signlet proof = create_proof(CreateProofOptions { document: &vc, key_id: "my-key", verification_method: "did:key:z6Mk...#z6Mk...", key_provider: &my_key_provider, created: None, // defaults to now}).await?;
// Verifylet valid = verify_proof(&signed_vc, &public_key_bytes);Algorithm (identical to TypeScript):
- JCS-canonicalize proof options → SHA-256
- JCS-canonicalize document (no proof) → SHA-256
- Concatenate hashes (64 bytes)
- Ed25519 sign (raw bytes)
- base58-btc encode with
zprefix
DID resolution for did:key, did:web, and urn:pdtf:*.
use pdtf_core::did::resolver::resolve;
let doc = resolve("did:key:z6Mk...").await?;let doc = resolve("did:web:example.com:transactions:abc123").await?;status::bitstring
Section titled “status::bitstring”Bitstring Status List — create, encode (gzip+base64), decode, and check bits.
use pdtf_core::status::bitstring::*;
let mut list = create_status_list(131_072)?;set_bit(&mut list, 42)?;
let encoded = encode_status_list(&list)?; // base64(gzip(bytes))let decoded = decode_status_list(&encoded)?;assert!(get_bit(&decoded, 42)?);Trusted Issuer Registry — load, validate issuer entries, path matching.
use pdtf_core::tir::verify::verify_tir;use pdtf_core::tir::path_match::path_matches;
// Path matchingassert!(path_matches("Property:/energyEfficiency/*", "Property:/energyEfficiency/certificate"));assert!(!path_matches("Property:*", "Title:/registerExtract/entries"));
// Full TIR verificationlet result = verify_tir(®istry, "did:key:z6Mk...", &["Property:/energyEfficiency/certificate"]);assert!(result.trusted);84 tests across the workspace:
| Crate | Tests | Coverage |
|---|---|---|
| pdtf-core (unit) | 67 | Keys, signing, verification, DID, status, TIR, structure validation |
| pdtf-core (integration) | 6 | Cross-language vector validation against TypeScript |
| dotnet-ffi | 8 | FFI function correctness, error handling |
| doc-tests | 3 | Inline documentation examples |
cargo test --workspaceCross-Language Interop
Section titled “Cross-Language Interop”The Rust tests consume test-vectors/vectors.json generated by the TypeScript reference implementation using a fixed Ed25519 seed. This proves byte-level interoperability:
| Test | What’s proven |
|---|---|
crosslang_key_derivation | Identical did:key and multibase encoding |
crosslang_signing_produces_identical_proofs | Same JCS + SHA-256 + Ed25519 = identical proof values |
crosslang_verification | Rust verifies TypeScript-signed VCs (valid, tampered, wrong key) |
crosslang_status_list_empty_roundtrip | Decoded status lists are byte-identical |
crosslang_status_list_operations | Set/check operations produce same results |
crosslang_tir_path_matching | Wildcard pattern matching is consistent |
Note: Gzip implementations may produce different compressed byte sequences, so status list tests compare decoded (logical) content rather than raw base64 strings.