Skip to content

Commit

Permalink
Merge branch 'main' into cheqd
Browse files Browse the repository at this point in the history
  • Loading branch information
sownak authored Jan 31, 2025
2 parents 9e0cc04 + 27f971d commit bd80443
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 124 deletions.
5 changes: 5 additions & 0 deletions .changeset/lemon-singers-sneeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@credo-ts/core': patch
---

feat: support EdDSA, P384 and P512 for mdoc holder binding
5 changes: 5 additions & 0 deletions .changeset/tall-geese-impress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@credo-ts/openid4vc': patch
---

fix: only include supported mdoc algs in vp_formats metadata
7 changes: 7 additions & 0 deletions .changeset/witty-rabbits-act.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@credo-ts/core': minor
---

feat: support ISO 18013-7 Draft 2024-03-12.

This mostly changes the structure of the calculated session transcript bytes for usage with OpenID4VP. This is a breaking change and incompatible with older versions.
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"@peculiar/asn1-schema": "^2.3.13",
"@peculiar/asn1-x509": "^2.3.13",
"@peculiar/x509": "^1.12.1",
"@animo-id/mdoc": "0.2.39",
"@animo-id/mdoc": "0.3.0",
"@sd-jwt/core": "^0.7.2",
"@sd-jwt/decode": "^0.7.2",
"@sd-jwt/jwt-status-list": "^0.7.2",
Expand Down
25 changes: 6 additions & 19 deletions packages/core/src/modules/mdoc/Mdoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { X509Certificate, X509ModuleConfig } from '../x509'
import { TypedArrayEncoder } from './../../utils'
import { getMdocContext } from './MdocContext'
import { MdocError } from './MdocError'
import { isMdocSupportedSignatureAlgorithm, mdocSupporteSignatureAlgorithms } from './mdocSupportedAlgs'

