Skip to content

Concepts: DIDs, VCs and did:key

Decentralized Identifier (DID)

A DID is an identifier you control without a central registry, e.g. did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK. Each DID method (did:key, did:web, did:ion, …) defines how the identifier is created and how a verifier looks up its public keys (the "DID Document").

Verifiable Credential (VC)

A VC is a tamper-evident, cryptographically signed set of claims made by an issuer about a subject, following the W3C VC Data Model. Example: a university (issuer) asserts that a student (subject) holds a degree.

Three roles:

  • Issuer — signs the credential.
  • Holder — stores it (often the subject) and presents it.
  • Verifier — checks the signature against the issuer's DID.

Why did:key here

did:key embeds the public key directly in the identifier. That means a verifier can reconstruct the public key and check a signature offline — no ledger, no network call, no registry. This makes it the simplest possible method to learn and to test with.

The trade-off: because the key is the identifier, did:key has no key rotation and no revocation. That's fine for demos and short-lived, peer-to-peer trust; for anything long-lived, see Going to production.

How simple-vc signs

  1. generateDidKey() creates an Ed25519 keypair and encodes the public key as a did:key (multicodec prefix 0xed01 + base58btc, the z6Mk… form).
  2. issueCredential() builds the VC payload and signs it as a JWT with the EdDSA algorithm using did-jwt-vc.
  3. verifyCredentialJwt() resolves the issuer did:key with key-did-resolver and verifies the signature.

JWT vs JSON-LD proofs

There are two common VC proof formats: JWT (compact, what this library uses) and JSON-LD Data Integrity proofs (embedded in the JSON). Both are valid W3C VCs; JWT is simpler to start with and interoperable with the wider JOSE ecosystem.