Skip to content

Commit

Permalink
feat(credential-ld): add Ed25519Signature2020 & `JsonWebSignature20…
Browse files Browse the repository at this point in the history
…20` experimental support (#1030)

fixes #1003
  • Loading branch information
Eengineer1 authored Nov 18, 2022
1 parent 33c7cee commit fbf7d48
Show file tree
Hide file tree
Showing 18 changed files with 680 additions and 39 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@
]
},
"resolutions": {
"@types/react": "^18.0.12",
"@types/eslint": "^8.4.3"
"@types/react": "^18.0.21",
"@types/eslint": "^8.4.6"
},
"engines": {
"node": ">= 14.0.0"
Expand Down
5 changes: 5 additions & 0 deletions packages/credential-ld/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,16 @@
}
},
"dependencies": {
"@digitalcredentials/ed25519-signature-2020": "3.0.2",
"@digitalcredentials/jsonld": "^5.2.1",
"@digitalcredentials/jsonld-signatures": "^9.3.1",
"@digitalcredentials/vc": "^4.0.0",
"@transmute/credentials-context": "^0.7.0-unstable.60",
"@transmute/ed25519-signature-2018": "^0.7.0-unstable.60",
"@digitalcredentials/vc": "^5.0.0",
"@transmute/credentials-context": "^0.7.0-unstable.67",
"@transmute/ed25519-signature-2018": "^0.7.0-unstable.67",
"@transmute/json-web-signature": "^0.7.0-unstable.67",
"@veramo-community/lds-ecdsa-secp256k1-recovery2020": "uport-project/EcdsaSecp256k1RecoverySignature2020",
"@veramo/core": "^4.1.1",
"@veramo/did-resolver": "^4.1.1",
Expand Down
6 changes: 6 additions & 0 deletions packages/credential-ld/src/contexts/did_v0.11.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
"EcdsaSecp256k1VerificationKey2019": "sec:EcdsaSecp256k1VerificationKey2019",
"Ed25519Signature2018": "sec:Ed25519Signature2018",
"Ed25519VerificationKey2018": "sec:Ed25519VerificationKey2018",
"Ed25519Signature2020": "sec:Ed25519Signature2020",
"Ed25519VerificationKey2020": "sec:Ed25519VerificationKey2020",
"JsonWebSignature2020": "sec:JsonWebSignature2020",
"JsonWebKey2020": "sec:JsonWebKey2020",
"RsaSignature2018": "sec:RsaSignature2018",
"RsaVerificationKey2018": "sec:RsaVerificationKey2018",
"SchnorrSecp256k1Signature2019": "sec:SchnorrSecp256k1Signature2019",
Expand Down Expand Up @@ -49,6 +53,8 @@
"proofValue": "sec:proofValue",
"publicKey": {"@id": "sec:publicKey", "@type": "@id", "@container": "@set"},
"publicKeyBase58": "sec:publicKeyBase58",
"publicKeyMultibase": "sec:publicKeyMultibase",
"publicKeyJwk": "sec:publicKeyJwk",
"publicKeyPem": "sec:publicKeyPem",
"revoked": {"@id": "sec:revoked", "@type": "xsd:dateTime"},
"service": {"@id": "didv:service", "@type": "@id", "@container": "@set"},
Expand Down
77 changes: 77 additions & 0 deletions packages/credential-ld/src/contexts/ed25519-signature-2020-v1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"@context": {
"id": "@id",
"type": "@type",
"@protected": true,
"proof": {
"@id": "https://w3id.org/security#proof",
"@type": "@id",
"@container": "@graph"
},
"Ed25519VerificationKey2020": {
"@id": "https://w3id.org/security#Ed25519VerificationKey2020"
},
"Ed25519Signature2020": {
"@id": "https://w3id.org/security#Ed25519Signature2020",
"@context": {
"@protected": true,
"id": "@id",
"type": "@type",
"challenge": "https://w3id.org/security#challenge",
"created": {
"@id": "http://purl.org/dc/terms/created",
"@type": "http://www.w3.org/2001/XMLSchema#dateTime"
},
"domain": "https://w3id.org/security#domain",
"expires": {
"@id": "https://w3id.org/security#expiration",
"@type": "http://www.w3.org/2001/XMLSchema#dateTime"
},
"nonce": "https://w3id.org/security#nonce",
"proofPurpose": {
"@id": "https://w3id.org/security#proofPurpose",
"@type": "@vocab",
"@context": {
"@version": 1.1,
"@protected": true,
"id": "@id",
"type": "@type",
"assertionMethod": {
"@id": "https://w3id.org/security#assertionMethod",
"@type": "@id",
"@container": "@set"
},
"authentication": {
"@id": "https://w3id.org/security#authenticationMethod",
"@type": "@id",
"@container": "@set"
},
"capabilityInvocation": {
"@id": "https://w3id.org/security#capabilityInvocationMethod",
"@type": "@id",
"@container": "@set"
},
"capabilityDelegation": {
"@id": "https://w3id.org/security#capabilityDelegationMethod",
"@type": "@id",
"@container": "@set"
},
"keyAgreement": {
"@id": "https://w3id.org/security#keyAgreementMethod",
"@type": "@id",
"@container": "@set"
}
}
},
"proofValue": {
"@id": "https://w3id.org/security#proofValue",
"@type": "https://w3id.org/security#multibase"
},
"verificationMethod": {
"@id": "https://w3id.org/security#verificationMethod",
"@type": "@id"
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"@context": {
"@version": 1.1,
"id": "@id",
"type": "@type",
"@protected": true,
"JsonWebKey2020": {
"@id": "https://w3id.org/security#JsonWebKey2020"
},
"JsonWebSignature2020": {
"@id": "https://w3id.org/security#JsonWebSignature2020",
"@context": {
"@version": 1.1,
"id": "@id",
"type": "@type",
"@protected": true,
"challenge": "https://w3id.org/security#challenge",
"created": {
"@id": "http://purl.org/dc/terms/created",
"@type": "http://www.w3.org/2001/XMLSchema#dateTime"
},
"domain": "https://w3id.org/security#domain",
"expires": {
"@id": "https://w3id.org/security#expiration",
"@type": "http://www.w3.org/2001/XMLSchema#dateTime"
},
"jws": "https://w3id.org/security#jws",
"nonce": "https://w3id.org/security#nonce",
"proofPurpose": {
"@id": "https://w3id.org/security#proofPurpose",
"@type": "@vocab",
"@context": {
"@version": 1.1,
"@protected": true,
"id": "@id",
"type": "@type",
"assertionMethod": {
"@id": "https://w3id.org/security#assertionMethod",
"@type": "@id",
"@container": "@set"
},
"authentication": {
"@id": "https://w3id.org/security#authenticationMethod",
"@type": "@id",
"@container": "@set"
},
"capabilityInvocation": {
"@id": "https://w3id.org/security#capabilityInvocationMethod",
"@type": "@id",
"@container": "@set"
},
"capabilityDelegation": {
"@id": "https://w3id.org/security#capabilityDelegationMethod",
"@type": "@id",
"@container": "@set"
},
"keyAgreement": {
"@id": "https://w3id.org/security#keyAgreementMethod",
"@type": "@id",
"@container": "@set"
}
}
},
"verificationMethod": {
"@id": "https://w3id.org/security#verificationMethod",
"@type": "@id"
}
}
}
}
}
2 changes: 2 additions & 0 deletions packages/credential-ld/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export { LdDefaultContexts } from './ld-default-contexts'
export { VeramoLdSignature } from './ld-suites'
export * from './suites/EcdsaSecp256k1RecoverySignature2020'
export * from './suites/Ed25519Signature2018'
export * from './suites/Ed25519Signature2020'
export * from './suites/JsonWebSignature2020'

/**
* The parameter and return types schemas for the {@link @veramo/credential-ld#CredentialIssuerLD | CredentialIssuerLD}
Expand Down
8 changes: 4 additions & 4 deletions packages/credential-ld/src/ld-credential-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export class LdCredentialModule {
options: any,
context: IAgentContext<RequiredAgentMethods>,
): Promise<VerifiableCredential> {
const suite = this.ldSuiteLoader.getSignatureSuiteForKeyType(key.type)
const suite = this.ldSuiteLoader.getSignatureSuiteForKeyType(key.type, key.meta?.verificationMethod?.type ?? '')
const documentLoader = this.getDocumentLoader(context, options.fetchRemoteContexts)

// some suites can modify the incoming credential (e.g. add required contexts)
Expand All @@ -110,7 +110,7 @@ export class LdCredentialModule {
return await vc.issue({
...options,
credential,
suite: suite.getSuiteForSigning(key, issuerDid, verificationMethodId, context),
suite: await suite.getSuiteForSigning(key, issuerDid, verificationMethodId, context),
documentLoader,
compactProof: false,
})
Expand All @@ -126,15 +126,15 @@ export class LdCredentialModule {
options: any,
context: IAgentContext<RequiredAgentMethods>,
): Promise<VerifiablePresentation> {
const suite = this.ldSuiteLoader.getSignatureSuiteForKeyType(key.type)
const suite = this.ldSuiteLoader.getSignatureSuiteForKeyType(key.type, key.meta?.verificationMethod?.type ?? '')
const documentLoader = this.getDocumentLoader(context, options.fetchRemoteContexts)

suite.preSigningPresModification(presentation)

return await vc.signPresentation({
...options,
presentation,
suite: suite.getSuiteForSigning(key, holderDid, verificationMethodId, context),
suite: await suite.getSuiteForSigning(key, holderDid, verificationMethodId, context),
challenge,
domain,
documentLoader,
Expand Down
2 changes: 2 additions & 0 deletions packages/credential-ld/src/ld-default-contexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export const LdDefaultContexts = new Map([
['https://w3id.org/security/v3-unstable', require('./contexts/w3id.org_security_v3-unstable.json')],
['https://w3id.org/security/suites/ed25519-2018/v1', require('./contexts/w3id.org_security_suites_ed25519-2018_v1.json')],
['https://w3id.org/security/suites/x25519-2019/v1', require('./contexts/w3id.org_security_suites_x25519-2019_v1.json')],
['https://w3id.org/security/suites/ed25519-2020/v1', require('./contexts/ed25519-signature-2020-v1.json')],
['https://w3id.org/security/suites/jws-2020/v1', require('./contexts/json-web-signature-2020-v1.json')],
// ['https://w3id.org/did/v0.11', require('./contexts/did_v0.11.json')],
// ['https://veramo.io/contexts/socialmedia/v1', require('./contexts/socialmedia-v1.json')],
// ['https://veramo.io/contexts/kyc/v1', require('./contexts/kyc-v1.json')],
Expand Down
16 changes: 9 additions & 7 deletions packages/credential-ld/src/ld-suite-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,25 @@ import { TKeyType } from '@veramo/core'
export class LdSuiteLoader {
constructor(options: { veramoLdSignatures: VeramoLdSignature[] }) {
options.veramoLdSignatures.forEach((obj) => {
this.signatureMap[obj.getSupportedVeramoKeyType()] = obj
const keyType = obj.getSupportedVeramoKeyType()
const verificationType = obj.getSupportedVerificationType()
return this.signatureMap[keyType] = { ...this.signatureMap[keyType], [verificationType]: obj }
})
}
private signatureMap: Record<string, VeramoLdSignature> = {}
private signatureMap: Record<string, Record<string, VeramoLdSignature>> = {}

getSignatureSuiteForKeyType(type: TKeyType) {
const suite = this.signatureMap[type]
getSignatureSuiteForKeyType(type: TKeyType, verificationType: string) {
const suite = this.signatureMap[type]?.[verificationType]
if (suite) return suite

throw new Error('No Veramo LD Signature Suite for ' + type)
}

getAllSignatureSuites() {
return Object.values(this.signatureMap)
getAllSignatureSuites(): VeramoLdSignature[] {
return Object.values(this.signatureMap).map((x) => Object.values(x)).flat()
}

getAllSignatureSuiteTypes() {
return Object.values(this.signatureMap).map((x) => x.getSupportedVerificationType())
return Object.values(this.signatureMap).map((x) => Object.keys(x)).flat()
}
}
2 changes: 2 additions & 0 deletions packages/credential-ld/src/module-types/jsonld/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
declare module '@digitalcredentials/jsonld'
declare module '@digitalcredentials/jsonld-signatures'
declare module '@digitalcredentials/vc'
declare module '@digitalcredentials/ed25519-signature-2020'
declare module '@digitalcredentials/ed25519-verification-key-2020'
declare module '@veramo-community/lds-ecdsa-secp256k1-recovery2020'

declare module "*.json" {
Expand Down
80 changes: 80 additions & 0 deletions packages/credential-ld/src/suites/Ed25519Signature2020.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { RequiredAgentMethods, VeramoLdSignature } from '../ld-suites'
import { CredentialPayload, DIDDocument, IAgentContext, IKey, TKeyType } from '@veramo/core'
import * as u8a from 'uint8arrays'
import { Ed25519Signature2020 } from '@digitalcredentials/ed25519-signature-2020'
import { Ed25519VerificationKey2020 } from '@digitalcredentials/ed25519-verification-key-2020'
import { TextEncoder } from 'util'
/**
* Veramo wrapper for the Ed25519Signature2020 suite by digitalcredentials
*
* @alpha This API is experimental and is very likely to change or disappear in future releases without notice.
*/
export class VeramoEd25519Signature2020 extends VeramoLdSignature {
private readonly MULTIBASE_BASE58BTC_PREFIX = 'z'
private readonly MULTICODEC_PREFIX = [0xed, 0x01]

getSupportedVerificationType(): string {
return 'Ed25519VerificationKey2020'
}

getSupportedVeramoKeyType(): TKeyType {
return 'Ed25519'
}

getSuiteForSigning(
key: IKey,
issuerDid: string,
verificationMethodId: string,
context: IAgentContext<RequiredAgentMethods>,
): Promise<any> {
const controller = issuerDid

// DID Key ID
let id = verificationMethodId

const signer = {
// returns signatureBytes
sign: async (args: { data: Uint8Array }): Promise<Uint8Array> => {
const messageString = u8a.toString(args.data, 'base64')
const signature = await context.agent.keyManagerSign({
keyRef: key.kid,
data: messageString,
encoding: 'base64',
})
const utf8Encode = new TextEncoder()
return utf8Encode.encode(signature)
},
}

const verificationKey = new Ed25519VerificationKey2020({
id,
controller,
publicKeyMultibase: this.preSigningKeyModification(u8a.fromString(key.publicKeyHex, 'hex')),
signer: ()=> signer,
type: this.getSupportedVerificationType(),
})
// overwrite the signer since we're not passing the private key
verificationKey.signer = () => signer as any
return new Ed25519Signature2020({
key: verificationKey,
signer: signer
})
}

getSuiteForVerification(): any {
return new Ed25519Signature2020()
}

preSigningCredModification(credential: CredentialPayload): void {
// nothing to do here
}

preDidResolutionModification(didUrl: string, didDoc: DIDDocument): void {
// nothing to do here
}

preSigningKeyModification(key: Uint8Array): string {
const modifiedKey = Uint8Array.from([...this.MULTICODEC_PREFIX, ...key])
return `${this.MULTIBASE_BASE58BTC_PREFIX}${u8a.toString(modifiedKey, 'base58btc')}`
}
}
Loading

0 comments on commit fbf7d48

Please sign in to comment.