Skip to content
Proposed specification for review. We are seeking feedback on key architectural choices in the industry consultation.

03 DID Methods & Identifiers

Version: 0.1 (Draft) Date: 1 April 2026 Author: Ed Molyneux Status: Draft Parent: 00 — Architecture Overview


This sub-specification defines the decentralised identifier (DID) system and URN naming scheme used throughout PDTF 2.0. It replaces the opaque platform-specific identifiers (Firebase Auth UIDs, Firestore document IDs) of PDTF v1 with cryptographically verifiable, standards-based identifiers that enable:

  • Portable identity — a person’s DID works across any PDTF-compliant platform, not just the one that created their account.
  • Verifiable provenance — every Verifiable Credential links back to an issuer DID whose keys can be independently resolved and verified.
  • Machine-readable discovery — a transaction’s DID document tells any agent where to find the PDTF API and MCP endpoint, without out-of-band configuration.
  • Entity addressability — every property, title, ownership claim, and representation mandate has a stable, globally unique identifier.

This spec covers:

  • DID method selection and rationale (decisions D7, D26)
  • URN scheme for non-DID entities (decision D23)
  • DID document structure for each entity type
  • Verification methods and key encoding
  • Service endpoint types
  • DID resolution procedures
  • Identifier lifecycle (creation, rotation, deactivation)
  • Security considerations

It does not cover:

ReferenceURL
W3C DID Core v1.0https://www.w3.org/TR/did-core/
W3C did:key Methodhttps://w3c-ccg.github.io/did-method-key/
W3C did:web Methodhttps://w3c-ccg.github.io/did-method-web/
Multibasehttps://www.w3.org/TR/controller-document/#multibase-0
Multicodechttps://github.com/multiformats/multicodec
Ed25519 (RFC 8032)https://www.rfc-editor.org/rfc/rfc8032
URN Syntax (RFC 8141)https://www.rfc-editor.org/rfc/rfc8141
ABNF (RFC 5234)https://www.rfc-editor.org/rfc/rfc5234
IDDecisionRationale
D7did:key for Persons; did:key or did:web for Organisations; did:web for Transactions and Trusted AdaptersPersons need zero-infrastructure identifiers derived from their signing keys. Organisations may use provider-managed did:key (the common case — issued by their case management platform) or self-hosted did:web (for firms wanting direct control). Transactions and adapters need discoverable service endpoints that did:web provides.
D23urn:pdtf:unregisteredTitle:{uuid} for unregistered titlesUnregistered land has no HMLR title number. A PDTF-minted UUID provides a stable identifier until first registration completes. Open: confirm UUID version and whether the URN should survive first registration.
D26did:key (provider-managed) or did:web (self-hosted) for OrganisationsMost organisations will use provider-managed did:key identifiers issued by their account provider (e.g. LMS). The provider verifies the organisation’s identity and regulatory status. Self-hosted did:web at the firm’s domain is available for firms wanting direct control.

Specification: W3C did:key Method

did:key encodes a public key directly into the DID string. The DID document is implicit — it can be deterministically derived from the DID itself without any network request. This makes did:key ideal for individual persons who need:

  • No infrastructure to maintain
  • Instant key-pair generation (client-side, offline)
  • Self-certifying identifiers — the DID is the public key

PDTF 2.0 uses Ed25519 keys exclusively (RFC 8032). Ed25519 provides:

  • 128-bit security level
  • Fast signing and verification
  • Small key and signature sizes (32-byte keys, 64-byte signatures)
  • Deterministic signatures (no random nonce required)
  • Wide library support across all platforms

The did:key identifier is derived from an Ed25519 public key through the following steps:

1. Generate an Ed25519 key pair → public key (32 bytes)
2. Prepend the multicodec prefix for Ed25519 public key: 0xed01 (2 bytes)
3. Encode the result with multibase using base58-btc (prefix 'z')
4. Prepend "did:key:" to form the DID

Worked example:

Raw Ed25519 public key (32 bytes, hex):
d7 5a 98 18 2b 10 ab 7d 54 bf eb 3c 11 63 04 3c
2b 7d 1a 31 03 66 c8 b4 05 e7 a8 43 4b 3a e1 41
With multicodec prefix (0xed 0x01):
ed 01 d7 5a 98 18 2b 10 ab 7d 54 bf eb 3c 11 63
04 3c 2b 7d 1a 31 03 66 c8 b4 05 e7 a8 43 4b 3a
e1 41
Base58-btc encoded (with 'z' prefix):
z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
Final DID:
did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK

Note: All did:key identifiers for Ed25519 keys begin with z6Mk. This prefix is deterministic: z is the multibase base58-btc prefix, and 6Mk is the base58-btc encoding of the 0xed01 multicodec header. If a DID starts with did:key:z6Mk, you know it’s an Ed25519 key.

Use caseDID method
Individual person (seller, buyer)did:key ✓
VC issuer who is a natural persondid:key ✓
Organisation managed by an account providerdid:key ✓ (the common case)
Any entity needing service endpointsdid:web (not did:key)

2.2 did:web — Organisations, Transactions, and Trusted Adapters

Section titled “2.2 did:web — Organisations, Transactions, and Trusted Adapters”

Specification: W3C did:web Method

did:web uses existing web infrastructure (DNS + HTTPS) to host DID documents. The DID encodes a URL path where the DID document can be fetched as a JSON file. This provides:

  • Discoverability — service endpoints (APIs, MCP servers) are embedded in the DID document
  • Domain verification — hosting the DID document at a domain proves control of that domain
  • Key rotation — keys can be updated by republishing the DID document
  • Rich metadata — DID documents can include regulatory identifiers, service descriptions, and linked resources

The did:web method maps DID identifiers to HTTPS URLs using these rules:

did:web:{domain}
→ https://{domain}/.well-known/did.json
did:web:{domain}:{path1}:{path2}
→ https://{domain}/{path1}/{path2}/did.json
Percent-encoded characters:
did:web:{domain}%3A{port}:{path}
→ https://{domain}:{port}/{path}/did.json

PDTF examples:

DIDResolves to
did:web:smithandjones.co.ukhttps://smithandjones.co.uk/.well-known/did.json
did:web:platform.example.com:transactions:abc123https://platform.example.com/transactions/abc123/did.json
did:web:adapters.propdata.org.uk:hmlrhttps://adapters.propdata.org.uk/hmlr/did.json
did:web:adapters.propdata.org.uk:epchttps://adapters.propdata.org.uk/epc/did.json
Entity typeDID patternExampleHosted by
Organisation (provider-managed)did:key:z6Mk{base58}did:key:z6MkpJmq...Implicit (no hosting — key managed by account provider)
Organisation (self-hosted)did:web:{firm-domain}did:web:smithandjones.co.ukThe firm itself
Transactiondid:web:{platform}:transactions:{id}did:web:platform.example.com:transactions:abc123The platform hosting the transaction
Trusted Adapterdid:web:{adapter-host}:{adapter-name}did:web:adapters.propdata.org.uk:hmlrThe adapter operator

Hosting a DID document at a domain constitutes proof of domain control. This has implications:

  • Organisations (did:web): A conveyancer firm at did:web:smithandjones.co.uk has proven they control the smithandjones.co.uk domain. Combined with a regulated-conveyancer Trust Mark (which cross-references SRA number and Companies House number), this provides a strong identity binding.
  • Organisations (did:key): A provider-managed Organisation’s identity is verified by the account provider. Verifiers confirm the did:key is listed in the provider’s managedOrganisations document (referenced from the account provider’s account-provider Trust Mark).
  • Transactions: A transaction DID like did:web:platform.example.com:transactions:abc123 is inherently scoped to the platform hosting it. The platform’s Entity Statement in the federation establishes its authority to host transactions.
  • Adapters: An adapter at did:web:adapters.propdata.org.uk:hmlr is controlled by whoever operates the adapters.propdata.org.uk domain. A pdtf-verified-issuer Trust Mark binds this to an authorised adapter operator.

Security note: did:web security depends entirely on DNS and TLS. See Section 9: Security Considerations for threat analysis and mitigations.


Entities that are not actors (they don’t sign credentials or authenticate) use URN identifiers in the urn:pdtf namespace. These entities are subjects of credentials, not issuers.

NID: pdtf
Registration: Informal (property-data-standards-co governance)
Registrant: Property Data Standards Company
URN PatternEntitySource of Identifier
urn:pdtf:uprn:{uprn}PropertyOrdnance Survey UPRN (Unique Property Reference Number)
urn:pdtf:titleNumber:{number}Title (registered)HMLR title number
urn:pdtf:unregisteredTitle:{uuid}Title (unregistered)Platform-generated UUID v4 (D23)
urn:pdtf:capacity:{uuid}SellerCapacityPlatform-generated UUID v4
urn:pdtf:offer:{uuid}OfferPlatform-generated UUID v4
urn:pdtf:gift:{uuid}GiftPlatform-generated UUID v4
urn:pdtf:representation:{uuid}RepresentationPlatform-generated UUID v4
urn:pdtf:role:{uuid}TransactionRolePlatform-generated UUID v4

The following ABNF grammar (per RFC 5234) defines the syntax for each URN type:

; Top-level PDTF URN
pdtf-urn = "urn:pdtf:" pdtf-nss
pdtf-nss = property-urn
/ title-urn
/ unregistered-title-urn
/ capacity-urn
/ offer-urn
/ gift-urn
/ representation-urn
/ role-urn
; Property — UPRN is a numeric identifier (up to 12 digits)
property-urn = "uprn:" uprn
uprn = 1*12DIGIT
; Title — HMLR title number format (e.g., "DN123456", "AGL12345", "WA123456")
title-urn = "titleNumber:" title-number
title-number = district-prefix 1*8DIGIT
district-prefix = 1*4ALPHA
; Unregistered Title — UUID v4 (D23)
unregistered-title-urn = "unregisteredTitle:" uuid-v4
; SellerCapacity — UUID v4
capacity-urn = "capacity:" uuid-v4
; Offer — UUID v4
offer-urn = "offer:" uuid-v4
; Gift — UUID v4
gift-urn = "gift:" uuid-v4
; Representation — UUID v4
representation-urn = "representation:" uuid-v4
; TransactionRole — UUID v4
role-urn = "role:" uuid-v4
; UUID v4 (RFC 4122 format)
uuid-v4 = 8hexdig "-" 4hexdig "-" "4" 3hexdig "-"
variant-char 3hexdig "-" 12hexdig
variant-char = "8" / "9" / "a" / "b"
/ "A" / "B"
hexdig = DIGIT / "a" / "b" / "c" / "d" / "e" / "f"
/ "A" / "B" / "C" / "D" / "E" / "F"
; Imported from RFC 5234
DIGIT = %x30-39 ; 0-9
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
urn:pdtf:uprn:100023456789
urn:pdtf:titleNumber:DN123456
urn:pdtf:titleNumber:AGL12345
urn:pdtf:unregisteredTitle:f47ac10b-58cc-4372-a567-0e02b2c3d479
urn:pdtf:capacity:7c9e6679-7425-40de-944b-e07fc1f90ae7
urn:pdtf:offer:c3d4e5f6-a7b8-4c9d-0e1f-2a3b4c5d6e7f
urn:pdtf:gift:b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e
urn:pdtf:representation:a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d
urn:pdtf:role:d4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f8a

The boundary is clear: actors get DIDs, subjects get URNs.

Has signing keys?Has service endpoints?Identifier type
YesNodid:key
YesYesdid:web
NoNourn:pdtf:*
  • Persons sign credentials → did:key
  • Organisations sign credentials → did:key (provider-managed, common case) or did:web (self-hosted, with service endpoints)
  • Transactions host endpoints (PDTF API, MCP) → did:web
  • Properties are credential subjects, never issuers → urn:pdtf:uprn:*
  • Titles are credential subjects → urn:pdtf:titleNumber:*
  • SellerCapacity, Offer, Gift, Representation, TransactionRole are credential subjects → urn:pdtf:{type}:{uuid}

did:key DID documents are implicit — they are deterministically derived from the DID string itself. No hosting is required. The resolved form is shown below for reference.

For did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK:

{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/ed25519-2020/v1",
"https://w3id.org/security/multikey/v1"
],
"id": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"verificationMethod": [
{
"id": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"type": "Ed25519VerificationKey2020",
"controller": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"publicKeyMultibase": "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
}
],
"authentication": [
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
],
"assertionMethod": [
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
],
"capabilityDelegation": [
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
],
"capabilityInvocation": [
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
]
}

Note: The verificationMethod.id fragment is the full multibase-encoded public key. This is the canonical form per the did:key specification. The same key serves all verification relationships (authentication, assertion, delegation, invocation) because a Person’s DID has exactly one key.