/**
* This class represents a IssuerSigned Mdoc Document,
Expand Down Expand Up @@ -118,28 +119,14 @@ export class Mdoc {
const cert = X509Certificate.fromEncodedCertificate(issuerCertificate)
const issuerKey = getJwkFromKey(cert.publicKey)

const alg = issuerKey.supportedSignatureAlgorithms.find(
(
alg
): alg is
| JwaSignatureAlgorithm.ES256
| JwaSignatureAlgorithm.ES384
| JwaSignatureAlgorithm.ES512
| JwaSignatureAlgorithm.EdDSA => {
return (
alg === JwaSignatureAlgorithm.ES256 ||
alg === JwaSignatureAlgorithm.ES384 ||
alg === JwaSignatureAlgorithm.ES512 ||
alg === JwaSignatureAlgorithm.EdDSA
)
}
)

const alg = issuerKey.supportedSignatureAlgorithms.find(isMdocSupportedSignatureAlgorithm)
if (!alg) {
throw new MdocError(
`Cannot find a suitable JwaSignatureAlgorithm for signing the mdoc. Supported algorithms are 'ES256', 'ES384', 'ES512'. The issuer key supports: ${issuerKey.supportedSignatureAlgorithms.join(
`Unable to create sign mdoc. No supported signature algorithm found to sign mdoc for jwk with key type ${
issuerKey.keyType
}. Key supports algs ${issuerKey.supportedSignatureAlgorithms.join(
', '
)}`
)}. mdoc supports algs ${mdocSupporteSignatureAlgorithms.join(', ')}`
)
}

Expand Down
46 changes: 37 additions & 9 deletions packages/core/src/modules/mdoc/MdocDeviceResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import type {
MdocDeviceResponseVerifyOptions,
} from './MdocOptions'
import type { AgentContext } from '../../agent'
import type { JwkJson } from '../../crypto'
import type { DifPresentationExchangeDefinition } from '../dif-presentation-exchange'
import type { PresentationDefinition } from '@animo-id/mdoc'
import type { IssuerSignedDocument, PresentationDefinition } from '@animo-id/mdoc'
import type { InputDescriptorV2 } from '@sphereon/pex-models'

import {
Expand All @@ -21,6 +22,7 @@ import {
DeviceRequest,
} from '@animo-id/mdoc'

import { getJwkFromJson } from '../../crypto'
import { CredoError } from '../../error'
import { uuid } from '../../utils/uuid'
import { X509Certificate } from '../x509/X509Certificate'
Expand All @@ -30,6 +32,7 @@ import { TypedArrayEncoder } from './../../utils'
import { Mdoc } from './Mdoc'
import { getMdocContext } from './MdocContext'
import { MdocError } from './MdocError'
import { isMdocSupportedSignatureAlgorithm, mdocSupporteSignatureAlgorithms } from './mdocSupportedAlgs'

export class MdocDeviceResponse {
private constructor(public base64Url: string, public documents: Mdoc[]) {}
Expand Down Expand Up @@ -173,10 +176,9 @@ export class MdocDeviceResponse {
const combinedDeviceResponseMdoc = new MDoc()

for (const issuerSignedDocument of issuerSignedDocuments) {
const { publicDeviceJwk, alg } = this.parseDeviceKeyFromIssuerSigned(issuerSignedDocument)
const deviceKey = issuerSignedDocument.issuerSigned.issuerAuth.decodedPayload.deviceKeyInfo?.deviceKey
if (!deviceKey) throw new CredoError(`Device key is missing in mdoc with doctype ${issuerSignedDocument.docType}`)

const publicDeviceJwk = COSEKey.import(deviceKey).toJWK()
if (!deviceKey) throw new MdocError(`Device key is missing in mdoc with doctype ${issuerSignedDocument.docType}`)

// We do PEX filtering on a different layer, so we only include the needed input descriptor here
const presentationDefinitionForDocument = {
Expand All @@ -189,7 +191,7 @@ export class MdocDeviceResponse {
const deviceResponseBuilder = DeviceResponse.from(new MDoc([issuerSignedDocument]))
.usingPresentationDefinition(presentationDefinitionForDocument)
.usingSessionTranscriptForOID4VP(sessionTranscriptOptions)
.authenticateWithSignature(publicDeviceJwk, 'ES256')
.authenticateWithSignature(publicDeviceJwk, alg)

for (const [nameSpace, nameSpaceValue] of Object.entries(options.deviceNameSpaces ?? {})) {
deviceResponseBuilder.addDeviceNameSpace(nameSpace, nameSpaceValue)
Expand Down Expand Up @@ -219,10 +221,10 @@ export class MdocDeviceResponse {
const combinedDeviceResponseMdoc = new MDoc()

for (const issuerSignedDocument of issuerSignedDocuments) {
const { publicDeviceJwk, alg } = this.parseDeviceKeyFromIssuerSigned(issuerSignedDocument)
const deviceKey = issuerSignedDocument.issuerSigned.issuerAuth.decodedPayload.deviceKeyInfo?.deviceKey
if (!deviceKey) throw new CredoError(`Device key is missing in mdoc with doctype ${issuerSignedDocument.docType}`)

const publicDeviceJwk = COSEKey.import(deviceKey).toJWK()
const deviceRequestForDocument = new DeviceRequest(
options.deviceRequest.version,
options.deviceRequest.docRequests.filter(
Expand All @@ -233,7 +235,7 @@ export class MdocDeviceResponse {
const deviceResponseBuilder = DeviceResponse.from(new MDoc([issuerSignedDocument]))
.usingSessionTranscriptBytes(options.sessionTranscriptBytes)
.usingDeviceRequest(deviceRequestForDocument)
.authenticateWithSignature(publicDeviceJwk, 'ES256')
.authenticateWithSignature(publicDeviceJwk, alg)

for (const [nameSpace, nameSpaceValue] of Object.entries(options.deviceNameSpaces ?? {})) {
deviceResponseBuilder.addDeviceNameSpace(nameSpace, nameSpaceValue)
Expand Down Expand Up @@ -287,8 +289,10 @@ export class MdocDeviceResponse {
const result = await verifier.verifyDeviceResponse(
{
encodedDeviceResponse: TypedArrayEncoder.fromBase64(this.base64Url),
//ephemeralReaderKey: options.verifierKey ? getJwkFromKey(options.verifierKey).toJson() : undefined,
encodedSessionTranscript: DeviceResponse.calculateSessionTranscriptForOID4VP(options.sessionTranscriptOptions),
encodedSessionTranscript: await DeviceResponse.calculateSessionTranscriptForOID4VP({
...options.sessionTranscriptOptions,
context: mdocContext,
}),
trustedCertificates: trustedCertificates.map(
(cert) => X509Certificate.fromEncodedCertificate(cert).rawCertificate
),
Expand All @@ -307,4 +311,28 @@ export class MdocDeviceResponse {

return this.documents
}

private static parseDeviceKeyFromIssuerSigned(issuerSignedDocument: IssuerSignedDocument) {
const deviceKey = issuerSignedDocument.issuerSigned.issuerAuth.decodedPayload.deviceKeyInfo?.deviceKey
if (!deviceKey) throw new MdocError(`Device key is missing in mdoc with doctype ${issuerSignedDocument.docType}`)

const publicDeviceJwk = COSEKey.import(deviceKey).toJWK()

const jwkInstance = getJwkFromJson(publicDeviceJwk as JwkJson)
const signatureAlgorithm = jwkInstance.supportedSignatureAlgorithms.find(isMdocSupportedSignatureAlgorithm)
if (!signatureAlgorithm) {
throw new MdocError(
`Unable to create mdoc device response. No supported signature algorithm found to sign device response for jwk with key type ${
jwkInstance.keyType
}. Key supports algs ${jwkInstance.supportedSignatureAlgorithms.join(
', '
)}. mdoc supports algs ${mdocSupporteSignatureAlgorithms.join(', ')}`
)
}

return {
publicDeviceJwk,
alg: signatureAlgorithm,
}
}
}
Loading

0 comments on commit bd80443

Please sign in to comment.