@digitalcredentials/vc

中文文档
10.0.2发布于 2025/11/20BSD-3-ClauseES Module近 30 天下载 8万

可验证的证书 JavaScript 库.

中文使用文档
文档目录16 节
  1. 目录
  2. 警卫
  3. 背景情况
  4. 安装
  5. 使用量
  6. 建立一个签名套房
  7. 签发一份可核证的证书
  8. 发布选择性披露
  9. 衍生出一种选择性披露
  10. 创建可验证的演示文稿
  11. 自定义文档Loader
  12. 验证可验证的演示文稿
  13. 验证可验证的证书
  14. 测试
  15. 贡献
  16. 许可证

可核实的身份证件 (@数字证书/vc)

NPM Version

一个 Javascript 库,用于发布和验证可验证的证书.

目录

警卫

同大多数与安全和密码学有关的工具一样 您的系统将在很大程度上取决于您的设计决定( 哪些关键类型) 你将使用,你将储存 私钥,你放进你的 证书等. )

背景情况

(从 digitalbazaar/vc v1.0.0 (韩语) 以提供反应兼容性。 )

此库是 Javascript (Node.js 和浏览器) 执行 可核实的证书数据模型 1.0 规格(目前不支持JWT序列化).

它允许您执行以下基本操作:

  1. 签署(签发)可核证的证书.
  2. 创建可验证的演示文稿(VP),签名或未签名
  3. 正在验证 VP
  4. 核查独立的《维也纳公约》

先决条件: 这个图书馆的使用假设你有能力做 目标如下:

  • 生成 LD 密钥对和签名套件
  • 将相应的公钥发布到可供用户访问的地方 审取者.
  • 确定您的习惯 @contexts,核查方法(如公用钥匙) 及其相应的控制文档,以及任何其他可解决的 对象,可通过 documentLoader。 。 。 .

安装

  • 浏览器和Node.js 18+得到支持.

从国家预防机制安装:

npm install @digitalbazaar/vc

在当地安装(用于开发):

git clone https://github.com/digitalcredentials/vc.git
cd vc
npm install

使用量

建立一个签名套房

签字时,设置签名套房时,需要通过 包含私钥的密钥对.

import vc from '@digitalcredentials/vc';

// Required to set up a suite instance with private key
import {Ed25519VerificationKey2020} from
  '@digitalcredentials/ed25519-verification-key-2020';
import {Ed25519Signature2020} from '@digitalcredentials/ed25519-signature-2020';

const keyPair = await Ed25519VerificationKey2020.generate();

const suite = new Ed25519Signature2020({key: keyPair});

签发一份可核证的证书

先决条件:

  • 您有私人密钥( 带有 ID 和控制器) 和相应的套件
  • 如果你使用习惯 @context,确保它可以解决
  • (建议) 你有一个策略 在哪里发布你的主计长 文档和公钥
const vc = require('@digitalcredentials/vc');

// Sample unsigned credential
const credential = {
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://www.w3.org/2018/credentials/examples/v1"
  ],
  "id": "https://example.com/credentials/1872",
  "type": ["VerifiableCredential", "AlumniCredential"],
  "issuer": "https://example.edu/issuers/565049",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "alumniOf": "Example University"
  }
};

const signedVC = await vc.issue({credential, suite, documentLoader});
console.log(JSON.stringify(signedVC, null, 2));

发布选择性披露

先决条件:

  • 您有私人密钥( 带有 ID 和控制器) 和相应的套件
  • 您正在使用一个密码套件 支持选择性的披露,例如 作为 ecdsa-sd-2023
  • 如果你使用习惯 @context,确保它可以解决
  • (建议) 你有一个策略 在哪里发布你的主计长 文档和公钥
import * as vc from '@digitalbazaar/vc';
import * as ecdsaSd2023Cryptosuite from
  '@digitalbazaar/ecdsa-sd-2023-cryptosuite';
import {DataIntegrityProof} from '@digitalbazaar/data-integrity';

const ecdsaKeyPair = await EcdsaMultikey.generate({
  curve: 'P-256',
  id: 'https://example.edu/issuers/keys/2',
  controller: 'https://example.edu/issuers/565049'
});

// sample unsigned credential
const credential = {
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://www.w3.org/2018/credentials/examples/v1"
  ],
  "id": "https://example.com/credentials/1872",
  "type": ["VerifiableCredential", "AlumniCredential"],
  "issuer": "https://example.edu/issuers/565049",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "alumniOf": "Example University"
  }
};

