From 9cf4d99e3ebd87d2da1d6da6815ea08f0c23adf2 Mon Sep 17 00:00:00 2001 From: Antonio Date: Mon, 20 Sep 2021 08:06:43 +0200 Subject: [PATCH] feat: add support for exporting DID details to W3C-compliant DID Document (#411) * Merge branch 'develop' into aa-w3c-diddoc-exporter Co-authored-by: Antonio Antonino * feat: add export to DID Document for light DIDs * test: add unit tests for light DID to DID Document export * test: add more tests for different keys for light DID W3C exporter * test: add edge cases for light DID Document exporter * test: add unit tests for full DID details exporting * chore: move exportToDidDocument to utils file * chore: restructure code to support multiple DID Document formats * chore: restructure code to support multiple DID Document formats pt. 2 * Merge branch 'develop' into aa-w3c-diddoc-exporter * fix: fix after merging from develop * fix: fix unit tests for DID exporter * chore: refactor imports * chore: remove unused .toDidDocument() * fix: unused import * doc: add README for DIDDocument exporter * doc: add missing import statement in exporter README * chore: bump packages version to 0.24.1-rc.1 * fix: do not include empty fields in final DID Document * fix: update naming to match universal resolver * fix: revert version to 0.24.0-1 * chore: add comment about allowed values to export a DID Document * test: add completed DID Document in exporter test cases * chore: minor refinements Co-authored-by: Raphael Flechtner <39338561+rflechtner@users.noreply.github.com> --- packages/kilt-did/README.md | 37 +- .../src/DidDetails/FullDidDetails.spec.ts | 3 +- .../src/DidDetails/LightDidDetails.spec.ts | 4 +- .../DidDocumentExporter.spec.ts | 450 ++++++++++++++++++ .../DidDocumentExporter.ts | 134 ++++++ .../src/DidDocumentExporter/README.md | 52 ++ .../kilt-did/src/DidDocumentExporter/index.ts | 17 + packages/kilt-did/src/index.ts | 1 + packages/kilt-did/src/types.ts | 15 + packages/sdk-js/package.json | 1 + packages/sdk-js/src/index.ts | 5 +- packages/types/src/DidDocumentExporter.ts | 55 +++ packages/types/src/index.ts | 1 + packages/vc-export/src/constants.ts | 8 - packages/vc-export/src/verificationUtils.ts | 11 +- yarn.lock | 1 + 16 files changed, 760 insertions(+), 35 deletions(-) create mode 100644 packages/kilt-did/src/DidDocumentExporter/DidDocumentExporter.spec.ts create mode 100644 packages/kilt-did/src/DidDocumentExporter/DidDocumentExporter.ts create mode 100644 packages/kilt-did/src/DidDocumentExporter/README.md create mode 100644 packages/kilt-did/src/DidDocumentExporter/index.ts create mode 100644 packages/types/src/DidDocumentExporter.ts diff --git a/packages/kilt-did/README.md b/packages/kilt-did/README.md index d2c372b32..a3eda1459 100644 --- a/packages/kilt-did/README.md +++ b/packages/kilt-did/README.md @@ -59,9 +59,7 @@ const authenticationKeyPublicDetails = await keystore.generateKeypair({ const lightDID = new LightDidDetails({ authenticationKey: { publicKey: authenticationKeyPublicDetails.publicKey, - type: DemoKeystore.getKeypairTypeForAlg( - authenticationKeyPublicDetails.alg - ) + type: DemoKeystore.getKeypairTypeForAlg(authenticationKeyPublicDetails.alg), }, }) // Will print `did:kilt:light:014sxSYXakw1ZXBymzT9t3Yw91mUaqKST5bFUEjGEpvkTuckar`. @@ -102,15 +100,11 @@ const serviceEndpoints: IServiceDetails[] = [ const lightDID = new LightDidDetails({ authenticationKey: { publicKey: authenticationKeyPublicDetails.publicKey, - type: DemoKeystore.getKeypairTypeForAlg( - authenticationKeyPublicDetails.alg - ), + type: DemoKeystore.getKeypairTypeForAlg(authenticationKeyPublicDetails.alg), }, encryptionKey: { publicKey: encryptionKeyPublicDetails.publicKey, - type: DemoKeystore.getKeypairTypeForAlg( - encryptionKeyPublicDetails.alg - ), + type: DemoKeystore.getKeypairTypeForAlg(encryptionKeyPublicDetails.alg), }, services: serviceEndpoints, }) @@ -151,11 +145,17 @@ import { FullDidDetails, SigningAlgorithms, } from '@kiltprotocol/did' -import { getDeleteDidExtrinsic, getSetKeyExtrinsic } from '@kiltprotocol/did/src/Did.chain' +import { + getDeleteDidExtrinsic, + getSetKeyExtrinsic, +} from '@kiltprotocol/did/src/Did.chain' import { KeyRelationship } from '@kiltprotocol/types' // Configure the resolution promise to wait for transactions to be finalized or simply included in a block depending on the environment. -const resolveOn = process.env.NODE_ENV === 'production' ? BlockchainUtils.IS_FINALIZED : BlockchainUtils.IS_IN_BLOCK +const resolveOn = + process.env.NODE_ENV === 'production' + ? BlockchainUtils.IS_FINALIZED + : BlockchainUtils.IS_IN_BLOCK // Initialise connection to the public KILT test network. await kiltInit({ address: 'wss://kilt-peregrine-k8s.kilt.io' }) @@ -185,9 +185,7 @@ const authenticationKeyPublicDetails = await keystore.generateKeypair({ const { extrinsic, did } = await DidUtils.writeDidFromPublicKeys(keystore, { [KeyRelationship.authentication]: { publicKey: authenticationKeyPublicDetails.publicKey, - type: DemoKeystore.getKeypairTypeForAlg( - authenticationKeyPublicDetails.alg - ), + type: DemoKeystore.getKeypairTypeForAlg(authenticationKeyPublicDetails.alg), }, }) // Will print `did:kilt:4sxSYXakw1ZXBymzT9t3Yw91mUaqKST5bFUEjGEpvkTuckar`. @@ -205,7 +203,10 @@ const fullDid = await DefaultResolver.resolveDoc(did) If additional keys and external services are to be specified, then they can be included in the DID create operation. ```typescript -const resolveOn = process.env.NODE_ENV === 'production' ? BlockchainUtils.IS_FINALIZED : BlockchainUtils.IS_IN_BLOCK +const resolveOn = + process.env.NODE_ENV === 'production' + ? BlockchainUtils.IS_FINALIZED + : BlockchainUtils.IS_IN_BLOCK await kiltInit({ address: 'wss://kilt-peregrine-k8s.kilt.io' }) @@ -255,9 +256,7 @@ const { extrinsic, did } = await DidUtils.writeDidFromPublicKeys( }, [KeyRelationship.keyAgreement]: { publicKey: encryptionKeyPublicDetails.publicKey, - type: DemoKeystore.getKeypairTypeForAlg( - encryptionKeyPublicDetails.alg - ), + type: DemoKeystore.getKeypairTypeForAlg(encryptionKeyPublicDetails.alg), }, }, serviceEndpoints @@ -340,4 +339,4 @@ await BlockchainUtils.signAndSubmitTx( ## Migrating a light DID to a full DID -This feature is a work in progress and this section will be updated when it will be added to the SDK. \ No newline at end of file +This feature is a work in progress and this section will be updated when it will be added to the SDK. diff --git a/packages/kilt-did/src/DidDetails/FullDidDetails.spec.ts b/packages/kilt-did/src/DidDetails/FullDidDetails.spec.ts index 61b4273b5..341c7cb64 100644 --- a/packages/kilt-did/src/DidDetails/FullDidDetails.spec.ts +++ b/packages/kilt-did/src/DidDetails/FullDidDetails.spec.ts @@ -11,13 +11,14 @@ import { KeyRelationship } from '@kiltprotocol/types' import { BN } from '@polkadot/util' +import type { IDidKeyDetails } from '@kiltprotocol/types' import { mapCallToKeyRelationship } from './FullDidDetails.utils' import { FullDidDetails, FullDidDetailsCreationOpts } from './FullDidDetails' describe('functional tests', () => { const identifier = '4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e' const did = `did:kilt:${identifier}` - const keys = [ + const keys: IDidKeyDetails[] = [ { id: `${did}#1`, controller: did, diff --git a/packages/kilt-did/src/DidDetails/LightDidDetails.spec.ts b/packages/kilt-did/src/DidDetails/LightDidDetails.spec.ts index 196f400f6..5d7817a59 100644 --- a/packages/kilt-did/src/DidDetails/LightDidDetails.spec.ts +++ b/packages/kilt-did/src/DidDetails/LightDidDetails.spec.ts @@ -11,9 +11,9 @@ * @group unit/did */ -import { Crypto } from '@kiltprotocol/utils' import type { IServiceDetails } from '@kiltprotocol/types' import { hexToU8a } from '@polkadot/util' +import { encodeAddress } from '@polkadot/util-crypto' import { LightDidDetails, LightDidDetailsCreationOpts } from './LightDidDetails' import type { INewPublicKey } from '../types' @@ -24,7 +24,7 @@ describe('Light DID v1 tests', () => { const encPublicKey = hexToU8a( '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ) - const address = Crypto.encodeAddress(authPublicKey, 38) + const address = encodeAddress(authPublicKey, 38) const authenticationDidKeyDetails: INewPublicKey = { publicKey: authPublicKey, type: 'ed25519', diff --git a/packages/kilt-did/src/DidDocumentExporter/DidDocumentExporter.spec.ts b/packages/kilt-did/src/DidDocumentExporter/DidDocumentExporter.spec.ts new file mode 100644 index 000000000..d10700532 --- /dev/null +++ b/packages/kilt-did/src/DidDocumentExporter/DidDocumentExporter.spec.ts @@ -0,0 +1,450 @@ +/** + * Copyright 2018-2021 BOTLabs GmbH. + * + * This source code is licensed under the BSD 4-Clause "Original" license + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * @group unit/did + */ + +import { KeyRelationship } from '@kiltprotocol/types' +import { BN, hexToU8a } from '@polkadot/util' +import type { IDidKeyDetails, IServiceDetails } from '@kiltprotocol/types' +import type { INewPublicKey } from '../types' +import { + FullDidDetails, + FullDidDetailsCreationOpts, +} from '../DidDetails/FullDidDetails' +import { + LightDidDetails, + LightDidDetailsCreationOpts, +} from '../DidDetails/LightDidDetails' +import { exportToDidDocument } from './DidDocumentExporter' + +describe('Full DID Document exporting tests', () => { + const identifier = '4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e' + const did = `did:kilt:${identifier}` + const keys: IDidKeyDetails[] = [ + { + id: `${did}#1`, + controller: did, + includedAt: 100, + type: 'ed25519', + publicKeyHex: + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + }, + { + id: `${did}#2`, + controller: did, + includedAt: 250, + type: 'x25519', + publicKeyHex: + '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', + }, + { + id: `${did}#3`, + controller: did, + includedAt: 250, + type: 'x25519', + publicKeyHex: + '0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + }, + { + id: `${did}#4`, + controller: did, + includedAt: 200, + type: 'sr25519', + publicKeyHex: + '0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', + }, + ] + const services = [ + { + id: `${did}#service1`, + type: 'messaging', + serviceEndpoint: 'example.com', + }, + { + id: `${did}#service2`, + type: 'telephone', + serviceEndpoint: '123344', + }, + ] + const didDetails: FullDidDetailsCreationOpts = { + did, + keys, + keyRelationships: { + [KeyRelationship.authentication]: [keys[0].id], + [KeyRelationship.keyAgreement]: [keys[1].id, keys[2].id], + [KeyRelationship.assertionMethod]: [keys[3].id], + }, + lastTxIndex: new BN(10), + services, + } + + it('exports the expected application/json W3C DID Document with an Ed25519 authentication key, two x25519 encryption keys, an Sr25519 assertion key, an Ecdsa delegation key, and some service endpoints', () => { + const ecdsaKey: IDidKeyDetails = { + id: `${did}#5`, + controller: did, + includedAt: 200, + type: 'ecdsa', + publicKeyHex: + '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', + } + const fullDidDetails = new FullDidDetails({ + ...didDetails, + keyRelationships: { + [KeyRelationship.authentication]: [keys[0].id], + [KeyRelationship.keyAgreement]: [keys[1].id, keys[2].id], + [KeyRelationship.assertionMethod]: [keys[3].id], + [KeyRelationship.capabilityDelegation]: [ecdsaKey.id], + }, + keys: keys.concat([ecdsaKey]), + }) + + const didDoc = exportToDidDocument(fullDidDetails, 'application/json') + + expect(didDoc).toStrictEqual({ + id: 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e', + verificationMethod: [ + { + id: 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#1', + controller: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e', + type: 'Ed25519VerificationKey2018', + publicKeyBase58: 'CVDFLCAjXhVWiPXH9nTCTpCgVzmDVoiPzNJYuccr1dqB', + }, + { + id: 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#2', + controller: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e', + type: 'X25519KeyAgreementKey2019', + publicKeyBase58: 'DdqGmK5uamYN5vmuZrzpQhKeehLdwtPLVJdhu5P2iJKC', + }, + { + id: 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#3', + controller: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e', + type: 'X25519KeyAgreementKey2019', + publicKeyBase58: 'EnTJCS15dqbDTU2XywYSMaScoPv4Py4GzExrtY9DQxoD', + }, + { + id: 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#4', + controller: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e', + type: 'Sr25519VerificationKey2020', + publicKeyBase58: 'Fw5KdYvFgue4q1HAQ264JTZax6VUr3jDVBJ1szuQ7dHE', + }, + { + id: 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#5', + controller: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e', + type: 'EcdsaSecp256k1VerificationKey2019', + publicKeyBase58: '2pEER9q8Tu5XVwfBQeU2NE883JsUTX9jbbmVg3SL1g2fKCSd17', + }, + ], + authentication: [ + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#1', + ], + keyAgreement: [ + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#2', + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#3', + ], + assertionMethod: [ + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#4', + ], + capabilityDelegation: [ + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#5', + ], + service: [ + { + id: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#service1', + type: 'messaging', + serviceEndpoint: 'example.com', + }, + { + id: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#service2', + type: 'telephone', + serviceEndpoint: '123344', + }, + ], + }) + }) + + it('exports the expected application/ld+json W3C DID Document with only an authentication key', () => { + const ecdsaKey: IDidKeyDetails = { + id: `${did}#5`, + controller: did, + includedAt: 200, + type: 'ecdsa', + publicKeyHex: + '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', + } + const fullDidDetails = new FullDidDetails({ + ...didDetails, + keyRelationships: { + [KeyRelationship.authentication]: [keys[0].id], + [KeyRelationship.keyAgreement]: [keys[1].id, keys[2].id], + [KeyRelationship.assertionMethod]: [keys[3].id], + [KeyRelationship.capabilityDelegation]: [ecdsaKey.id], + }, + keys: keys.concat([ecdsaKey]), + }) + + const didDoc = exportToDidDocument(fullDidDetails, 'application/ld+json') + + expect(didDoc).toStrictEqual({ + '@context': ['https://www.w3.org/ns/did/v1'], + id: 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e', + verificationMethod: [ + { + id: 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#1', + controller: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e', + type: 'Ed25519VerificationKey2018', + publicKeyBase58: 'CVDFLCAjXhVWiPXH9nTCTpCgVzmDVoiPzNJYuccr1dqB', + }, + { + id: 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#2', + controller: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e', + type: 'X25519KeyAgreementKey2019', + publicKeyBase58: 'DdqGmK5uamYN5vmuZrzpQhKeehLdwtPLVJdhu5P2iJKC', + }, + { + id: 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#3', + controller: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e', + type: 'X25519KeyAgreementKey2019', + publicKeyBase58: 'EnTJCS15dqbDTU2XywYSMaScoPv4Py4GzExrtY9DQxoD', + }, + { + id: 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#4', + controller: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e', + type: 'Sr25519VerificationKey2020', + publicKeyBase58: 'Fw5KdYvFgue4q1HAQ264JTZax6VUr3jDVBJ1szuQ7dHE', + }, + { + id: 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#5', + controller: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e', + type: 'EcdsaSecp256k1VerificationKey2019', + publicKeyBase58: '2pEER9q8Tu5XVwfBQeU2NE883JsUTX9jbbmVg3SL1g2fKCSd17', + }, + ], + authentication: [ + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#1', + ], + keyAgreement: [ + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#2', + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#3', + ], + assertionMethod: [ + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#4', + ], + capabilityDelegation: [ + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#5', + ], + service: [ + { + id: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#service1', + type: 'messaging', + serviceEndpoint: 'example.com', + }, + { + id: + 'did:kilt:4rp4rcDHP71YrBNvDhcH5iRoM3YzVoQVnCZvQPwPom9bjo2e#service2', + type: 'telephone', + serviceEndpoint: '123344', + }, + ], + }) + }) +}) + +describe('Light DID Document exporting tests', () => { + const authPublicKey = hexToU8a( + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + ) + const encPublicKey = hexToU8a( + '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + ) + let authenticationDidKeyDetails: INewPublicKey = { + publicKey: authPublicKey, + type: 'ed25519', + } + let encryptionDidKeyDetails: INewPublicKey | undefined + let services: IServiceDetails[] | undefined + + it('exports the expected application/json W3C DID Document with an Ed25519 authentication key, an x25519 encryption key, and some service endpoints', () => { + encryptionDidKeyDetails = { + publicKey: encPublicKey, + type: 'x25519', + } + services = [ + { + id: `service1`, + type: 'messaging', + serviceEndpoint: 'example.com', + }, + { + id: `service2`, + type: 'telephone', + serviceEndpoint: '123344', + }, + ] + + const didCreationDetails: LightDidDetailsCreationOpts = { + authenticationKey: authenticationDidKeyDetails, + encryptionKey: encryptionDidKeyDetails, + services, + } + const didDetails = new LightDidDetails(didCreationDetails) + const didDoc = exportToDidDocument(didDetails, 'application/json') + + expect(didDoc).toStrictEqual({ + id: + 'did:kilt:light:014rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF:omFlomlwdWJsaWNLZXlYILu7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7ZHR5cGVmeDI1NTE5YXOCo2JpZGhzZXJ2aWNlMWR0eXBlaW1lc3NhZ2luZ29zZXJ2aWNlRW5kcG9pbnRrZXhhbXBsZS5jb22jYmlkaHNlcnZpY2UyZHR5cGVpdGVsZXBob25lb3NlcnZpY2VFbmRwb2ludGYxMjMzNDQ=', + verificationMethod: [ + { + id: + 'did:kilt:light:014rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF:omFlomlwdWJsaWNLZXlYILu7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7ZHR5cGVmeDI1NTE5YXOCo2JpZGhzZXJ2aWNlMWR0eXBlaW1lc3NhZ2luZ29zZXJ2aWNlRW5kcG9pbnRrZXhhbXBsZS5jb22jYmlkaHNlcnZpY2UyZHR5cGVpdGVsZXBob25lb3NlcnZpY2VFbmRwb2ludGYxMjMzNDQ=#authentication', + controller: + 'did:kilt:light:014rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF:omFlomlwdWJsaWNLZXlYILu7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7ZHR5cGVmeDI1NTE5YXOCo2JpZGhzZXJ2aWNlMWR0eXBlaW1lc3NhZ2luZ29zZXJ2aWNlRW5kcG9pbnRrZXhhbXBsZS5jb22jYmlkaHNlcnZpY2UyZHR5cGVpdGVsZXBob25lb3NlcnZpY2VFbmRwb2ludGYxMjMzNDQ=', + type: 'Ed25519VerificationKey2018', + publicKeyBase58: 'CVDFLCAjXhVWiPXH9nTCTpCgVzmDVoiPzNJYuccr1dqB', + }, + { + id: + 'did:kilt:light:014rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF:omFlomlwdWJsaWNLZXlYILu7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7ZHR5cGVmeDI1NTE5YXOCo2JpZGhzZXJ2aWNlMWR0eXBlaW1lc3NhZ2luZ29zZXJ2aWNlRW5kcG9pbnRrZXhhbXBsZS5jb22jYmlkaHNlcnZpY2UyZHR5cGVpdGVsZXBob25lb3NlcnZpY2VFbmRwb2ludGYxMjMzNDQ=#encryption', + controller: + 'did:kilt:light:014rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF:omFlomlwdWJsaWNLZXlYILu7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7ZHR5cGVmeDI1NTE5YXOCo2JpZGhzZXJ2aWNlMWR0eXBlaW1lc3NhZ2luZ29zZXJ2aWNlRW5kcG9pbnRrZXhhbXBsZS5jb22jYmlkaHNlcnZpY2UyZHR5cGVpdGVsZXBob25lb3NlcnZpY2VFbmRwb2ludGYxMjMzNDQ=', + type: 'X25519KeyAgreementKey2019', + publicKeyBase58: 'DdqGmK5uamYN5vmuZrzpQhKeehLdwtPLVJdhu5P2iJKC', + }, + ], + authentication: [ + 'did:kilt:light:014rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF:omFlomlwdWJsaWNLZXlYILu7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7ZHR5cGVmeDI1NTE5YXOCo2JpZGhzZXJ2aWNlMWR0eXBlaW1lc3NhZ2luZ29zZXJ2aWNlRW5kcG9pbnRrZXhhbXBsZS5jb22jYmlkaHNlcnZpY2UyZHR5cGVpdGVsZXBob25lb3NlcnZpY2VFbmRwb2ludGYxMjMzNDQ=#authentication', + ], + keyAgreement: [ + 'did:kilt:light:014rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF:omFlomlwdWJsaWNLZXlYILu7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7ZHR5cGVmeDI1NTE5YXOCo2JpZGhzZXJ2aWNlMWR0eXBlaW1lc3NhZ2luZ29zZXJ2aWNlRW5kcG9pbnRrZXhhbXBsZS5jb22jYmlkaHNlcnZpY2UyZHR5cGVpdGVsZXBob25lb3NlcnZpY2VFbmRwb2ludGYxMjMzNDQ=#encryption', + ], + service: [ + { + id: + 'did:kilt:light:014rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF:omFlomlwdWJsaWNLZXlYILu7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7ZHR5cGVmeDI1NTE5YXOCo2JpZGhzZXJ2aWNlMWR0eXBlaW1lc3NhZ2luZ29zZXJ2aWNlRW5kcG9pbnRrZXhhbXBsZS5jb22jYmlkaHNlcnZpY2UyZHR5cGVpdGVsZXBob25lb3NlcnZpY2VFbmRwb2ludGYxMjMzNDQ=#service1', + type: 'messaging', + serviceEndpoint: 'example.com', + }, + { + id: + 'did:kilt:light:014rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF:omFlomlwdWJsaWNLZXlYILu7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7ZHR5cGVmeDI1NTE5YXOCo2JpZGhzZXJ2aWNlMWR0eXBlaW1lc3NhZ2luZ29zZXJ2aWNlRW5kcG9pbnRrZXhhbXBsZS5jb22jYmlkaHNlcnZpY2UyZHR5cGVpdGVsZXBob25lb3NlcnZpY2VFbmRwb2ludGYxMjMzNDQ=#service2', + type: 'telephone', + serviceEndpoint: '123344', + }, + ], + }) + }) + + it('exports the expected application/json W3C DID Document with an Sr25519 authentication key', () => { + authenticationDidKeyDetails = { + publicKey: authPublicKey, + type: 'sr25519', + } + const didCreationDetails: LightDidDetailsCreationOpts = { + authenticationKey: authenticationDidKeyDetails, + } + const didDetails = new LightDidDetails(didCreationDetails) + const didDoc = exportToDidDocument(didDetails, 'application/json') + + expect(didDoc).toStrictEqual({ + id: 'did:kilt:light:004rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF', + verificationMethod: [ + { + id: + 'did:kilt:light:004rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF#authentication', + controller: + 'did:kilt:light:004rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF', + type: 'Sr25519VerificationKey2020', + publicKeyBase58: 'CVDFLCAjXhVWiPXH9nTCTpCgVzmDVoiPzNJYuccr1dqB', + }, + ], + authentication: [ + 'did:kilt:light:004rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF#authentication', + ], + }) + }) + + it('exports the expected application/json W3C DID Document with an Ecdsa authentication key', () => { + authenticationDidKeyDetails = { + publicKey: authPublicKey, + type: 'ecdsa', + } + const didCreationDetails: LightDidDetailsCreationOpts = { + authenticationKey: authenticationDidKeyDetails, + } + const didDetails = new LightDidDetails(didCreationDetails) + const didDoc = exportToDidDocument(didDetails, 'application/json') + + expect(didDoc).toStrictEqual({ + id: 'did:kilt:light:024rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF', + verificationMethod: [ + { + id: + 'did:kilt:light:024rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF#authentication', + controller: + 'did:kilt:light:024rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF', + type: 'EcdsaSecp256k1VerificationKey2019', + publicKeyBase58: 'CVDFLCAjXhVWiPXH9nTCTpCgVzmDVoiPzNJYuccr1dqB', + }, + ], + authentication: [ + 'did:kilt:light:024rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF#authentication', + ], + }) + }) + + it('exports the expected application/ld+json W3C DID Document with only an authentication key', () => { + authenticationDidKeyDetails = { + publicKey: authPublicKey, + type: 'sr25519', + } + const didCreationDetails: LightDidDetailsCreationOpts = { + authenticationKey: authenticationDidKeyDetails, + } + const didDetails = new LightDidDetails(didCreationDetails) + const didDoc = exportToDidDocument(didDetails, 'application/ld+json') + + expect(didDoc).toStrictEqual({ + '@context': ['https://www.w3.org/ns/did/v1'], + id: 'did:kilt:light:004rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF', + verificationMethod: [ + { + id: + 'did:kilt:light:004rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF#authentication', + controller: + 'did:kilt:light:004rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF', + type: 'Sr25519VerificationKey2020', + publicKeyBase58: 'CVDFLCAjXhVWiPXH9nTCTpCgVzmDVoiPzNJYuccr1dqB', + }, + ], + authentication: [ + 'did:kilt:light:004rmqfMwFrv9mhwJwMb1vGWcmKmCNTRM8J365TRsJuPzXDNGF#authentication', + ], + }) + }) + + it('does not export a DID Document with an unsupported format', () => { + const didCreationDetails: LightDidDetailsCreationOpts = { + authenticationKey: authenticationDidKeyDetails, + } + const didDetails = new LightDidDetails(didCreationDetails) + expect(() => exportToDidDocument(didDetails, 'text/html')).toThrow() + }) +}) diff --git a/packages/kilt-did/src/DidDocumentExporter/DidDocumentExporter.ts b/packages/kilt-did/src/DidDocumentExporter/DidDocumentExporter.ts new file mode 100644 index 000000000..a5f294df5 --- /dev/null +++ b/packages/kilt-did/src/DidDocumentExporter/DidDocumentExporter.ts @@ -0,0 +1,134 @@ +/** + * Copyright 2018-2021 BOTLabs GmbH. + * + * This source code is licensed under the BSD 4-Clause "Original" license + * found in the LICENSE file in the root directory of this source tree. + */ + +/* eslint-disable import/prefer-default-export */ + +/** + * @packageDocumentation + * @module DID + */ + +import { base58Encode } from '@polkadot/util-crypto' +import { hexToU8a } from '@polkadot/util' + +import type { + IDidDocument, + IJsonLDDidDocument, + IDidDetails, + IDidDocumentExporter, +} from '@kiltprotocol/types' +import { + KeyRelationship, + VerificationKeyTypesMap, + EncryptionKeyTypesMap, +} from '@kiltprotocol/types' + +function exportToJsonDidDocument(details: IDidDetails): IDidDocument { + const result: any = {} + + result.id = details.did + result.verificationMethod = new Array() + + // Populate the `verificationMethod` array and then sets the `authentication` array with the key IDs (or undefined if no auth key is present - which should never happen) + const authenticationKeysIds = details + .getKeys(KeyRelationship.authentication) + .map((authKey) => { + result.verificationMethod.push({ + id: authKey.id, + controller: details.did, + type: VerificationKeyTypesMap[authKey.type], + publicKeyBase58: base58Encode(hexToU8a(authKey.publicKeyHex)), + }) + // Parse only the key ID from the complete key URI + return authKey.id + }) + if (authenticationKeysIds.length) { + result.authentication = authenticationKeysIds + } + + const keyAgreementKeysIds = details + .getKeys(KeyRelationship.keyAgreement) + .map((keyAgrKey) => { + result.verificationMethod.push({ + id: keyAgrKey.id, + controller: details.did, + type: EncryptionKeyTypesMap[keyAgrKey.type], + publicKeyBase58: base58Encode(hexToU8a(keyAgrKey.publicKeyHex)), + }) + return keyAgrKey.id + }) + if (keyAgreementKeysIds.length) { + result.keyAgreement = keyAgreementKeysIds + } + + const assertionKeysIds = details + .getKeys(KeyRelationship.assertionMethod) + .map((assKey) => { + result.verificationMethod.push({ + id: assKey.id, + controller: details.did, + type: VerificationKeyTypesMap[assKey.type], + publicKeyBase58: base58Encode(hexToU8a(assKey.publicKeyHex)), + }) + return assKey.id + }) + if (assertionKeysIds.length) { + result.assertionMethod = assertionKeysIds + } + + const delegationKeyIds = details + .getKeys(KeyRelationship.capabilityDelegation) + .map((delKey) => { + result.verificationMethod.push({ + id: delKey.id, + controller: details.did, + type: VerificationKeyTypesMap[delKey.type], + publicKeyBase58: base58Encode(hexToU8a(delKey.publicKeyHex)), + }) + return delKey.id + }) + if (delegationKeyIds.length) { + result.capabilityDelegation = delegationKeyIds + } + + if (details.getServices().length) { + result.service = details.getServices() + } + + return result as IDidDocument +} + +function exportToJsonLdDidDocument(details: IDidDetails): IJsonLDDidDocument { + const document = exportToJsonDidDocument(details) + document['@context'] = ['https://www.w3.org/ns/did/v1'] + return document as IJsonLDDidDocument +} + +/** + * Export an instance of [[IDidDetails]] to a W3c-compliant DID Document in the format provided. + * + * @param details The [[IDidDetails]] instance. + * @param mimeType The format for the output DID Document. Accepted values are `application/json` and `application/ld+json`. + * @returns The DID Document formatted according to the mime type provided, or an error if the format specified is not supported. + */ +export function exportToDidDocument( + details: IDidDetails, + mimeType: string +): IDidDocument { + switch (mimeType) { + case 'application/json': + return exportToJsonDidDocument(details) + case 'application/ld+json': + return exportToJsonLdDidDocument(details) + default: + throw new Error( + `${mimeType} not supported by any of the available exporters.` + ) + } +} + +export const DidDocumentExporter: IDidDocumentExporter = { exportToDidDocument } diff --git a/packages/kilt-did/src/DidDocumentExporter/README.md b/packages/kilt-did/src/DidDocumentExporter/README.md new file mode 100644 index 000000000..7f31120cf --- /dev/null +++ b/packages/kilt-did/src/DidDocumentExporter/README.md @@ -0,0 +1,52 @@ +# DID Document exporter + +The DID Document exporter provides the functionality needed to convert an instance of a generic `IDidDetails` into a document that is compliant with the [W3C specification](https://www.w3.org/TR/did-core/). This component is required for the KILT plugin for the [DIF Universal Resolver](https://dev.uniresolver.io/). + +## How to use the exporter + +The exporter interface and used types are part of the `@kiltprotocol/types` package, while the actual `DidDocumentExporter` is part of this module. The following shows how to use the exporter to generate a DID Document for both a light and a full DID. + +Currently, the exporter supports DID Documents in `application/json` and `application/ld+json` format. + +```typescript +import { + exportToDidDocument, + FullDidDetails, + LightDidDetails +} from '@kiltprotocol/did' + +import type { IDidDocument, IJsonLDDidDocument } from '@kiltprotocol/types' + +// Create an instance of `LightDidDetails` with the required information +const lightDidDetails = new LightDidDetails({...}) + +const lightDidDocument: IDidDocument = exportToDidDocument(lightDidDetails, 'application/json') + +// Will print the light DID. +console.log(lightDidDocument.id) + +// Will print all the public keys associated with the light DID. +console.log(lightDidDocument.verificationMethod) + +// Will print all the assertion keys. +console.log(lightDidDocument.assertionMethod) + +// Will print all the encryption keys. +console.log(lightDidDocument.keyAgreement) + +// Will print all the delegation keys. +console.log(lightDidDocument.capabilityDelegation) + +// Will print all the external services referenced inside the `IDidDetails` instance. +console.log(lightDidDocument.service) + +// Let's export an instance of `FullDidDetails` using the `application/ld+json` format. + +const fullDidDetails = new FullDidDetails({...}) + +// The document type will be a `IJsonLDDidDocument`, which extends the simpler `IDidDocument`. +const fullDidDocument: IJsonLDDidDocument = exportToDidDocument(fullDidDetails, 'application/ld+json') + +// The same properties of `IDidDocument` can be accessed, plus a `@context` property required by the JSON-LD specification. +console.log(fullDidDocument['@context']) +``` diff --git a/packages/kilt-did/src/DidDocumentExporter/index.ts b/packages/kilt-did/src/DidDocumentExporter/index.ts new file mode 100644 index 000000000..c64263343 --- /dev/null +++ b/packages/kilt-did/src/DidDocumentExporter/index.ts @@ -0,0 +1,17 @@ +/** + * Copyright 2018-2021 BOTLabs GmbH. + * + * This source code is licensed under the BSD 4-Clause "Original" license + * found in the LICENSE file in the root directory of this source tree. + */ + +/* eslint-disable import/prefer-default-export */ + +/** + * @packageDocumentation + * @module DID + */ + +import { DidDocumentExporter, exportToDidDocument } from './DidDocumentExporter' + +export { DidDocumentExporter, exportToDidDocument } diff --git a/packages/kilt-did/src/index.ts b/packages/kilt-did/src/index.ts index d66bfbfe2..19f9856b3 100644 --- a/packages/kilt-did/src/index.ts +++ b/packages/kilt-did/src/index.ts @@ -13,3 +13,4 @@ export * as DidUtils from './Did.utils' export * from './DemoKeystore/DemoKeystore' export * from './DidDetails' export * from './DidResolver/DefaultResolver' +export * from './DidDocumentExporter' diff --git a/packages/kilt-did/src/types.ts b/packages/kilt-did/src/types.ts index cb48669ba..06e02c8bf 100644 --- a/packages/kilt-did/src/types.ts +++ b/packages/kilt-did/src/types.ts @@ -9,6 +9,7 @@ import type { IIdentity, IDidKeyDetails, IDidDetails, + IServiceDetails, KeyRelationship, } from '@kiltprotocol/types' import type { AnyNumber } from '@polkadot/types/types' @@ -201,3 +202,17 @@ export interface DidAuthorizedCallOperation extends Struct { txCounter: u64 call: Call } + +export type JsonDidDocument = { + id: IDidDetails['did'] + verificationMethod: Pick & { + publicKeyBase58: string + } + authentication: string[] + assertionMethod?: string[] + keyAgreement?: string[] + capabilityDelegation?: string[] + service?: IServiceDetails[] +} + +export type JsonLDDidDocument = JsonDidDocument & { '@context': string[] } diff --git a/packages/sdk-js/package.json b/packages/sdk-js/package.json index 0de90681a..bf35c7ac2 100644 --- a/packages/sdk-js/package.json +++ b/packages/sdk-js/package.json @@ -38,6 +38,7 @@ "dependencies": { "@kiltprotocol/chain-helpers": "workspace:*", "@kiltprotocol/core": "workspace:*", + "@kiltprotocol/did": "workspace:*", "@kiltprotocol/messaging": "workspace:*", "@kiltprotocol/types": "workspace:*", "@kiltprotocol/utils": "workspace:*" diff --git a/packages/sdk-js/src/index.ts b/packages/sdk-js/src/index.ts index 46208f83e..c196ec968 100644 --- a/packages/sdk-js/src/index.ts +++ b/packages/sdk-js/src/index.ts @@ -9,10 +9,12 @@ import * as core from '@kiltprotocol/core' import Message, * as Messaging from '@kiltprotocol/messaging' import { BlockchainUtils } from '@kiltprotocol/chain-helpers' import * as ChainHelpers from '@kiltprotocol/chain-helpers' +import * as Did from '@kiltprotocol/did' import * as Utils from '@kiltprotocol/utils' -export * from '@kiltprotocol/types' export * from '@kiltprotocol/core' +export * from '@kiltprotocol/did' +export * from '@kiltprotocol/types' export { Message, Messaging, BlockchainUtils, ChainHelpers, Utils } export default { @@ -21,5 +23,6 @@ export default { Messaging, BlockchainUtils, ChainHelpers, + Did, Utils, } diff --git a/packages/types/src/DidDocumentExporter.ts b/packages/types/src/DidDocumentExporter.ts new file mode 100644 index 000000000..cdf78688d --- /dev/null +++ b/packages/types/src/DidDocumentExporter.ts @@ -0,0 +1,55 @@ +/** + * Copyright 2018-2021 BOTLabs GmbH. + * + * This source code is licensed under the BSD 4-Clause "Original" license + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * @packageDocumentation + * @module IDidDocumentExporter + */ + +import type { IDidDetails, IDidKeyDetails, IServiceDetails } from '.' + +export enum DidDocumentPublicKeyType { + Ed25519VerificationKey = 'Ed25519VerificationKey2018', + Sr25519VerificationKey = 'Sr25519VerificationKey2020', + EcdsaVerificationKey = 'EcdsaSecp256k1VerificationKey2019', + X25519EncryptionKey = 'X25519KeyAgreementKey2019', +} + +export const VerificationKeyTypesMap = { + // proposed and used by dock.io, e.g. https://github.com/w3c-ccg/security-vocab/issues/32, https://github.com/docknetwork/sdk/blob/9c818b03bfb4fdf144c20678169c7aad3935ad96/src/utils/vc/contexts/security_context.js + sr25519: DidDocumentPublicKeyType.Sr25519VerificationKey, + // these are part of current w3 security vocab, see e.g. https://www.w3.org/ns/did/v1 + ed25519: DidDocumentPublicKeyType.Ed25519VerificationKey, + ecdsa: DidDocumentPublicKeyType.EcdsaVerificationKey, +} + +export const EncryptionKeyTypesMap = { + x25519: DidDocumentPublicKeyType.X25519EncryptionKey, +} + +export type IDidPublicKeyDetails = Pick & { + publicKeyBase58: string + type: DidDocumentPublicKeyType +} + +export type IDidPublicKeyId = Pick + +export type IDidDocument = { + id: IDidDetails['did'] + verificationMethod: IDidPublicKeyDetails[] + authentication: IDidPublicKeyId[] + assertionMethod?: IDidPublicKeyId[] + keyAgreement?: IDidPublicKeyId[] + capabilityDelegation?: IDidPublicKeyId[] + service?: IServiceDetails[] +} + +export type IJsonLDDidDocument = IDidDocument & { '@context': string[] } + +export interface IDidDocumentExporter { + exportToDidDocument: (details: IDidDetails, mimeType: string) => IDidDocument +} diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 22a80b34e..5f9869700 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -26,3 +26,4 @@ export * from './Blockchain' export * from './DidDetails' export * from './Keystore' export * from './DidResolver' +export * from './DidDocumentExporter' diff --git a/packages/vc-export/src/constants.ts b/packages/vc-export/src/constants.ts index deff5bce4..8c562e96a 100644 --- a/packages/vc-export/src/constants.ts +++ b/packages/vc-export/src/constants.ts @@ -31,11 +31,3 @@ export const KILT_CREDENTIAL_DIGEST_PROOF_TYPE = 'KILTCredentialDigest2020' export const JSON_SCHEMA_TYPE = 'JsonSchemaValidator2018' export const KILT_CREDENTIAL_IRI_PREFIX = 'kilt:cred:' - -export const KeyTypesMap = { - // proposed and used by dock.io, e.g. https://github.com/w3c-ccg/security-vocab/issues/32, https://github.com/docknetwork/sdk/blob/9c818b03bfb4fdf144c20678169c7aad3935ad96/src/utils/vc/contexts/security_context.js - sr25519: 'Sr25519VerificationKey2020', - // these are part of current w3 security vocab, see e.g. https://www.w3.org/ns/did/v1 - ed25519: 'Ed25519VerificationKey2018', - ecdsa: 'EcdsaSecp256k1VerificationKey2019', -} diff --git a/packages/vc-export/src/verificationUtils.ts b/packages/vc-export/src/verificationUtils.ts index ffc60b6c4..1cdfe80c7 100644 --- a/packages/vc-export/src/verificationUtils.ts +++ b/packages/vc-export/src/verificationUtils.ts @@ -17,11 +17,11 @@ import Ajv from 'ajv' import { Attestation, CTypeSchema } from '@kiltprotocol/core' import { Crypto } from '@kiltprotocol/utils' import { DocumentLoader } from 'jsonld-signatures' +import { VerificationKeyTypesMap } from '@kiltprotocol/types' import { KILT_SELF_SIGNED_PROOF_TYPE, KILT_ATTESTED_PROOF_TYPE, KILT_CREDENTIAL_DIGEST_PROOF_TYPE, - KeyTypesMap, } from './constants' import type { VerifiableCredential, @@ -100,10 +100,10 @@ export async function verifySelfSignedProof( if (!verificationMethod.controller === credentialOwner) throw new Error('credential subject is not owner of signing key') const keyType = verificationMethod.type || verificationMethod['@type'] - if (!Object.values(KeyTypesMap).includes(keyType)) + if (!Object.values(VerificationKeyTypesMap).includes(keyType)) throw PROOF_MALFORMED_ERROR( `signature type unknown; expected one of ${JSON.stringify( - Object.values(KeyTypesMap) + Object.values(VerificationKeyTypesMap) )}, got "${verificationMethod.type}"` ) const signerPubKey = verificationMethod.publicKeyHex @@ -119,7 +119,10 @@ export async function verifySelfSignedProof( signerPubKey ) if ( - !(verification.isValid && KeyTypesMap[verification.crypto] === keyType) + !( + verification.isValid && + VerificationKeyTypesMap[verification.crypto] === keyType + ) ) { throw new Error('signature could not be verified') } diff --git a/yarn.lock b/yarn.lock index 1edf99df4..893130103 100644 --- a/yarn.lock +++ b/yarn.lock @@ -896,6 +896,7 @@ __metadata: dependencies: "@kiltprotocol/chain-helpers": "workspace:*" "@kiltprotocol/core": "workspace:*" + "@kiltprotocol/did": "workspace:*" "@kiltprotocol/messaging": "workspace:*" "@kiltprotocol/types": "workspace:*" "@kiltprotocol/utils": "workspace:*"