Skip to content

Commit

Permalink
feat(core-types): export a basic mapping between key types and algori…
Browse files Browse the repository at this point in the history
…thms
  • Loading branch information
mirceanis committed Aug 15, 2023
1 parent 3406a04 commit 57b6c58
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 28 deletions.
24 changes: 18 additions & 6 deletions packages/core-types/src/plugin.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -549,12 +549,16 @@
"algorithms": {
"type": "array",
"items": {
"type": "string"
"$ref": "#/components/schemas/TAlg"
}
}
},
"description": "This encapsulates data about a key.\n\nImplementations of {@link @veramo/key-manager#AbstractKeyManagementSystem | AbstractKeyManagementSystem } should populate this object, for each key, with the algorithms that can be performed using it.\n\nThis can also be used to add various tags to the keys under management."
},
"TAlg": {
"type": "string",
"description": "Known algorithms supported by some of the above key types defined by {@link TKeyType } .\n\nActual implementations of {@link @veramo/key-manager#AbstractKeyManagementSystem | Key Management Systems } can support more. One should check the {@link IKey.meta.algorithms } property to see what is possible for a particular managed key."
},
"ManagedKeyInfo": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -736,7 +740,7 @@
"type",
"publicKeyHex"
],
"description": "Cryptographic key"
"description": "Cryptographic key, usually managed by the current Veramo instance."
},
"MinimalImportableKey": {
"$ref": "#/components/schemas/RequireOnly<IKey,(\"privateKeyHex\"|\"type\"|\"kms\")>",
Expand Down Expand Up @@ -1099,7 +1103,7 @@
"type",
"publicKeyHex"
],
"description": "Cryptographic key"
"description": "Cryptographic key, usually managed by the current Veramo instance."
},
"TKeyType": {
"type": "string",
Expand All @@ -1119,12 +1123,16 @@
"algorithms": {
"type": "array",
"items": {
"type": "string"
"$ref": "#/components/schemas/TAlg"
}
}
},
"description": "This encapsulates data about a key.\n\nImplementations of {@link @veramo/key-manager#AbstractKeyManagementSystem | AbstractKeyManagementSystem } should populate this object, for each key, with the algorithms that can be performed using it.\n\nThis can also be used to add various tags to the keys under management."
},
"TAlg": {
"type": "string",
"description": "Known algorithms supported by some of the above key types defined by {@link TKeyType } .\n\nActual implementations of {@link @veramo/key-manager#AbstractKeyManagementSystem | Key Management Systems } can support more. One should check the {@link IKey.meta.algorithms } property to see what is possible for a particular managed key."
},
"IDIDManagerAddServiceArgs": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -2776,7 +2784,7 @@
"type",
"publicKeyHex"
],
"description": "Cryptographic key"
"description": "Cryptographic key, usually managed by the current Veramo instance."
},
"TKeyType": {
"type": "string",
Expand All @@ -2796,12 +2804,16 @@
"algorithms": {
"type": "array",
"items": {
"type": "string"
"$ref": "#/components/schemas/TAlg"
}
}
},
"description": "This encapsulates data about a key.\n\nImplementations of {@link @veramo/key-manager#AbstractKeyManagementSystem | AbstractKeyManagementSystem } should populate this object, for each key, with the algorithms that can be performed using it.\n\nThis can also be used to add various tags to the keys under management."
},
"TAlg": {
"type": "string",
"description": "Known algorithms supported by some of the above key types defined by {@link TKeyType } .\n\nActual implementations of {@link @veramo/key-manager#AbstractKeyManagementSystem | Key Management Systems } can support more. One should check the {@link IKey.meta.algorithms } property to see what is possible for a particular managed key."
},
"IService": {
"type": "object",
"properties": {
Expand Down
30 changes: 28 additions & 2 deletions packages/core-types/src/types/IIdentifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,33 @@ export type MinimalImportableIdentifier = {
export type TKeyType = 'Ed25519' | 'Secp256k1' | 'Secp256r1' | 'X25519' | 'Bls12381G1' | 'Bls12381G2'

/**
* Cryptographic key
* Known algorithms supported by some of the above key types defined by {@link TKeyType}.
*
* Actual implementations of {@link @veramo/key-manager#AbstractKeyManagementSystem | Key Management Systems} can
* support more. One should check the {@link IKey.meta.algorithms} property to see what is possible
* for a particular managed key.
*
* @public
*/
export type TAlg = 'ES256K' | 'ES256K-R' | 'ES256' | 'EdDSA' | 'ECDH' | 'ECDH-ES' | 'ECDH-1PU' | string

/**
* Mapping of known key types({@link TKeyType}) to the known algorithms({@link TAlg}) they should support.
*
* @public
*/
export const KEY_ALG_MAPPING: Record<TKeyType, ReadonlyArray<TAlg>> = {
Secp256k1: ['ES256K', 'ES256K-R'],
Secp256r1: ['ES256', 'ECDH', 'ECDH-ES', 'ECDH-1PU'],
Ed25519: ['EdDSA'],
X25519: ['ECDH', 'ECDH-ES', 'ECDH-1PU'],
Bls12381G1: [],
Bls12381G2: [],
} as const

/**
* Cryptographic key, usually managed by the current Veramo instance.
*
* @public
*/
export interface IKey {
Expand Down Expand Up @@ -100,7 +126,7 @@ export interface IKey {
* @public
*/
export interface KeyMetadata {
algorithms?: string[]
algorithms?: TAlg[]

[x: string]: any
}
Expand Down
20 changes: 13 additions & 7 deletions packages/kms-local/src/key-management-system.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { IKey, ManagedKeyInfo, MinimalImportableKey, RequireOnly, TKeyType } from '@veramo/core-types'
import {
IKey,
KEY_ALG_MAPPING,
ManagedKeyInfo,
MinimalImportableKey,
RequireOnly,
TKeyType,
} from '@veramo/core-types'
import {
AbstractKeyManagementSystem,
AbstractPrivateKeyStore,
Expand All @@ -8,6 +15,7 @@ import {

import { EdDSASigner, ES256KSigner, ES256Signer } from 'did-jwt'
import { ed25519, x25519 } from '@noble/curves/ed25519'
import { p256 } from '@noble/curves/p256'
import { TransactionRequest } from '@ethersproject/abstract-provider'
import { toUtf8String } from '@ethersproject/strings'
import { parse } from '@ethersproject/transactions'
Expand All @@ -16,7 +24,6 @@ import { SigningKey } from '@ethersproject/signing-key'
import { randomBytes } from '@ethersproject/random'
import { arrayify, hexlify } from '@ethersproject/bytes'
import Debug from 'debug'
import { p256 } from '@noble/curves/p256'
import {
bytesToHex,
concat,
Expand Down Expand Up @@ -302,7 +309,7 @@ export class KeyManagementSystem extends AbstractKeyManagementSystem {
kid: args.alias || publicKeyHex,
publicKeyHex,
meta: {
algorithms: ['Ed25519', 'EdDSA'],
algorithms: [...KEY_ALG_MAPPING[args.type], 'Ed25519'],
},
}
break
Expand All @@ -317,8 +324,7 @@ export class KeyManagementSystem extends AbstractKeyManagementSystem {
publicKeyHex,
meta: {
algorithms: [
'ES256K',
'ES256K-R',
...KEY_ALG_MAPPING[args.type],
'eth_signTransaction',
'eth_signTypedData',
'eth_signMessage',
Expand All @@ -336,7 +342,7 @@ export class KeyManagementSystem extends AbstractKeyManagementSystem {
kid: args.alias || publicKeyHex,
publicKeyHex,
meta: {
algorithms: ['ES256'],
algorithms: ['ES256'], // ECDH not supported yet by this KMS
},
}
break
Expand All @@ -349,7 +355,7 @@ export class KeyManagementSystem extends AbstractKeyManagementSystem {
kid: args.alias || publicKeyHex,
publicKeyHex: publicKeyHex,
meta: {
algorithms: ['ECDH', 'ECDH-ES', 'ECDH-1PU'],
algorithms: [...KEY_ALG_MAPPING[args.type]],
},
}
break
Expand Down
20 changes: 8 additions & 12 deletions packages/selective-disclosure/src/action-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import {
IDIDManager,
IKey,
IKeyManager,
KEY_ALG_MAPPING,
TAlg,
TClaimsColumns,
TKeyType,
VerifiableCredential,
VerifiablePresentation,
} from '@veramo/core-types'
Expand All @@ -32,17 +33,9 @@ import {
computeEntryHash,
decodeCredentialToObject,
extractIssuer,
intersect,
} from '@veramo/utils'

const KEY_ALG_MAPPING: Record<TKeyType, string | null> = {
Secp256k1: 'ES256K',
Secp256r1: 'ES256',
Ed25519: 'EdDSA',
X25519: null,
Bls12381G1: null,
Bls12381G2: null,
} as const

/**
* This class adds support for creating
* {@link https://github.com/uport-project/specs/blob/develop/flows/selectivedisclosure.md | Selective Disclosure}
Expand Down Expand Up @@ -89,17 +82,20 @@ export class SelectiveDisclosure implements IAgentPlugin {
delete data.issuer
Debug('veramo:selective-disclosure:create-sdr')('Signing SDR with', identifier.did)

// only these signature algorithms are supported
const algs: TAlg[] = ['ES256K', 'ES256K-R', 'EdDSA', 'ES256']

const key = identifier.keys.find((k: IKey) => {
return (
Object.keys(KEY_ALG_MAPPING).includes(k.type) &&
KEY_ALG_MAPPING[k.type] &&
k.meta?.algorithms?.includes(KEY_ALG_MAPPING[k.type] ?? 'unsupported')
intersect(intersect(k.meta?.algorithms, KEY_ALG_MAPPING[k.type]), algs).length > 0
)
})

if (!key) throw Error('Signing key not found')

const algorithm = KEY_ALG_MAPPING[key?.type ?? '']
const algorithm = KEY_ALG_MAPPING[key.type]?.[0]

if (!algorithm) throw Error('Unsupported key type')

Expand Down
21 changes: 20 additions & 1 deletion packages/utils/src/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { asArray, isDefined } from '../type-utils.js'
import { asArray, intersect, isDefined } from '../type-utils.js'

describe('@veramo/utils type utils', () => {
it('isDefined should return correct results', () => {
Expand All @@ -20,4 +20,23 @@ describe('@veramo/utils type utils', () => {
expect(asArray(undefined)).toEqual([])
expect(asArray(null)).toEqual([])
})

describe('intersect', () => {
it('should work with primitive types', () => {
expect(intersect(['a'], ['b'])).toStrictEqual([])
expect(intersect(['a', 'a'], ['b'])).toStrictEqual([])
expect(intersect(['a', 'a', 'b'], ['b'])).toStrictEqual(['b'])
expect(intersect(['a', 'a', 'b'], ['b', 'a'])).toStrictEqual(['a', 'b'])
expect(intersect(['a', 'a', 'b', 1], ['b', 'a', 2])).toStrictEqual(['a', 'b'])
expect(intersect(['a', 'a', 'b', 1], ['b', 1, 2])).toStrictEqual(['b', 1])
expect(intersect([1, false], [true])).toStrictEqual([])
expect(intersect([1, false, null], [true, null])).toStrictEqual([null])
expect(intersect([1, false, undefined], [true, undefined])).toStrictEqual([undefined])
expect(intersect([1], [true])).toStrictEqual([])
})

it('does not work with objects since references are different', () => {
expect(intersect([{}], [{}])).toStrictEqual([])
})
})
})
14 changes: 14 additions & 0 deletions packages/utils/src/type-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,17 @@ export function asArray<T>(arg?: T | T[] | any): (T | any)[] {
export function isIterable<T>(obj: any): obj is Iterable<T> {
return obj != null && typeof obj[Symbol.iterator] === 'function'
}

/**
* Compute the intersection of two arrays
* Elements are compared by reference so object types will appear as unique even if they contain the same data.
*
* @param a - first array
* @param b - second array
* @returns The intersection of the two arrays.
*
*/
export function intersect<T>(a: T[] | any, b: any[] | any): T[] {
const setB = new Set<T>(asArray(b));
return [...new Set(asArray(a))].filter(x => setB.has(x));
}

0 comments on commit 57b6c58

Please sign in to comment.