// setup ecdsa-sd-2023 suite for signing selective disclosure VCs
const suite = new DataIntegrityProof({
  signer: ecdsaKeyPair.signer(),
  cryptosuite: createSignCryptosuite({
    // require the `issuer` and `issuanceDate` fields to always be disclosed
    // by the holder (presenter)
    mandatoryPointers: [
      '/issuanceDate',
      '/issuer'
    ]
  })
});
// use a proof ID to enable it to be found and transformed into a disclosure
// proof by the holder later
const proofId = `urn:uuid:${uuid()}`;
suite.proof = {id: proofId};

const signedVC = await vc.issue({credential, suite, documentLoader});
console.log(JSON.stringify(signedVC, null, 2));

衍生出一种选择性披露

说明: 这一步骤是作为可核查证书的持有者履行的,而不是作为 一个发行商.

先决条件:

  • 你有一个可核查的证书 发行使用密码套件 支持选择性披露,例如: ecdsa-sd-2023
  • 如果你使用习惯 @context,确保它可以解决
import * as vc from '@digitalbazaar/vc';
import * as ecdsaSd2023Cryptosuite from
  '@digitalbazaar/ecdsa-sd-2023-cryptosuite';
import {DataIntegrityProof} from '@digitalbazaar/data-integrity';

const {
  createDiscloseCryptosuite,
  createSignCryptosuite,
  createVerifyCryptosuite
} = ecdsaSd2023Cryptosuite;

// sample signed credential
const credential = {
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://www.w3.org/2018/credentials/examples/v1",
    "https://w3id.org/security/data-integrity/v2"
  ],
  "id": "http://example.edu/credentials/1872",
  "type": [
    "VerifiableCredential",
    "AlumniCredential"
  ],
  "issuer": "https://example.edu/issuers/565049",
  "issuanceDate": "2010-01-01T19:23:24Z",
  "credentialSubject": {
    "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
    "alumniOf": "<span lang=\"en\">Example University</span>"
  },
  "proof": {
    "id": "urn:uuid:2ef8c7ce-a4da-44b4-ba7f-3d43eaf1e50c",
    "type": "DataIntegrityProof",
    "created": "2023-11-13T22:58:06Z",
    "verificationMethod": "https://example.edu/issuers/keys/2",
    "cryptosuite": "ecdsa-sd-2023",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0AhVhAtYPKUQxwULXzMdsAfqtipsiX6YEPURYSBFYxoFY-v0vCPyAs1Ckyy61Wtk3xZWyBGNaEr3w0wQiJHHd5B9uR-1gjgCQCVtFPMk-ECi0CJFYv_GTjCChf8St0FQjuExTAnwP0-ipYIOHSun3YqabOfNe2DYFkHBTZa0Csf1a7YUDW8hhsOHqTglhA8aqnyanT-Ybo2-aHBTcI-UmHX0iluGb2IxoHLLhQoOPm2rDW0eB04Fa2Dh6WMKoOl_Bz3wZZDGQ31XoGrQvgIlhAo8qspvC-QQ-xI3KADiA12sO5LRsZ7hl9ozoJEECVsDOKlxWd-dhices5b2ZQIiiRE9XxxJx8YuwCMoD2bRLbOIJtL2lzc3VhbmNlRGF0ZWcvaXNzdWVy"
  }
};

// note no `signer` needed; the selective disclosure credential will be
// derived from the base proof already provided by the issuer
const suite = new DataIntegrityProof({
  cryptosuite: createDiscloseCryptosuite({
    // the ID of the base proof to convert to a disclosure proof
    proofId: 'urn:uuid:da088899-3439-41ea-a580-af3f1cf98cd3',
    // selectively disclose the entire credential subject; different JSON
    // pointers could be provided to selectively disclose different information;
    // the issuer will have mandatory fields that will be automatically
    // disclosed such as the `issuer` and `issuanceDate` fields
    selectivePointers: [
      '/credentialSubject'
    ]
  })
});

const derivedVC = await vc.derive({
  verifiableCredential, suite, documentLoader
});
console.log(JSON.stringify(derivedVC, null, 2));

创建可验证的演示文稿

先决条件:

  • 您拥有必要的私人密钥( 带有 ID 和控制器) 和 相应套间
  • 如果你使用习惯 @context,确保它可以解决
  • (建议) 你有一个策略 在哪里发布你的主计长 文件和公用钥匙

创建未签名的演示文稿

