メインコンテンツまでスキップ

Decentralized Identifiers (DIDs)

The W3C DID Standard

Definition: A globally unique identifier that doesn't require a central registration authority.

DID syntax:

did:method:method-specific-identifier

Examples:
did:ethr:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH
did:web:example.com
did:ion:EiDyOQbbZAa3aiRzeCkV7LOx3SERjjH93EXoIM3UoN4oWg

Components:

did:ethr:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
↑ ↑ ↑
| | └── Unique identifier (Ethereum address)
| └──────────── Method (how to resolve)
└───────────────── Scheme (always "did")

DID Document:

{
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:ethr:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"verificationMethod": [{
"id": "did:ethr:0x742d35...#keys-1",
"type": "EcdsaSecp256k1VerificationKey2019",
"controller": "did:ethr:0x742d35...",
"publicKeyHex": "04ab5d8a2f..."
}],
"authentication": ["did:ethr:0x742d35...#keys-1"],
"service": [{
"id": "did:ethr:0x742d35...#vcs",
"type": "VerifiableCredentialService",
"serviceEndpoint": "https://example.com/vc"
}]
}

Key properties:

1. Self-sovereign:
- You control your identifier
- No company can revoke it
- No permission needed to create

2. Resolvable:
- DID → DID Document (public keys, endpoints)
- Multiple resolution methods
- Works across systems

3. Cryptographically verifiable:
- Sign with private key
- Others verify with public key from DID Document
- No central authority needed

4. Persistent:
- Same identifier forever
- Can update keys/services
- Portable across platforms

DID Methods

Different methods for different use cases:

1. did:ethr (Ethereum-based)

// ERC-1056: Ethereum DID Registry
contract EthereumDIDRegistry {
mapping(address => address) public owners;
mapping(address => mapping(bytes32 => mapping(address => uint))) public delegates;

// Change owner
function changeOwner(address identity, address newOwner) public {
require(msg.sender == owners[identity] || msg.sender == identity);
owners[identity] = newOwner;
emit DIDOwnerChanged(identity, newOwner);
}

// Add delegate (e.g., for signing)
function addDelegate(
address identity,
bytes32 delegateType,
address delegate,
uint validity
) public {
require(msg.sender == owners[identity] || msg.sender == identity);
delegates[identity][delegateType][delegate] = block.timestamp + validity;
emit DIDDelegateChanged(identity, delegateType, delegate, validity);
}
}

// Usage:
// DID: did:ethr:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
// Resolution: Query registry for owner and delegates
// Verification: Check if public key is registered delegate

2. did:key (Self-contained)

Format: did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH
└─────────────────────────────────┘
Base58-encoded public key

DID Document derived from key itself:
{
"id": "did:key:z6Mkp...",
"verificationMethod": [{
"id": "did:key:z6Mkp...#z6Mkp...",
"type": "Ed25519VerificationKey2020",
"controller": "did:key:z6Mkp...",
"publicKeyMultibase": "z6Mkp..."
}]
}

Benefits:
+ No blockchain needed
+ No registration cost
+ Instant creation
+ Works offline

Drawbacks:
- Cannot update keys (key = identity)
- Cannot add services
- Limited functionality

3. did:web (Web-based)

Format: did:web:example.com:user:alice

Resolution:
GET https://example.com/user/alice/did.json

Returns DID Document from web server

Benefits:
+ Familiar infrastructure (HTTPS)
+ Easy for companies to adopt
+ Can use existing domains

Drawbacks:
- Centralized (domain owner controls)
- Can be censored
- Subject to DNS/CA system

4. did:ion (Bitcoin-anchored, decentralized)

Microsoft's ION system:
- Uses Bitcoin for anchoring
- IPFS for data storage
- Sidetree protocol

Process:
1. Create DID locally
2. Publish DID operations to IPFS
3. Anchor IPFS hash on Bitcoin
4. Anyone can resolve by reading Bitcoin + IPFS

Benefits:
+ Highly decentralized
+ Bitcoin security
+ No tokens needed (no gas)

Drawbacks:
- Complex resolution
- Slow updates (Bitcoin block time)
- Still maturing

How DID Resolution Works

User has: did:ethr:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb

Step 1: Parse DID
method = "ethr"
identifier = "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"

Step 2: Select resolver based on method
if method == "ethr":
resolver = EthereumDIDResolver()
elif method == "key":
resolver = KeyDIDResolver()
elif method == "web":
resolver = WebDIDResolver()

Step 3: Resolve DID → DID Document
document = resolver.resolve(identifier)

Step 4: Extract verification methods
public_keys = document["verificationMethod"]
services = document["service"]

Step 5: Use for verification
signature = "0x1a2b3c..."
message = "I authenticate with this DID"
is_valid = verify(public_keys[0], message, signature)

Example: Authentication flow

// 1. User wants to authenticate with website
const did = "did:ethr:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb";

// 2. Website generates challenge
const challenge = "Sign this message at " + Date.now();

// 3. User signs with their private key
const signature = await wallet.signMessage(challenge);

// 4. Website resolves DID to get public key
const didDocument = await resolve(did);
const publicKey = didDocument.verificationMethod[0].publicKeyHex;

// 5. Website verifies signature
const isValid = verifySignature(challenge, signature, publicKey);

// 6. If valid, user is authenticated
if (isValid) {
// User proved control of DID
// No password needed!
authenticateUser(did);
}