Skip to content

Commit

Permalink
fix: Multiple DID EBSI fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
nklomp committed Jun 19, 2024
1 parent e305573 commit 131faa0
Show file tree
Hide file tree
Showing 26 changed files with 4,258 additions and 3,978 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@
"@veramo/remote-server": "4.2.0",
"@veramo/selective-disclosure": "4.2.0",
"@veramo/url-handler": "4.2.0",
"@sphereon/ssi-sdk.core": "0.23.0",
"@sphereon/ssi-types": "0.23.0",
"@sphereon/ssi-sdk.core": "0.25.0",
"@sphereon/ssi-types": "0.25.0",
"@digitalcredentials/ed25519-verification-key-2020": "3.2.2",
"did-jwt": "6.11.6",
"did-jwt-vc": "3.1.3",
Expand Down
9 changes: 6 additions & 3 deletions packages/did-provider-ebsi/__tests__/EbsiDidProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,33 +44,36 @@ describe('@sphereon/did-provider-ebsi', () => {
expect(identifier).toBeDefined()
expect(identifier.keys.length).toBe(2)
const secp256k1 = identifier.keys.find((key) => key.type === 'Secp256k1')
const secp256r1 = identifier.keys.find((key) => key.type === 'Secp256r1')
expect(secp256k1).toBeDefined()
expect(secp256k1).toEqual(
expect.objectContaining({
kid: expect.any(String),
kms: 'mem',
type: 'Secp256k1',
publicKeyHex: expect.any(String),
meta: {
jwkThumbprint: expect.any(String),
algorithms: ['ES256'],
purposes: [EbsiPublicKeyPurpose.CapabilityInvocation],
},
})
)
expect(secp256k1).toBeDefined()
expect(secp256k1?.publicKeyHex?.length).toEqual(66)

const secp256r1 = identifier.keys.find((key) => key.type === 'Secp256r1')
expect(secp256r1).toEqual(
expect.objectContaining({
kid: expect.any(String),
kms: 'mem',
type: 'Secp256r1',
publicKeyHex: expect.any(String),
meta: {
jwkThumbprint: expect.any(String),
algorithms: ['ES256K', 'ES256K-R', 'eth_signTransaction', 'eth_signTypedData', 'eth_signMessage', 'eth_rawSign'],
purposes: [EbsiPublicKeyPurpose.AssertionMethod, EbsiPublicKeyPurpose.Authentication],
},
})
)
expect(secp256r1?.publicKeyHex?.length).toEqual(66)
})

