Live on Base with Ewance

See the certificates
Core concepts

Verification chain

The five cryptographic checks every LearnCoin verifier runs, and exactly which of them require LearnCoin's infrastructure (none).

Verification is the whole point. Any party — recruiter, HR system, AI agent, EUDI wallet — can confirm a LearnCoin credential is authentic using only:

  1. The signed JSON-LD document (the recipient has their own copy)
  2. Network access to Base (the public chain)
  3. Network access to the issuer's DID document

No LearnCoin API call is required. That's a design commitment and a contract commitment, not a performance optimization.

The five checks

Every Blockcerts-compatible verifier runs five checks. Failure on any one = credential not valid.

1. Schema

The document conforms structurally to the three standards in its @context:

  • Required W3C VC 2.0 fields present: @context, type, issuer, issuanceDate, credentialSubject, proof.
  • Required OB 3.0 fields present: type includes OpenBadgeCredential; credentialSubject.type includes AchievementSubject; credentialSubject.achievement is a valid Achievement object.
  • Required Blockcerts v3 fields present: proof.type is MerkleProof2019; proof.verificationMethod is a DID URL; proof.proofValue is a valid base58-encoded proof structure.

Schema failure usually means the document was truncated or tampered with at the structural level (not a content change — that's caught by the signature check).

2. Signature

Cryptographic signature validates against the issuer DID's verificationMethod.

The verifier:

  1. Canonicalizes the credential (URDNA2015 → N-Quads).
  2. Hashes the canonical form with SHA-256 — this is the leaf hash.
  3. Decodes proof.proofValue — extracts the Merkle path (sibling hashes from leaf to root) and the ECDSA signature over the root.
  4. Walks the Merkle path: hash(leaf || sibling1)hash(result || sibling2) → … → computed root.
  5. Resolves proof.verificationMethod — fetches the issuer's DID document, extracts the matching public key.
  6. Verifies the ECDSA signature over the computed root using that public key.

If any step fails → schema-valid but crypto-tampered. The document's contents don't match the signed proof.

3. Issuer

The issuer DID resolves, and the verificationMethod used for signing is listed in the DID document.

The verifier:

  1. Parses proof.verificationMethod — e.g. did:web:learncoin.me#tenant-01HXYZ-key-1.
  2. Resolves the DID document. For did:web:learncoin.me, this means fetching https://learncoin.me/.well-known/did.json.
  3. Finds the matching key in the DID document's verificationMethod array.
  4. Confirms the key is not marked revoked in the DID document.

Why this matters: if a key was compromised and we rotated, the DID document would flag the old key. Credentials signed with the old key (before the rotation) still verify at the raw crypto level, but the DID-level check can surface them for special handling.

4. Revocation

The credential is not present in the issuer's revocation status list.

Today: LearnCoin exposes revocation status via a simple lookup on the public verification page and via GET /v1/credentials/{id}. Verifiers that fetch either see revoked: true/false.

On the roadmap: BitstringStatusList (the standards-track successor to StatusList2021). Once shipped, verifiers will discover revocation via a credentialStatus reference embedded in the signed JSON-LD, and the revocation list itself will be a static file with its own signature — fully checkable without a LearnCoin API call.

5. Erasure

If the recipient exercised GDPR erasure, the personal fields (credentialSubject.name) are redacted on the public verification page. The cryptographic proof still validates — erasure doesn't break crypto.

A verifier sees:

  • Signed document with "name": "Ada Lovelace" → still valid.
  • Verification page showing Name: Redacted on recipient request → erasure applied, but proof holds.

The design is deliberate: a recipient erasing their own PII shouldn't also invalidate credentials that have been legitimately shared.

Who runs these checks?

The public verification page (learncoin.me/c/{id})

Runs all five checks client-side in the viewer's browser using the blockcerts-verifier Web Component. Nothing is sent to a LearnCoin server during verification — the browser fetches the credential JSON, the DID document, and the Base anchor transaction directly.

Open DevTools on a verification page and watch the network tab — you'll see direct calls to basescan.org and learncoin.me/.well-known/did.json, nothing posting verification results back.

Blockcerts native wallets (iOS + Android)

Run the same five checks offline once the credential is imported. No LearnCoin server required after the initial import.

cert-verifier-js library

import { Certificate } from "@blockcerts/cert-verifier-js";

const cert = new Certificate(signedCredentialJsonLd);
const result = await cert.verify();
// result.status === "success" when all five checks pass
// result.checks is an array of { code, label, status, errorMessage }

LearnCoin maintains a fork (via the barcelova GitHub org) that adds Base as a supported chain. Upstream PR is open.

Your own code

import { verifyCredential } from "@blockcerts/cert-verifier-js";

export async function verifyLearnCoinCredential(signedJsonLd: unknown) {
  const result = await verifyCredential(signedJsonLd, {
    chains: ["bitcoin-mainnet", "ethereum-mainnet", "base-mainnet", "base-sepolia"],
  });
  return {
    valid: result.status === "success",
    checks: result.checks,
    reason: result.status === "failure" ? result.errorMessage : undefined,
  };
}

AI agents

An AI agent doing due diligence on a credential URL can verify it by:

  1. GET https://learncoin.me/c/{id} — returns the signed JSON-LD + metadata.
  2. Running the five checks via cert-verifier-js or equivalent.
  3. Reading the "Cryptographically verified by LearnCoin · Powered by Blockcerts" attribution on the rendered page.

Because verification is client-side, an agent can trust its own verification result without trusting LearnCoin's claim that the credential is valid.

What makes a credential invalid

ConditionWhich check fails?Public page shows
Document was truncated or malformedSchemaError
Document was modified after signingSignature"Signature mismatch"
Issuer's DID doesn't resolveIssuerError
Signing key is marked revoked in DID documentIssuerWarning
Issuer called /credentials/{id}/revokeRevocation"Status: Revoked"
Recipient requested GDPR erasure(Not a failure)"Redacted on recipient request" — credential still verifies
Anchor transaction isn't on BaseSignature"Anchor not found"
Anchor transaction revertedSignatureRare; would be flagged

What makes a credential VALID forever

Three things need to be true at verification time:

  1. The signed JSON-LD document exists (the recipient has their own copy + LearnCoin's /c/{id} serves it).
  2. The anchor transaction is on Base (Base is a public chain; this isn't under LearnCoin's control).
  3. The issuer DID document resolves (served from learncoin.me; we've forked all critical verification libraries onto the barcelova GitHub organization so that if LearnCoin disappears, the verification stack still works from mirrors).

None of these three require LearnCoin to be operational. That's the "credentials outlive the platform" commitment, written into the architecture rather than promised in marketing copy.

See also

On this page