Organisations may use either did:key (provider-managed) or did:web (self-hosted). When managed by an account provider, an Organisation receives a did:key identifier generated by the provider. The provider verifies the organisation’s identity (SRA number, Companies House registration, etc.) before issuing the DID. The provider’s account-provider Trust Mark includes (via the delegation.managed_organisations URL) a signed document listing the organisation’s DID, enabling verifiers to trace the did:key back to a trusted source. This is expected to be the dominant model — most conveyancer firms and estate agencies will not self-host did:web infrastructure.

4.2.1 Organisation DID Document — Provider-Managed (did:key)

Section titled “4.2.1 Organisation DID Document — Provider-Managed (did:key)”

For a conveyancer firm Smith & Jones LLP managed by LMS, the Organisation receives a did:key identifier. Like Person did:key documents, the DID document is implicit — deterministically derived from the key with no hosting required:

{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/ed25519-2020/v1",
"https://w3id.org/security/multikey/v1"
],
"id": "did:key:z6MkpJmqLFMmaFHCqS9jVjMNRNHriSNkFCyG3MLbiqkVMhvm",
"verificationMethod": [
{
"id": "did:key:z6MkpJmqLFMmaFHCqS9jVjMNRNHriSNkFCyG3MLbiqkVMhvm#z6MkpJmqLFMmaFHCqS9jVjMNRNHriSNkFCyG3MLbiqkVMhvm",
"type": "Ed25519VerificationKey2020",
"controller": "did:key:z6MkpJmqLFMmaFHCqS9jVjMNRNHriSNkFCyG3MLbiqkVMhvm",
"publicKeyMultibase": "z6MkpJmqLFMmaFHCqS9jVjMNRNHriSNkFCyG3MLbiqkVMhvm"
}
],
"authentication": [
"did:key:z6MkpJmqLFMmaFHCqS9jVjMNRNHriSNkFCyG3MLbiqkVMhvm#z6MkpJmqLFMmaFHCqS9jVjMNRNHriSNkFCyG3MLbiqkVMhvm"
],
"assertionMethod": [
"did:key:z6MkpJmqLFMmaFHCqS9jVjMNRNHriSNkFCyG3MLbiqkVMhvm#z6MkpJmqLFMmaFHCqS9jVjMNRNHriSNkFCyG3MLbiqkVMhvm"
]
}

Key points:

  • No service endpoints — the Organisation’s regulatory registrations and contact details live in the entity graph (Organisation entity), not in the DID document.
  • The account provider (e.g. LMS) manages the key material on behalf of the Organisation.
  • Verifiers trace this did:key back to a trusted provider via the account-provider Trust Mark’s delegation.managed_organisations document.
  • The Organisation’s identity (SRA number, Companies House registration) is verified by the account provider before the DID is issued.

4.2.2 Organisation DID Document — Self-Hosted (did:web)

Section titled “4.2.2 Organisation DID Document — Self-Hosted (did:web)”

For firms that want direct control of their identity, hosted at the firm’s domain. For a conveyancer firm Smith & Jones LLP at did:web:smithandjones.co.uk, the DID document is served from https://smithandjones.co.uk/.well-known/did.json:

{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/ed25519-2020/v1",
"https://w3id.org/security/multikey/v1"
],
"id": "did:web:smithandjones.co.uk",
"verificationMethod": [
{
"id": "did:web:smithandjones.co.uk#key-1",
"type": "Ed25519VerificationKey2020",
"controller": "did:web:smithandjones.co.uk",
"publicKeyMultibase": "z6Mkr7JAFsC4K5Zmq3RqtEZjTNz9e3o8yBPyqGMpKVqZv2R"
}
],
"authentication": [
"did:web:smithandjones.co.uk#key-1"
],
"assertionMethod": [
"did:web:smithandjones.co.uk#key-1"
],
"service": [
{
"id": "did:web:smithandjones.co.uk#sra",
"type": "RegulatoryRegistration",
"serviceEndpoint": "https://www.sra.org.uk/solicitors/firm/612345",
"name": "SRA Registration",
"registrationNumber": "612345"
},
{
"id": "did:web:smithandjones.co.uk#companies-house",
"type": "CompanyRegistration",
"serviceEndpoint": "https://find-and-update.company-information.service.gov.uk/company/OC123456",
"name": "Companies House",
"companyNumber": "OC123456"
},
{
"id": "did:web:smithandjones.co.uk#pdtf-contact",
"type": "PdtfOrganisationEndpoint",
"serviceEndpoint": "https://portal.smithandjones.co.uk/pdtf",
"description": "PDTF credential exchange endpoint"
}
]
}

Key points:

  • The #sra and #companies-house service endpoints provide machine-readable links to regulatory registrations. The Trust Anchor cross-references these when issuing the Organisation’s Trust Mark.
  • assertionMethod is included because Organisations may issue credentials (e.g., a conveyancer firm issuing a Representation credential confirmation).
  • The firm controls key rotation by updating the DID document at their domain.

Hosted by the platform at the transaction’s path. For did:web:platform.example.com:transactions:abc123, served from https://platform.example.com/transactions/abc123/did.json:

{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/ed25519-2020/v1",
"https://w3id.org/security/multikey/v1"
],
"id": "did:web:platform.example.com:transactions:abc123",
"controller": "did:web:platform.example.com",
"verificationMethod": [
{
"id": "did:web:platform.example.com:transactions:abc123#key-1",
"type": "Ed25519VerificationKey2020",
"controller": "did:web:platform.example.com:transactions:abc123",
"publicKeyMultibase": "z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp7eTbCt2DADLY"
}
],
"authentication": [
"did:web:platform.example.com:transactions:abc123#key-1"
],
"assertionMethod": [
"did:web:platform.example.com:transactions:abc123#key-1"
],
"service": [
{
"id": "did:web:platform.example.com:transactions:abc123#pdtf-api",
"type": "PdtfTransactionEndpoint",
"serviceEndpoint": "https://api.platform.example.com/v2/transactions/abc123",
"description": "PDTF v2 transaction API — credential submission, state retrieval, entity queries"
},
{
"id": "did:web:platform.example.com:transactions:abc123#mcp",
"type": "McpEndpoint",
"serviceEndpoint": "https://api.platform.example.com/mcp/transactions/abc123",
"description": "Model Context Protocol endpoint for AI agent access"
}
],
"alsoKnownAs": [
"urn:pdtf:uprn:100023456789"
]
}