要从一个或多个可核查的证书创建演示文稿,您可以 使用该 createPresentation() 方便功能. 或者,你可以 手动创建演示文稿对象(不要忘记设置) @context 财务报告和审定财务报表 type 属性).

用自定义创建可核查的演示文稿 @context 字段使用 a 自定义文档Loader

const verifiableCredential = [vc1, vc2]; // either array or single object

// optional `id` and `holder`
const id = 'ebc6f1c2';
const holder = 'did:ex:12345';

const presentation = vc.createPresentation({
  verifiableCredential, id, holder
});

console.log(JSON.stringify(presentation, null, 2));
// ->
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1"
  ],
  "type": [
    "VerifiablePresentation"
  ],
  "id": "ebc6f1c2",
  "holder": "did:ex:12345",
  "verifiableCredential": [
    // vc1:
    {
      "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://www.w3.org/2018/credentials/examples/v1"
      ],
      "id": "http://example.edu/credentials/1872",
      "type": [
        "VerifiableCredential",
        "AlumniCredential"
      ],
      "issuer": "https://example.edu/issuers/565049",
      "issuanceDate": "2010-01-01T19:23:24Z",
      "credentialSubject": {
        "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
        "alumniOf": "<span lang=\"en\">Example University</span>"
      },
      "proof": {
        "type": "Ed25519Signature2018",
        "created": "2020-02-03T17:23:49Z",
        "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..AUQ3AJ23WM5vMOWNtYKuqZBekRAOUibOMH9XuvOd39my1sO-X9R4QyAXLD2ospssLvIuwmQVhJa-F0xMOnkvBg",
        "proofPurpose": "assertionMethod",
        "verificationMethod": "https://example.edu/issuers/keys/1"
      }
    },
    // vc2 goes here ...
  ]
}

请注意,这会造成 未签名 演示文稿( 可能有效) (有些情况).

自定义文档Loader

先决条件:

  • 您有一个有效的 JSON- LD @context。 。 。 .
  • 您的自定义上下文可以在地址中解决 .
// jsonld-signatures has a secure context loader
// by requiring this first you ensure security
// contexts are loaded from jsonld-signatures
// and not an insecure source.
import vc from '@digitalcredentials/vc';
import { securityLoader } from '@digitalcredentials/security-document-loader';

const documentLoader = securityLoader().build();

const vp = await vc.signPresentation({
  presentation, suite, challenge, documentLoader
});

// or
const signedVC = await vc.issue({credential, suite, documentLoader});

// or
const result = await vc.verifyCredential({credential: signedVC, suite, documentLoader});

签署陈述

一旦你创建了演示文稿(或者通过 createPresentation() 或者说 手动,可以使用 signPresentation()数字 :

const vp = await vc.signPresentation({
  presentation, suite, challenge, documentLoader
});

console.log(JSON.stringify(vp, null, 2));
// ->
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1"
  ],
  "type": [
    "VerifiablePresentation"
  ],
  "verifiableCredential": [
    {
      "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://www.w3.org/2018/credentials/examples/v1"
      ],
      "id": "http://example.edu/credentials/1872",
      "type": [
        "VerifiableCredential",
        "AlumniCredential"
      ],
      "issuer": "https://example.edu/issuers/565049",
      "issuanceDate": "2010-01-01T19:23:24Z",
      "credentialSubject": {
        "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
        "alumniOf": "<span lang=\"en\">Example University</span>"
      },
      "proof": {
        "type": "Ed25519Signature2018",
        "created": "2020-02-03T17:23:49Z",
        "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..AUQ3AJ23WM5vMOWNtYKuqZBekRAOUibOMH9XuvOd39my1sO-X9R4QyAXLD2ospssLvIuwmQVhJa-F0xMOnkvBg",
        "proofPurpose": "assertionMethod",
        "verificationMethod": "https://example.edu/issuers/keys/1"
      }
    }
  ],
  "id": "ebc6f1c2",
  "holder": "did:ex:holder123",
  "proof": {
    "type": "Ed25519Signature2018",
    "created": "2019-02-03T17:23:49Z",
    "challenge": "12ec21",
    "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..ZO4Lkq8-fOruE4oUvuMaxepGX-vLD2gPyNIsz-iA7X0tzC3_96djaBYDxxl6wD1xKrx0h60NjI9i9p_MxoXkDQ",
    "proofPurpose": "authentication",
    "verificationMethod": "https://example.edu/issuers/keys/1"
  }
}

验证可验证的演示文稿