it('should create consistent identifier with provided key', async () => {
Expand Down
10 changes: 5 additions & 5 deletions packages/did-provider-ebsi/__tests__/functions.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { generateEbsiPrivateKeyHex } from '../src/functions'
import { generateOrUseProvidedEbsiPrivateKeyHex } from '../src/functions'

describe('functions: key generator', () => {
it('Secp256k1 should generate random keys', () => {
const key1 = generateEbsiPrivateKeyHex()
const key2 = generateEbsiPrivateKeyHex()
const key3 = generateEbsiPrivateKeyHex()
const key1 = generateOrUseProvidedEbsiPrivateKeyHex()
const key2 = generateOrUseProvidedEbsiPrivateKeyHex()
const key3 = generateOrUseProvidedEbsiPrivateKeyHex()
expect(key1).toBeDefined()
expect(key2).toBeDefined()
expect(key3).toBeDefined()
expect(key1).not.toBe(key2)
expect(key2).not.toBe(key3)
})
it('Secp256k1 should result in hex length 64', () => {
expect(generateEbsiPrivateKeyHex().length).toBe(64)
expect(generateOrUseProvidedEbsiPrivateKeyHex().length).toBe(64)
})
})
4 changes: 2 additions & 2 deletions packages/did-provider-ebsi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@veramo/core": "4.2.0",
"@veramo/did-manager": "4.2.0",
"@veramo/did-provider-key": "4.2.0",
"cross-fetch": "^4.0.0",
"cross-fetch": "^3.1.8",
"debug": "^4.3.4",
"did-resolver": "^4.1.0",
"ethers": "^6.11.1",
Expand All @@ -26,7 +26,7 @@
"devDependencies": {
"@sphereon/ssi-sdk-ext.key-manager": "workspace:*",
"@sphereon/ssi-sdk-ext.kms-local": "workspace:*",
"@sphereon/ssi-sdk.dev": "^0.23.0",
"@sphereon/ssi-sdk.dev": "0.25.0",
"@veramo/cli": "4.2.0",
"@veramo/key-manager": "4.2.0"
},
Expand Down
92 changes: 49 additions & 43 deletions packages/did-provider-ebsi/src/EbsiDidProvider.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { IAgentContext, IDIDManager, IIdentifier, IKeyManager } from '@veramo/core'
import Debug from 'debug'
import { AbstractIdentifierProvider } from '@veramo/did-manager/build/abstract-identifier-provider'
import { IKey, IService } from '@veramo/core/build/types/IIdentifier'
import { AbstractIdentifierProvider } from '@veramo/did-manager/build/abstract-identifier-provider'
import Debug from 'debug'
import { createEbsiDidOnLedger, generateEbsiMethodSpecificId, generateOrUseEbsiKeyPair, randomRpcId } from './functions'
import { ApiOpts, EBSI_DID_SPEC_INFOS, IContext, ICreateIdentifierArgs, UpdateIdentifierParams } from './types'
import { createEbsiDidOnLedger, generateEbsiKeyPair, generateEbsiMethodSpecificId, randomRpcId } from './functions'

const debug = Debug('sphereon:did-provider-ebsi')

Expand All @@ -19,64 +19,70 @@ export class EbsiDidProvider extends AbstractIdentifierProvider {

async createIdentifier(args: ICreateIdentifierArgs, context: IContext): Promise<Omit<IIdentifier, 'provider'>> {
const { type, options, kms, alias } = args
const { notBefore, notAfter, secp256k1Key, secp256r1Key, bearerToken, from } = { ...options }
const rpcId = options?.rpcId ?? randomRpcId()
const { notBefore, notAfter, secp256k1Key, secp256r1Key, bearerToken, from, executeLedgerOperation = false } = { ...options }

if (!type || type === EBSI_DID_SPEC_INFOS.V1) {
const secp256k1GeneratedKey = await generateEbsiKeyPair(
{
keyOpts: secp256k1Key,
keyType: 'Secp256k1',
kms: kms ?? this.defaultKms,
},
context
)
if (executeLedgerOperation && !bearerToken) {
throw new Error('Bearer token must be provided to execute ledger operation')
}
const rpcId = options?.rpcId ?? randomRpcId()

const secp256k1ManagedKeyInfo = await context.agent.keyManagerImport(secp256k1GeneratedKey)
const secp256r1GeneratedKey = await generateEbsiKeyPair(
{
keyOpts: secp256r1Key,
keyType: 'Secp256r1',
kms: kms ?? this.defaultKms,
},
context
)
if (type === EBSI_DID_SPEC_INFOS.KEY) {
throw new Error(`Type ${type} not supported. Please use @sphereon/ssi-sdk-ext.did-provider-key for Natural Person EBSI DIDs`)
}

const secp256r1ManagedKeyInfo = await context.agent.keyManagerImport(secp256r1GeneratedKey)
const methodSpecificId = generateEbsiMethodSpecificId(EBSI_DID_SPEC_INFOS.V1)
const identifier: Omit<IIdentifier, 'provider'> = {
did: `${EBSI_DID_SPEC_INFOS.V1.method}${methodSpecificId}`,
controllerKeyId: secp256k1ManagedKeyInfo.kid,
keys: [secp256k1ManagedKeyInfo, secp256r1ManagedKeyInfo],
alias,
services: [],
}
const secp256k1ImportKey = await generateOrUseEbsiKeyPair(
{
keyOpts: secp256k1Key,
keyType: 'Secp256k1',
kms: kms ?? this.defaultKms,
},
context
)
const secp256k1ManagedKeyInfo = await context.agent.keyManagerImport(secp256k1ImportKey)

const secp256r1ImportKey = await generateOrUseEbsiKeyPair(
{
keyOpts: secp256r1Key,
keyType: 'Secp256r1',
kms: kms ?? this.defaultKms,
},
context
)

const secp256r1ManagedKeyInfo = await context.agent.keyManagerImport(secp256r1ImportKey)

const methodSpecificId = generateEbsiMethodSpecificId(EBSI_DID_SPEC_INFOS.V1)
const identifier: Omit<IIdentifier, 'provider'> = {
did: `${EBSI_DID_SPEC_INFOS.V1.method}${methodSpecificId}`,
controllerKeyId: secp256k1ManagedKeyInfo.kid,
keys: [secp256k1ManagedKeyInfo, secp256r1ManagedKeyInfo],
alias,
services: [],
}

if (options === undefined) {
throw new Error(`Options must be provided ${JSON.stringify(options)}`)
if (executeLedgerOperation) {
if (!from) {
// TODO: The agent should be able to devise the from, as we have access to the keys etc.
throw Error(`No from provided, whilst we are performing a ledger operation!`)
}

await createEbsiDidOnLedger(
{
identifier,
secp256k1ManagedKeyInfo,
secp256r1ManagedKeyInfo,
bearerToken,
bearerToken: bearerToken!,
rpcId,
from,
notBefore: notBefore ?? Date.now() / 1000,
notAfter: notAfter ?? Number.MAX_SAFE_INTEGER,
apiOpts: { ...this.apiOpts, ...options.apiOpts },
apiOpts: { ...this.apiOpts, ...options?.apiOpts },
},
context
)

debug('Created', identifier.did)
return identifier
} else if (type === EBSI_DID_SPEC_INFOS.KEY) {
throw new Error(`Type ${type} not supported. Please use @sphereon/ssi-sdk-ext.did-provider-key for Natural Person EBSI DIDs`)
}
throw new Error(`Type ${type} not supported`)

debug('Created', identifier.did)
return identifier
}

addKey(
Expand Down
Loading

0 comments on commit 131faa0

Please sign in to comment.