Key points:

  • The controller field indicates did:web:platform.example.com controls this transaction DID. This establishes the platform’s authority over the transaction.
  • #pdtf-api is the primary API endpoint for credential exchange and state retrieval.
  • #mcp provides the MCP (Model Context Protocol) endpoint for AI agent interaction.
  • alsoKnownAs links to the property UPRN for cross-referencing. Multiple URNs may be listed when a transaction involves multiple properties.

4.4 Trusted Adapter DID Document (did:web)

Section titled “4.4 Trusted Adapter DID Document (did:web)”

For the HMLR Official Copies adapter at did:web:adapters.propdata.org.uk:hmlr, served from https://adapters.propdata.org.uk/hmlr/did.json:

{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/ed25519-2020/v1",
"https://w3id.org/security/multikey/v1"
],
"id": "did:web:adapters.propdata.org.uk:hmlr",
"controller": "did:web:adapters.propdata.org.uk",
"verificationMethod": [
{
"id": "did:web:adapters.propdata.org.uk:hmlr#key-1",
"type": "Ed25519VerificationKey2020",
"controller": "did:web:adapters.propdata.org.uk:hmlr",
"publicKeyMultibase": "z6MkpTHR8VNs5xhqAKbSQgpzGRwXaN7cPsMjczbEPceFRFw8"
},
{
"id": "did:web:adapters.propdata.org.uk:hmlr#key-2",
"type": "Ed25519VerificationKey2020",
"controller": "did:web:adapters.propdata.org.uk:hmlr",
"publicKeyMultibase": "z6MkvZm1eJ9hRYdPB4q7SBLW9XprJPVt2Bv4c4f6kJfQxrKn"
}
],
"authentication": [
"did:web:adapters.propdata.org.uk:hmlr#key-1"
],
"assertionMethod": [
"did:web:adapters.propdata.org.uk:hmlr#key-1",
"did:web:adapters.propdata.org.uk:hmlr#key-2"
],
"service": [
{
"id": "did:web:adapters.propdata.org.uk:hmlr#vc-issuance",
"type": "VcIssuanceEndpoint",
"serviceEndpoint": "https://adapters.propdata.org.uk/hmlr/credentials/issue",
"description": "Request HMLR Official Copies as Verifiable Credentials",
"credentialTypes": [
"TitleCredential",
"SellerCapacityCredential"
]
},
{
"id": "did:web:adapters.propdata.org.uk:hmlr#status",
"type": "BitstringStatusListEndpoint",
"serviceEndpoint": "https://adapters.propdata.org.uk/hmlr/status",
"description": "Credential revocation status lists"
}
]
}

Key points:

  • Multiple keys in assertionMethod — adapters may use key rotation with overlapping validity periods. key-2 might be the next rotation key, already listed in assertionMethod but not yet primary.
  • The #vc-issuance service endpoint tells consumers where to request VCs and what credential types the adapter issues.
  • The #status endpoint links to the Bitstring Status List for revocation checking.
  • credentialTypes in the service endpoint metadata lists the VC types this adapter can issue, enabling automated discovery.

All PDTF 2.0 verification methods use the Ed25519VerificationKey2020 type with publicKeyMultibase encoding. This is the canonical representation for Ed25519 keys in the W3C DID ecosystem.

{
"id": "did:example:123#key-1",
"type": "Ed25519VerificationKey2020",
"controller": "did:example:123",
"publicKeyMultibase": "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
}

The publicKeyMultibase value encodes the raw Ed25519 public key using:

  1. Multicodec prefix: 0xed01 (Ed25519 public key)
  2. Multibase encoding: base58-btc (prefix z)
publicKeyMultibase = "z" + base58btc(0xed01 || raw_public_key_32_bytes)

All publicKeyMultibase values for Ed25519 keys will begin with z6Mk.

DID documents assign keys to specific verification relationships, which determine what the key may be used for:

RelationshipPurpose in PDTFRequired for
authenticationProve control of the DID (DID Auth challenge-response)Access control — presenting credentials to access restricted data
assertionMethodSign Verifiable CredentialsVC issuance — any entity that issues credentials must have a key listed here
capabilityDelegationDelegate authority to another DIDPerson DIDs only — used when issuing Representation credentials
capabilityInvocationInvoke capabilitiesPerson DIDs only — included for completeness in did:key resolution
Entity typeauthenticationassertionMethodcapabilityDelegationcapabilityInvocation
Person (did:key)✓✓✓✓
Organisation (did:key)✓✓✓✓
Organisation (did:web)✓✓——
Transaction (did:web)✓✓——
Trusted Adapter (did:web)✓✓——

Note: For did:key, all four relationships are automatically assigned to the single key. This is an inherent property of the did:key method — there’s only one key, and it serves all purposes.

Verifiable Credentials in PDTF 2.0 use the eddsa-jcs-2022 cryptosuite for Data Integrity Proofs:

{
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-jcs-2022",
"verificationMethod": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"created": "2026-03-24T10:00:00Z",
"proofPurpose": "assertionMethod",
"proofValue": "z3FXQje2VihZqE3WPgtvJh4Kv8VDsK6dN4RGLMA2PdoYbzLFST..."
}
}

Why eddsa-jcs-2022:

  • Uses JSON Canonicalization Scheme (JCS, RFC 8785) for deterministic serialisation
  • Ed25519 signatures — consistent with our key type
  • No dependency on JSON-LD processing (unlike eddsa-rdfc-2022)
  • Wide implementation support in VC libraries

The verificationMethod in the proof MUST reference a key listed in the issuer’s DID document under assertionMethod.


Service endpoints in DID documents enable machine-readable discovery of APIs and capabilities. PDTF 2.0 defines three custom service endpoint types.

The primary API for interacting with a PDTF transaction.

{
"id": "did:web:platform.example.com:transactions:abc123#pdtf-api",
"type": "PdtfTransactionEndpoint",
"serviceEndpoint": "https://api.platform.example.com/v2/transactions/abc123",
"description": "PDTF v2 transaction API"
}

Capabilities exposed:

OperationMethodPath (relative to serviceEndpoint)
Get composed state (v3 compat)GET/state/v3
Get composed state (v4 native)GET/state/v4
Submit credentialPOST/credentials
List credentialsGET/credentials
Get entityGET/entities/{entityType}/{id}
Verify credentialPOST/credentials/verify

