Skip to main content

What are DIDs

W3C Decentralized Identifiers give agents a portable, cryptographic identity that works across services. Instead of an opaque token tied to one KavachOS instance, an agent gets a DID like did:key:z6Mk... backed by an Ed25519 keypair. The agent can prove its identity to any service by signing a payload with its private key. The verifier resolves the DID to get the public key and checks the signature. No shared secrets, no central registry.
DIDs are optional. Regular kv_ bearer tokens work fine for single-service deployments. Use DIDs when agents need to prove identity across organizational boundaries.

Two DID methods

KavachOS supports two W3C DID methods:
MethodFormatBest for
did:keydid:key:z6Mk...Self-contained identity. No server needed. Key is embedded in the identifier.
did:webdid:web:auth.example.com:agents:agt_123Organization-backed identity. DID document hosted at a well-known URL.

Generate a DID for an agent

const { agentDid, privateKeyJwk } = await kavach.did.generateKey(agent.id);

console.log(agentDid.did);
// did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK

// Store privateKeyJwk securely. It's shown once and never stored in the database.
The private key is returned once and never stored in the database. Only the public key and DID document are persisted. Treat the private key like a bearer token.

Sign and verify payloads

An agent can sign a payload to prove it authored a request:
// Agent signs a payload
const signed = await kavach.did.sign(agent.id, {
  action: 'deploy',
  environment: 'staging',
  timestamp: new Date().toISOString(),
}, privateKeyJwk);

console.log(signed.jws);    // compact JWS string
console.log(signed.issuer); // did:key:z6Mk...
A receiving service verifies the signature:
const result = await kavach.did.verify(signed.jws, agentDid.did);

if (result.valid) {
  console.log(result.payload);  // { action: 'deploy', ... }
  console.log(result.issuer);   // did:key:z6Mk...
}

Verifiable presentations

A presentation is a signed JWT that bundles an agent’s identity with its capabilities. Use this when an agent needs to prove both who it is and what it can do.
// Create a presentation
const jwt = await kavach.did.createPresentation({
  agentId: agent.id,
  did: agentDid.did,
  privateKeyJwk,
  capabilities: ['mcp:github:read', 'mcp:linear:write'],
  audience: 'https://mcp.partner.com',
  expiresIn: 300, // 5 minutes
});

// Verify on the receiving end
const result = await kavach.did.verifyPresentation(jwt);

if (result.valid) {
  console.log(result.agentId);      // agt_abc123
  console.log(result.capabilities); // ['mcp:github:read', 'mcp:linear:write']
}

DID document structure

Every agent DID resolves to a W3C DID document:
{
  "@context": ["https://www.w3.org/ns/did/v1"],
  "id": "did:key:z6MkhaXg...",
  "controller": "did:key:z6MkhaXg...",
  "verificationMethod": [{
    "id": "did:key:z6MkhaXg...#key-0",
    "type": "JsonWebKey2020",
    "controller": "did:key:z6MkhaXg...",
    "publicKeyJwk": {
      "kty": "OKP",
      "crv": "Ed25519",
      "x": "..."
    }
  }],
  "authentication": ["did:key:z6MkhaXg...#key-0"],
  "assertionMethod": ["did:key:z6MkhaXg...#key-0"],
  "capabilityInvocation": ["did:key:z6MkhaXg...#key-0"],
  "capabilityDelegation": ["did:key:z6MkhaXg...#key-0"]
}

Retrieve a stored DID

const agentDid = await kavach.did.getAgentDid(agent.id);

if (agentDid) {
  console.log(agentDid.did);       // did:key:z6Mk...
  console.log(agentDid.method);    // 'key' or 'web'
}

Resolve any DID

// Resolve did:key (local, no network)
const doc = await kavach.did.resolve('did:key:z6Mk...');

// Resolve did:web (fetches from HTTPS)
const doc = await kavach.did.resolve('did:web:auth.example.com');
agentId
string
The agent this DID belongs to.
did
string
The full DID string (did:key:… or did:web:…).
method
'key' | 'web'
Which DID method was used.
publicKeyJwk
JsonWebKey
Ed25519 public key in JWK format.
didDocument
DidDocument
The full W3C DID document.
createdAt
Date
When the DID was generated.
Last modified on April 20, 2026