diff --git a/lib/helpers.js b/lib/helpers.js index 4d44afb3..012a2f3c 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -85,7 +85,9 @@ export async function getIssuerAndSuite({ cause }); } - const suite = createSuite({signer: assertionMethodKey, config, options}); + const suite = await createSuite({ + signer: assertionMethodKey, config, options + }); return {issuer, suite}; } diff --git a/lib/suites.js b/lib/suites.js index 4d3729f6..0ed0ff78 100644 --- a/lib/suites.js +++ b/lib/suites.js @@ -1,7 +1,11 @@ /*! - * Copyright (c) 2019-2023 Digital Bazaar, Inc. All rights reserved. + * Copyright (c) 2019-2024 Digital Bazaar, Inc. All rights reserved. */ import * as bedrock from '@bedrock/core'; +import * as Bls12381Multikey from '@digitalbazaar/bls12-381-multikey'; +import { + createSignCryptosuite as createBbs2023SignCryptosuite +} from '@digitalbazaar/bbs-2023-cryptosuite'; import { createSignCryptosuite as createEcdsaSd2023SignCryptosuite } from '@digitalbazaar/ecdsa-sd-2023-cryptosuite'; @@ -50,7 +54,10 @@ const SUPPORTED_SUITES = new Map([ }], [createEcdsaXi2023SignCryptosuite().name, { createSuite: _createEcdsaXi2023Suite - }] + }], + [createBbs2023SignCryptosuite().name, { + createSuite: _createBbs2023Suite + }], ]); const {util: {BedrockError}} = bedrock; @@ -160,6 +167,26 @@ function _createEcdsaXi2023Suite({signer, options} = {}) { }); } +async function _createBbs2023Suite({signer, options} = {}) { + // BBS requires signer public key + const {publicKeyMultibase} = await signer.getKeyDescription(); + const {publicKey} = await Bls12381Multikey.from({publicKeyMultibase}); + signer.publicKey = publicKey; + + const mandatoryPointers = options?.mandatoryPointers || + ['/issuer', '/issuanceDate']; + const cryptosuite = createBbs2023SignCryptosuite({ + mandatoryPointers + }); + const diProof = new DataIntegrityProof({ + signer, + date: _getISODateTime(), + cryptosuite + }); + diProof.proof = {id: `urn:uuid:${uuid()}`}; + return diProof; +} + function _getISODateTime(date = new Date()) { // remove milliseconds precision return date.toISOString().replace(/\.\d+Z$/, 'Z'); diff --git a/package.json b/package.json index 94b7bc3e..7e0f102b 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,9 @@ }, "homepage": "https://github.com/digitalbazaar/bedrock-vc-issuer", "dependencies": { + "@digitalbazaar/bbs-2023-cryptosuite": "^1.2.0", "@digitalbazaar/bitstring": "^3.0.0", + "@digitalbazaar/bls12-381-multikey": "^1.3.0", "@digitalbazaar/data-integrity": "^2.0.0", "@digitalbazaar/ecdsa-2019-cryptosuite": "^2.0.0", "@digitalbazaar/ecdsa-rdfc-2019-cryptosuite": "^1.0.1", @@ -42,7 +44,7 @@ "@digitalbazaar/eddsa-rdfc-2022-cryptosuite": "^1.0.1", "@digitalbazaar/lru-memoize": "^3.0.0", "@digitalbazaar/vc": "github:digitalbazaar/vc#vc-2.0-time-props", - "@digitalbazaar/webkms-client": "^13.0.0", + "@digitalbazaar/webkms-client": "^14.1.0", "assert-plus": "^1.0.0", "base64url-universal": "2.0.0", "bnid": "^3.0.0", diff --git a/schemas/bedrock-vc-issuer.js b/schemas/bedrock-vc-issuer.js index 6e38582d..69d3cdb2 100644 --- a/schemas/bedrock-vc-issuer.js +++ b/schemas/bedrock-vc-issuer.js @@ -26,7 +26,8 @@ export const issueOptions = { // supported default suites in this version enum: [ 'ecdsa-rdfc-2019', 'eddsa-rdfc-2022', 'Ed25519Signature2020', - 'Ed25519Signature2018', 'ecdsa-sd-2023', 'ecdsa-xi-2023' + 'Ed25519Signature2018', 'ecdsa-sd-2023', 'ecdsa-xi-2023', + 'bbs-2023' ] } } diff --git a/test/mocha/20-credentials.js b/test/mocha/20-credentials.js index 740af771..981c36f5 100644 --- a/test/mocha/20-credentials.js +++ b/test/mocha/20-credentials.js @@ -60,6 +60,15 @@ describe('issue APIs', () => { statusOptions: { suiteName: 'ecdsa-rdfc-2019' } + }, + 'bbs-2023': { + algorithm: ['Bls12381G2'], + statusOptions: { + // sign status list with simple ECDSA + algorithm: 'P-256', + suiteName: 'ecdsa-rdfc-2019' + }, + terseIssueOptions: {mandatoryPointers: ['issuer']} } }; // list of suites to run the selective disclosure tests on @@ -134,7 +143,7 @@ describe('issue APIs', () => { let assertionMethodKey; const publicAliasTemplate = 'did:key:{publicKeyMultibase}#{publicKeyMultibase}'; - if(algorithm === 'P-256' || algorithm === 'P-384') { + if(['P-256', 'P-384', 'Bls12381G2'].includes(algorithm)) { assertionMethodKey = await helpers._generateMultikey({ keystoreAgent, type: `urn:webkms:multikey:${algorithm}`, diff --git a/test/mocha/helpers.js b/test/mocha/helpers.js index be4d4ba6..52c974f0 100644 --- a/test/mocha/helpers.js +++ b/test/mocha/helpers.js @@ -367,8 +367,10 @@ export async function provisionIssuerForStatus({ let assertionMethodKey; const publicAliasTemplate = 'did:key:{publicKeyMultibase}#{publicKeyMultibase}'; - const {algorithm, statusOptions: {suiteName}} = suiteOptions; - if(algorithm === 'P-256' || algorithm === 'P-384') { + const {statusOptions} = suiteOptions; + const algorithm = statusOptions.algorithm ?? suiteOptions.algorithm; + const {suiteName} = statusOptions; + if(['P-256', 'P-384'].includes(algorithm)) { assertionMethodKey = await _generateMultikey({ keystoreAgent, type: `urn:webkms:multikey:${algorithm}`, diff --git a/test/package.json b/test/package.json index 3c6d4af6..bc21a570 100644 --- a/test/package.json +++ b/test/package.json @@ -36,7 +36,7 @@ "@bedrock/service-agent": "^8.0.0", "@bedrock/service-context-store": "^11.0.0", "@bedrock/service-core": "^9.0.0", - "@bedrock/ssm-mongodb": "^11.0.0", + "@bedrock/ssm-mongodb": "^11.2.0", "@bedrock/test": "^8.0.5", "@bedrock/validation": "^7.0.0", "@bedrock/vc-issuer": "file:..", @@ -50,7 +50,7 @@ "@digitalbazaar/http-client": "^4.0.0", "@digitalbazaar/vc-bitstring-status-list": "github:digitalbazaar/vc-bitstring-status-list#main", "@digitalbazaar/vc-status-list": "^7.1.0", - "@digitalbazaar/webkms-client": "^14.0.0", + "@digitalbazaar/webkms-client": "^14.1.0", "c8": "^9.1.0", "cross-env": "^7.0.3", "jose": "^4.8.3",