Authentication: Credential presentation (SellerCapacity, Offer, Representation, or TransactionRole VC) with DID Auth challenge-response. Public endpoints (state/v3, state/v4 for public-only data) may be unauthenticated.

The Model Context Protocol endpoint for AI agent interaction.

{
"id": "did:web:platform.example.com:transactions:abc123#mcp",
"type": "McpEndpoint",
"serviceEndpoint": "https://api.platform.example.com/mcp/transactions/abc123",
"description": "Model Context Protocol endpoint for AI agent access"
}

Capabilities: Provides the same transaction data as the PDTF API but through the MCP protocol, enabling AI agents (property assistants, automated diligence tools, conveyancing copilots) to interact with transaction data using natural language tools.

Authentication: Same credential presentation model as PdtfTransactionEndpoint. The MCP server verifies presented credentials before exposing tools.

Used by Trusted Adapters to advertise their credential issuance capability.

{
"id": "did:web:adapters.propdata.org.uk:hmlr#vc-issuance",
"type": "VcIssuanceEndpoint",
"serviceEndpoint": "https://adapters.propdata.org.uk/hmlr/credentials/issue",
"description": "Request HMLR Official Copies as Verifiable Credentials",
"credentialTypes": ["TitleCredential", "SellerCapacityCredential"]
}

Request flow:

  1. Consumer discovers adapter DID via OpenID Federation trust resolution
  2. Resolves adapter DID document → finds VcIssuanceEndpoint
  3. Sends issuance request to serviceEndpoint:
{
"type": "TitleCredential",
"subject": "urn:pdtf:titleNumber:DN123456",
"requester": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"authPresentation": "eyJ..."
}
  1. Adapter fetches data from primary source (e.g., HMLR API)
  2. Adapter signs and returns VC

credentialTypes — array of VC type strings this adapter can issue. Enables automated discovery: a platform can enumerate all subordinate entities from the Trust Anchor’s federation_list_endpoint and determine which adapter to call for a given credential type.

TypeUsed byPurpose
RegulatoryRegistrationOrganisationsLink to SRA, CLC, or other regulatory body registration
CompanyRegistrationOrganisationsLink to Companies House record
BitstringStatusListEndpointAdaptersCredential revocation status list hosting
PdtfOrganisationEndpointOrganisationsPDTF credential exchange endpoint for the firm

did:key is self-resolving. The DID document is deterministically derived from the DID string — no network request is needed.

Resolution algorithm:

Input: did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
Output: DID Document (see Section 4.1)
1. Strip the "did:key:" prefix → multibase-encoded value
2. Decode base58-btc (strip 'z' prefix) → multicodec-prefixed key bytes
3. Verify multicodec prefix is 0xed01 (Ed25519)
4. Extract 32-byte raw public key
5. Construct DID document with the key in all verification relationships

Properties:

  • Zero latency — no HTTP request
  • Always available — no server dependency
  • Deterministic — same DID always produces the same document
  • Immutable — the document cannot change (key rotation = new DID)

did:web requires an HTTPS fetch to retrieve the DID document.

Resolution algorithm:

Input: did:web:platform.example.com:transactions:abc123
Output: DID Document (fetched from HTTPS)
1. Parse the DID:
- Method: "web"
- Domain: "platform.example.com"
- Path segments: ["transactions", "abc123"]
2. Construct the URL:
- If path segments exist:
https://{domain}/{path1}/{path2}/.../did.json
→ https://platform.example.com/transactions/abc123/did.json
- If no path segments:
https://{domain}/.well-known/did.json
3. Percent-decode any encoded characters in the domain
(e.g., %3A for port numbers)
4. Fetch the URL via HTTPS (TLS required — HTTP MUST be rejected)
5. Parse the response as JSON
6. Validate:
a. Response Content-Type is application/json or application/did+json
b. The "id" field matches the input DID
c. The document is valid per DID Core specification
d. All verificationMethod entries have valid key encodings
7. Return the DID Document

DID documents (especially for Organisations and Adapters) should be cached to avoid repeated HTTP requests during credential verification chains.

Entity typeCache TTLRationale
Person (did:key)∞ (no cache needed)Deterministic — always the same
Organisation (did:key)∞ (no cache needed)Deterministic — always the same
Organisation (did:web)24 hoursKeys rotate infrequently; regulatory metadata is stable
Transaction (did:web)1 hourService endpoints may update; shorter TTL acceptable
Trusted Adapter (did:web)24 hoursKeys rotate on a scheduled basis; longer TTL is safe

Cache invalidation:

  • On verification failure (signature doesn’t match any listed key), the resolver MUST re-fetch the DID document bypassing cache and retry verification once.
  • Implementations SHOULD respect HTTP Cache-Control headers from the DID document server as a minimum TTL.
ErrorConditionBehaviour
notFoundHTTP 404 from DID document URLDID cannot be resolved. Verification MUST fail.
invalidDidDocumentJSON parse failure or DID Core validation failureTreat as unresolvable. Log the error for diagnostics.
idMismatch"id" in the document doesn’t match the queried DIDReject — possible misconfiguration or attack.
httpErrorHTTP 5xx, timeout, or connection failureRetry with exponential backoff (max 3 attempts). If all fail, resolution fails. Use cached document if available and not expired.
tlsErrorCertificate validation failureResolution MUST fail. Do not fall back to HTTP.
deactivatedDID document contains "deactivated": trueDID is deactivated. Return the document but flag it as deactivated. Verifiers MUST reject credentials from deactivated DIDs.

did:web security ultimately depends on DNS integrity. PDTF 2.0 recommends but does not require DNSSEC for did:web hosts, because:

  • Many UK domains (.co.uk) do not yet support DNSSEC
  • The Trust Mark cross-check (binding DID to regulatory registration) provides a secondary trust anchor
  • Requiring DNSSEC would be a barrier to adoption

However, Trusted Adapter hosts (e.g., adapters.propdata.org.uk) SHOULD deploy DNSSEC, as they are high-value targets in the trust infrastructure.