先决条件:

  • 您的风俗 @contexts、核查方法(如公用钥匙)及其 相应的控制器文档可以通过一个 documentLoader。 。 。 .

为核实可核查的列报:

// challenge has been received from the requesting party - see 'challenge'
// section below
import vc from '@digitalcredentials/vc';
import { securityLoader } from '@digitalcredentials/security-document-loader';

const documentLoader = securityLoader().build();

const result = await vc.verify({presentation, challenge, suite, documentLoader});
// {valid: true}

默认, verify() 如果出现错误,则会投出错误 proof 区域缺失. 为了验证未签名的演示文稿,您必须设置 unsignedPresentation 旗帜 :

const result = await vc.verify({
  presentation, suite, documentLoader, unsignedPresentation: true
});
// {valid: true}

challenge 参数

可核查的演示文稿通常用于认证目的. A 类 challenge parm (类似于 nonce 在 OAuth2/ OpenID 连接中提供 并阻止节目重播 攻击。 工作流程如下:

  1. 接收方要求提供可核实的陈述,并提供 challenge 参数.
  2. 创建 VP 的客户端代码在此挑战中通过(来自请求) 党),并被包括在"副总统"中.
  3. 客户端代码将VP传递给接收方,接收方随后检查到 确保 challenge 与请求中提供的相同 在1页.

验证可验证的证书

在大多数情况下,可核查的全权证书将用可核查的 演示文稿和整个副总统应加以核实。 然而,这个图书馆 提供一种功能来验证可验证的证书.

先决条件:

  • 您的风俗 @contexts、核查方法(如公用钥匙)及其 相应的控制器文档可以通过一个 documentLoader。 。 。 .

核查可核查的证明:

const suite = new Ed25519Signature2020();
const result = await vc.verifyCredential({credential: signedVC, suite, documentLoader});
// {valid: true}

核查可核查的选择性披露证书,确保套件 支持,例如:

import * as ecdsaSd2023Cryptosuite from
  '@digitalbazaar/ecdsa-sd-2023-cryptosuite';
import {DataIntegrityProof} from '@digitalbazaar/data-integrity';

const {
  createDiscloseCryptosuite,
  createSignCryptosuite,
  createVerifyCryptosuite
} = ecdsaSd2023Cryptosuite;

const suite = new DataIntegrityProof({
  cryptosuite: createVerifyCryptosuite()
});
const result = await vc.verifyCredential({credential, suite, documentLoader});
// {valid: true}

以习惯验证可核查的证书 @context 字段使用 a 自定义文档Loader

测试

进行Mocha测试:

npm run test-node

进行Karma(浏览器)测试:

npm run test-karma

贡献

见 贡献文件来啊!

公关接受.

注:如果编辑Readme,请遵照 标准读取 规格.

许可证

  • MIT许可证 - DCC - TypeScript兼容.
  • 新BSD许可证 (3-clause) 2020-2021 Digital Bazaar - 初始实施.

版本与发布记录

@digitalcredentials/vc 共发布 28 个版本,首次发布于 2021/05/20;过去 12 个月发布了 1 个版本。

版本发布日期距今
10.0.2latest2025/11/2011 个月前
10.0.12025/10/031.1 年前
10.0.02025/05/011.5 年前
10.0.0-beta.1beta2025/03/141.7 年前
9.0.2-beta.32025/03/121.7 年前
9.0.1-beta.22025/01/271.8 年前

关于 @digitalcredentials/vc 的常见问题

@digitalcredentials/vc 是什么?

可验证的证书 JavaScript 库.

如何安装 @digitalcredentials/vc?

在项目目录运行 npm install @digitalcredentials/vc,或使用 pnpm add / yarn add / bun add。

@digitalcredentials/vc 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/digitalcredentials__vc 是否存在。

@digitalcredentials/vc 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@digitalcredentials/vc 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@digitalcredentials/vc 可以商用吗?

@digitalcredentials/vc 使用 BSD-3-Clause 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。另外不得用原作者名义为衍生产品背书。以上为概括,不构成法律意见,请以许可原文为准。

@digitalcredentials/vc 的下载量有多少?

根据 npm 官方下载统计,@digitalcredentials/vc 在 2026/10/12 – 2026/11/10 这 30 天内被下载 80,129 次,日均约 2,671 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@digitalcredentials/vc 还在维护吗?

最新版本 10.0.2 发布于 2025/11/20(11 个月前);至今共发布 28 个版本,其中过去 12 个月发布了 1 个;首次发布于 2021/05/20。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。