Skip to content

签名与验证

badges.ninja 发布一个公开的加密身份,以便第三方可以验证携带数字签名的凭证。这是支持 Open Badges 3.0 / W3C Verifiable Credentials 的基础。

这些端点是 公开的,无需认证。它们相对于 https://api.badges.ninja

颁发者 DID

平台的颁发者身份是 did:web 标识符:

did:web:api.badges.ninja

根据 did:web 规则,它会解析为在下面 well-known 路径提供的 DID 文档。

DID 文档

GET /.well-known/did.json

返回 DID 文档,将颁发者的公开签名密钥(一个 Ed25519 JsonWebKey2020)作为其 assertionMethod 暴露出来。

bash
curl https://api.badges.ninja/.well-known/did.json
json
{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/suites/jws-2020/v1"
  ],
  "id": "did:web:api.badges.ninja",
  "verificationMethod": [
    {
      "id": "did:web:api.badges.ninja#<kid>",
      "type": "JsonWebKey2020",
      "controller": "did:web:api.badges.ninja",
      "publicKeyJwk": { "kty": "OKP", "crv": "Ed25519", "x": "<base64url>" }
    }
  ],
  "assertionMethod": ["did:web:api.badges.ninja#<kid>"],
  "authentication": ["did:web:api.badges.ninja#<kid>"]
}

响应内容类型为 application/did+json。该文档可缓存(它仅在密钥轮换时更改)。

JWKS

对于更倾向于使用 JWK Set 发现而非 DID 解析的验证者:

GET /.well-known/jwks.json
bash
curl https://api.badges.ninja/.well-known/jwks.json
json
{
  "keys": [
    {
      "kty": "OKP",
      "crv": "Ed25519",
      "x": "<base64url>",
      "kid": "<thumbprint>",
      "alg": "EdDSA",
      "use": "sig"
    }
  ]
}

kid 是公钥的 RFC 7638 指纹,并与 DID 文档 verificationMethod id 上的片段相匹配。

可验证凭证(Open Badges 3.0)

每个奖励都可以作为 Open Badges 3.0 / W3C Verifiable Credential 获取,使用上面的颁发者密钥签名。

GET /certify-badge/award/{guid}/vc
查询结果
(默认)?format=jwt已签名的 VC-JWT(application/jwt)——可导入 OB 3.0 钱包。
?format=json未签名的 OpenBadgeCredential JSON(application/vc+ld+json)——用于查看。
bash
# Signed credential (VC-JWT)
curl https://api.badges.ninja/certify-badge/award/<guid>/vc

# Human-readable credential JSON
curl "https://api.badges.ninja/certify-badge/award/<guid>/vc?format=json"

该凭证是一个类型为 ["VerifiableCredential", "OpenBadgeCredential"] 的 VC(上下文为 https://www.w3.org/ns/credentials/v2 和 OB 3.0 上下文)。它的 issuer.iddid:web:api.badges.ninja,而成就、接收者身份(哈希后的邮箱)以及颁发/过期日期都来自该奖励。

验证 VC-JWT

该令牌是一个带有 EdDSA 签名的紧凑型 JWS。要验证它:

  1. 将 JWT 拆分为 header.payload.signature
  2. 从 header 中读取 kid——它指向 DID 文档 / JWKS
  3. 获取公钥并验证 header.payload 上的 Ed25519 签名。
js
import crypto from "node:crypto";

const [h, p, s] = jwt.split(".");
const jwks = await (await fetch("https://api.badges.ninja/.well-known/jwks.json")).json();
const jwk = jwks.keys[0];
const pub = crypto.createPublicKey({ key: jwk, format: "jwk" });
const ok = crypto.verify(null, Buffer.from(`${h}.${p}`), pub, Buffer.from(s, "base64url"));

接收者也可以从其公开凭证页面的 Download 菜单获取凭证(Verifiable Credential)。

签名算法

签名使用 Ed25519(EdDSA)。私钥由服务端托管且从不暴露;仅发布上面的公钥。

托管验证(Open Badges 2.0)

如今,每个凭证也可通过其托管的 Open Badge 2.0 断言独立验证。关于断言、徽章和颁发者 JSON 端点,请参见 公开验证;关于面向接收者的验证页面,请参见 分享与验证

badges.ninja Documentation