Entity typeCreation process
Person (did:key)Generate Ed25519 key pair (client-side). Derive DID from public key. No registration needed.
Organisation (did:key)Account provider generates Ed25519 key pair on behalf of the Organisation. Provider verifies the org’s identity (SRA number, Companies House, etc.) and adds the DID to its managedOrganisations registry. No self-hosting required.
Organisation (did:web)Generate Ed25519 key pair. Create DID document with regulatory metadata. Host at firm’s domain. Apply to the Trust Anchor for a regulated-conveyancer Trust Mark.
Transaction (did:web)Platform generates transaction ID. Creates DID document with service endpoints. Hosts at platform domain.
Trusted Adapter (did:web)Adapter operator generates key pair. Creates DID document with issuance endpoint. Publishes Entity Configuration referencing the Trust Anchor via authority_hints; receives a pdtf-verified-issuer Trust Mark with delegation.authorised_paths.
Property (urn:pdtf:uprn:*)Derived from UPRN. No creation step — the identifier exists as long as the UPRN exists.
Title (urn:pdtf:titleNumber:*)Derived from HMLR title number. No creation step.
Unregistered Title (urn:pdtf:unregisteredTitle:*)Platform generates UUID v4 when a transaction involves unregistered land.

Key rotation differs fundamentally between did:key and did:web:

did:key cannot rotate keys. The key is the identifier. Changing the key changes the DID.

When a Person needs a new key (compromise, device loss, routine rotation):

  1. Generate new Ed25519 key pair → new did:key
  2. Issue a DID succession credential from the old DID (if old key is still available):
{
"@context": ["https://www.w3.org/ns/credentials/v2"],
"type": ["VerifiableCredential", "DidSuccession"],
"issuer": "did:key:z6MkOLD...",
"credentialSubject": {
"id": "did:key:z6MkNEW...",
"succeeds": "did:key:z6MkOLD...",
"reason": "routineRotation"
},
"proof": { "..." : "signed by old key" }
}
  1. Update all credentials that reference the old DID:

    • Re-issue SellerCapacity credentials with new DID
    • Re-issue Representation credentials with new DID
    • Previous credentials remain valid (signed by old key) but point to a now-superseded DID
  2. If old key is compromised and unavailable, the Person must re-establish their identity through out-of-band verification (e.g., re-verification by the platform, re-issuance of SellerCapacity credentials).

did:web supports in-place key rotation. Update the DID document to add the new key and (eventually) remove the old one.

Recommended rotation procedure:

Phase 1 — Add new key (overlap period):
verificationMethod: [key-1 (old), key-2 (new)]
assertionMethod: [key-1, key-2]
Duration: at least 2× the cache TTL for this entity type
Phase 2 — Switch primary:
Sign new credentials with key-2
Stop signing with key-1
Keep key-1 in verificationMethod for verification of old credentials
Phase 3 — Remove old key (after all old credentials expire or are re-issued):
verificationMethod: [key-2]
assertionMethod: [key-2]

Important: During the overlap period, verifiers may have either the old or new DID document cached. Both keys must be valid for verification during this window.

When a transaction completes (or is withdrawn), the platform should:

  1. Update the DID document to include "deactivated": true
  2. Remove service endpoints (API and MCP are no longer active)
  3. Retain verification methods for historical credential verification
  4. Maintain the DID document at its URL for at least 7 years (legal retention)
{
"@context": ["https://www.w3.org/ns/did/v1"],
"id": "did:web:platform.example.com:transactions:abc123",
"deactivated": true,
"verificationMethod": [
{
"id": "did:web:platform.example.com:transactions:abc123#key-1",
"type": "Ed25519VerificationKey2020",
"controller": "did:web:platform.example.com:transactions:abc123",
"publicKeyMultibase": "z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp7eTbCt2DADLY"
}
],
"assertionMethod": [
"did:web:platform.example.com:transactions:abc123#key-1"
]
}

If a firm ceases to operate (SRA de-registration, company dissolution):

  1. Remove DID document from domain (or mark as deactivated)
  2. The corresponding Trust Mark is marked revoked via the Trust Anchor’s federation_trust_mark_status_endpoint
  3. All Representation credentials issued to this Organisation should be revoked via Bitstring Status List

did:key cannot be “deactivated” in the DID document sense (there is no hosted document). Instead:

  • The private key is securely destroyed
  • Any credentials issued by this DID remain verifiable (signatures are still valid) but new credentials cannot be created
  • SellerCapacity and Representation credentials referencing this DID should be revoked if the person is withdrawing from the transaction

did:web inherits the security properties (and weaknesses) of the web PKI:

ThreatImpactLikelihoodMitigation
DNS hijackingAttacker serves fraudulent DID documentLow (DNSSEC mitigates)Federation cross-check: verifier confirms the Subordinate Entity Statement from the Trust Anchor pins the expected JWKS and matches regulatory IDs in the Trust Mark
Domain compromiseAttacker replaces DID document with their own keysLow–MediumFederation cross-check + certificate transparency monitoring + JWKS pinned by Trust Anchor in Subordinate Entity Statement
TLS interceptionMITM serves modified DID documentLow (certificate pinning mitigates)Strict TLS validation, reject HTTP, certificate transparency
Domain expiryFirm lets domain lapse; new owner can serve fraudulent DID docMedium (human process risk)Trust Anchor monitors domain ownership changes; revoke Trust Mark on ownership change
Insider threatFirm’s IT admin rotates keys and issues fraudulent credentialsLowCredential verification includes Trust Mark delegation check of issuance authorisation
ThreatImpactLikelihoodMitigation
Key compromiseAttacker can sign credentials as the personHigh impact, low likelihoodKey rotation (new DID + succession credential). Hardware key storage (future).
Key lossPerson loses access to their DID permanentlyMediumOut-of-band identity re-verification. Platform re-issuance of credentials.
Quantum computingEd25519 vulnerable to quantum attacksFuture risk (10+ years)Migration path to post-quantum algorithms. DID method is agnostic to key type — can switch to dilithium/kyber when multicodec prefixes are assigned.

9.3 Federation Cross-Check as Defence in Depth

Section titled “9.3 Federation Cross-Check as Defence in Depth”

The Trusted Issuer Registry provides a critical second layer of trust for did:web:

Verification chain:
1. Resolve did:web → get DID document
2. Verify credential signature against key in DID document
3. Resolve issuer trust chain to the Trust Anchor:
a. Is this DID registered?
b. Is it authorised for this credential type + entity path?
c. Does the Trust Mark's delegation / subject metadata match the DID document's regulatory metadata?
d. Is the Trust Mark still active (status endpoint reports not revoked)?
4. Only if ALL checks pass: credential is trusted

This means that even if an attacker compromises a domain and serves a fraudulent DID document, they cannot issue trusted credentials unless they also compromise the Trust Anchor’s signing key (which is held in an HSM with separate, independently governed access).

Entity typeKey storageMinimum requirement
PersonDevice keychain (iOS Keychain, Android Keystore)Encrypted at rest, biometric-gated access
Organisation (did:key, provider-managed)Provider’s KMS infrastructureProvider is responsible for key security
Organisation (did:web, self-hosted)HSM or cloud KMS (AWS KMS, Google Cloud KMS)FIPS 140-2 Level 2+
TransactionPlatform KMSPlatform’s standard key management
Trusted AdapterHSMFIPS 140-2 Level 2+ (adapters are high-value targets)

10.1 D23 — Unregistered Title Identifier Design

Section titled “10.1 D23 — Unregistered Title Identifier Design”

Status: Open

Unregistered land (land not registered at HMLR) has no title number. PDTF needs to identify these titles for credential issuance and reference.

Current proposal: urn:pdtf:unregisteredTitle:{uuid-v4}

Open questions:

  1. UUID version: Should we use UUID v4 (random) or UUID v5 (deterministic, based on a namespace + name like the property UPRN)? UUID v5 would mean the same unregistered title always gets the same identifier, but it creates a dependency on knowing the UPRN.

  2. First registration transition: When unregistered land is first registered at HMLR, it receives a title number. Should:

    • (a) The urn:pdtf:unregisteredTitle:{uuid} be retired and replaced with urn:pdtf:titleNumber:{number}, with a succession credential linking them?
    • (b) The unregistered title URN remain as an alias (alsoKnownAs) alongside the new title number URN?
    • (c) Both — succession credential + alias?
  3. Scope: Does the identifier cover the title (the legal interest) or the physical extent of unregistered land? Multiple titles can overlap the same land.

Status: Decided (did:key provider-managed as default, did:web self-hosted as option)

Decision: Most organisations will use provider-managed did:key identifiers issued by their account provider (e.g. LMS). The account provider verifies the organisation’s identity and regulatory status before issuing the DID, and lists it in their managedOrganisations registry. Self-hosted did:web at the firm’s domain is available for firms wanting direct control, but adoption is expected to be gradual.

Remaining questions:

  1. Self-hosted did:web guidance: For firms that choose did:web, should PDTF provide a standard tool/template for generating and hosting DID documents? (Likely yes — see Implementation Notes.)

  2. Domain verification cadence: For did:web Organisations, how often should the Trust Anchor re-verify that a firm’s DID document is still hosted and unchanged before renewing the Subordinate Entity Statement / Trust Mark? (Proposal: daily automated check.)

  3. Provider migration: If an Organisation switches account providers, how is the did:key transitioned? The new provider would issue a new did:key and update its managedOrganisations registry. A DID succession credential from the old provider may be needed.

Should Organisations be allowed to have multiple active keys for different purposes (e.g., one key for credential signing, another for authentication)? The current spec allows it (multiple entries in verificationMethod) but does not mandate it. Need to assess whether the added complexity is justified.

If did:web is superseded by a more secure method (e.g., did:webvh with verifiable history, or did:tdw), what is the migration path? OpenID Federation is DID-method-agnostic and can support multiple methods simultaneously, but credential re-issuance may be needed.


Status: Recommended approach decided; open for industry consultation.

Problem: A person who has been identity-verified in Transaction A (e.g., as a buyer) subsequently enters Transaction B (e.g., as a seller, or as a buyer of a different property). How do they carry their verified identity across without re-verification, and how does the receiving party in Transaction B trust the assertion “this is my identity”?

Recommended approach: DID-bound credential with platform-managed proof of control (Option C).

The person’s identity verification credential is bound to their did:key via credentialSubject.id. When they enter a new transaction, the platform proves DID control on their behalf (signing a challenge with the platform-managed key) and presents the identity credential. The receiving firm verifies:

  1. Credential signature — valid, signed by an issuer in the Federated Registry
  2. DID binding — credentialSubject.id matches the DID presenting the credential
  3. Proof of control — the presenter signed the challenge with the private key corresponding to the DID (proving they are the credential subject, not a replayer)
  4. Revocation status — Bitstring Status List confirms the credential has not been revoked
  5. Issuer authority — the issuing entity is listed in the Federated Registry as an authorised identity verifier

Verification flow:

Transaction A (completed):
Person verified by Firm X → Identity VC issued
credentialSubject.id: did:key:z6Mk{person}
issuer: did:key:z6Mk{firmX} (or platform DID)
type: [VerifiableCredential, IdentityVerification]
evidence: [{type: "DocumentVerification", ...}]
Transaction B (new):
1. Person enters transaction, platform asserts their DID
2. Receiving Firm Y sends challenge nonce
3. Platform signs challenge with person's key (platform-managed)
→ proves person controls did:key:z6Mk{person}
4. Platform presents Identity VC from Transaction A
5. Firm Y verifies:
a. VC signature valid
b. credentialSubject.id == DID that signed the challenge
c. Issuer DID in Federated Registry as identity verifier
d. Credential not revoked
6. Firm Y accepts — person is identity-verified without re-verification

Why this approach:

  • Cryptographic binding — the relationship assertion (“this is my identity”) is provable via DID control, not merely claimed. A bearer token without holder-binding could be replayed by anyone who obtains the credential.
  • Platform-managed keys — the account holder does not need to manage cryptographic keys directly. The platform holds the key in KMS and signs on behalf of the person. This preserves the zero-friction onboarding model (Sub-spec 06 §10.1) while providing the cryptographic guarantees of self-sovereign identity.
  • Forward-compatible — when digital identity wallets mature (Sub-spec 06 §10), the person can migrate to a self-held key. The credential format and verification flow are identical; only the key custody changes.
  • Consent-gated — the person must initiate or approve the presentation. The platform cannot unilaterally share identity credentials into a new transaction.

Alternative approaches (presented for industry consultation):

OptionMechanismTrust modelKey managementLimitations
A. Bearer VC presentationPerson presents identity VC directly; no DID-binding proofCredential signature + Federated Registry lookupNone (bearer token)Without holder-binding, anyone with a copy of the VC can present it. Requires additional anti-replay measures (audience restriction, nonce binding).
B. Firm-to-firm transfer with consentPerson authorises Firm X to share credential with Firm Y; platform brokers the handoffFirm-to-firm trust, both in Federated RegistryNone (firm-held)Person has no independent control over their identity. Not truly portable — tied to the originating firm’s willingness to share.
C. DID-bound + platform-managed proof of control (recommended)Person’s DID is bound to credential; platform proves DID control on their behalfCryptographic proof of control + Federated RegistryPlatform-managed (KMS)Requires platform to manage keys on behalf of users. Person trusts platform not to sign without consent. Mitigated by audit logging and future wallet migration.

Consultation question: See Industry Consultation Q10.


11.1 Reference Implementation: pdtf-did-resolver

Section titled “11.1 Reference Implementation: pdtf-did-resolver”

The pdtf-did-resolver package (to be published at property-data-standards-co/pdtf-did-resolver on GitHub) provides:

  • did:key resolution — deterministic DID document generation from Ed25519 keys
  • did:web resolution — HTTPS fetch with caching, error handling, and TLS validation
  • URN validation — ABNF grammar validation for all urn:pdtf:* identifiers
  • Key derivation — Ed25519 key pair generation and did:key derivation
  • DID document builder — typed builder for constructing Organisation, Transaction, and Adapter DID documents
import {
resolveDidKey,
resolveDidWeb,
resolveDid,
generateDidKey,
validatePdtfUrn,
DidDocumentBuilder
} from '@pdtf/did-resolver';
// Generate a new did:key
const { did, publicKey, privateKey } = await generateDidKey();
// → did = "did:key:z6Mk..."
// Resolve any DID
const didDocument = await resolveDid('did:web:platform.example.com:transactions:abc123');
// → { id: "did:web:...", verificationMethod: [...], service: [...] }
// Resolve did:key (synchronous — no network)
const keyDoc = resolveDidKey('did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK');
// Validate a PDTF URN
const valid = validatePdtfUrn('urn:pdtf:titleNumber:DN123456');
// → true
// Build a DID document
const doc = new DidDocumentBuilder('did:web:smithandjones.co.uk')
.addVerificationMethod({
id: '#key-1',
type: 'Ed25519VerificationKey2020',
publicKeyMultibase: 'z6Mkr7JAFsC4...'
})
.addAuthentication('#key-1')
.addAssertionMethod('#key-1')
.addService({
id: '#sra',
type: 'RegulatoryRegistration',
serviceEndpoint: 'https://www.sra.org.uk/solicitors/firm/612345',
registrationNumber: '612345'
})
.build();

Organisations and platforms hosting did:web DID documents must serve them with:

  • Content-Type: application/json or application/did+json
  • HTTPS only — HTTP MUST be rejected by resolvers
  • CORS headers: Access-Control-Allow-Origin: * (DID documents are public by design)
  • Cache-Control: Set appropriate TTL (recommended: max-age=3600 for transactions, max-age=86400 for organisations)

Minimal hosting example (static file):

A conveyancer firm can host their DID document as a static JSON file at https://smithandjones.co.uk/.well-known/did.json. No dynamic server required — a CDN or static site host (GitHub Pages, Cloudflare Pages, Netlify) is sufficient.

PackagePurpose
@noble/ed25519Ed25519 key generation, signing, verification
multiformatsMultibase/multicodec encoding and decoding
@digitalbazaar/ed25519-verification-key-2020Ed25519VerificationKey2020 type implementation

The reference implementation MUST include test vectors for:

  1. did:key derivation — known public key → expected DID string
  2. did:key resolution — known DID → expected DID document
  3. did:web URL construction — known DID → expected HTTPS URL
  4. URN validation — valid and invalid URN strings for each type
  5. Round-trip — generate key pair → derive DID → resolve → verify key matches

To lower the barrier for firms, PDTF will provide a CLI tool:

Terminal window
# Generate Organisation DID document
npx @pdtf/did-tools org-init \
--domain smithandjones.co.uk \
--sra-number 612345 \
--company-number OC123456 \
--output .well-known/did.json
# Verify DID document is correctly hosted
npx @pdtf/did-tools org-verify --did did:web:smithandjones.co.uk

This generates the key pair, constructs the DID document with regulatory metadata, and outputs the file for hosting. The org-verify command checks that the document is accessible, valid, and matches the expected format.


EntityIdentifier TypePatternExample
Persondid:keydid:key:z6Mk{base58}did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
Organisation (provider-managed)did:keydid:key:z6Mk{base58}did:key:z6MkpJmqLFMmaFHCqS9jVjMNRNHriSNkFCyG3MLbiqkVMhvm
Organisation (self-hosted)did:webdid:web:{domain}did:web:smithandjones.co.uk
Transactiondid:webdid:web:{platform}:transactions:{id}did:web:platform.example.com:transactions:abc123
Trusted Adapterdid:webdid:web:{host}:{adapter}did:web:adapters.propdata.org.uk:hmlr
PropertyURNurn:pdtf:uprn:{uprn}urn:pdtf:uprn:100023456789
Title (registered)URNurn:pdtf:titleNumber:{number}urn:pdtf:titleNumber:DN123456
Title (unregistered)URNurn:pdtf:unregisteredTitle:{uuid}urn:pdtf:unregisteredTitle:f47ac10b-58cc-4372-a567-0e02b2c3d479
SellerCapacityURNurn:pdtf:capacity:{uuid}urn:pdtf:capacity:7c9e6679-7425-40de-944b-e07fc1f90ae7
OfferURNurn:pdtf:offer:{uuid}urn:pdtf:offer:c3d4e5f6-a7b8-4c9d-0e1f-2a3b4c5d6e7f
GiftURNurn:pdtf:gift:{uuid}urn:pdtf:gift:b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e
RepresentationURNurn:pdtf:representation:{uuid}urn:pdtf:representation:a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d
TransactionRoleURNurn:pdtf:role:{uuid}urn:pdtf:role:d4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f8a
IDDecisionDateStatus
D7did:key for Persons; did:key or did:web for Organisations; did:web for Transactions/Adapters2026-03-23Updated — Organisations may use provider-managed did:key (common case) or self-hosted did:web
D23urn:pdtf:unregisteredTitle:{uuid} for unregistered titles2026-03-24Open — UUID version and first-registration transition TBD
D26Organisations use did:key (provider-managed, default) or did:web (self-hosted)2026-03-24Updated — did:key via account provider is the common path; did:web for firms wanting direct control
Sub-specRelevance
01 — Entity Graph & SchemaEntity types that these identifiers address
02 — VC Data ModelHow DIDs appear in issuer and credentialSubject.id fields
04 — OpenID FederationFederation accreditation of did:web entities via Entity Statements and Trust Marks
12 — Adapter Access Control (Coming Soon)DID Auth and credential presentation protocols
07 — State AssemblyHow identifiers are used in graph composition