@credo-ts/core 0.6.2-alpha-20251210145840 → 0.6.2-alpha-20251211115250

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.mjs CHANGED
@@ -25,15 +25,15 @@ import { deepEquality, equalsIgnoreOrder, equalsWithOrder } from "./utils/deepEq
25
25
  import { base64ToBase64URL } from "./utils/base64.mjs";
26
26
  import { TypedArrayEncoder } from "./utils/TypedArrayEncoder.mjs";
27
27
  import { indyDidFromPublicKeyBase58, isDid } from "./utils/did.mjs";
28
- import { JsonEncoder } from "./utils/JsonEncoder.mjs";
29
- import { MessageValidator } from "./utils/MessageValidator.mjs";
30
- import { JsonTransformer } from "./utils/JsonTransformer.mjs";
31
- import { MultiBaseEncoder } from "./utils/MultiBaseEncoder.mjs";
32
28
  import { Sha1 } from "./crypto/hashes/Sha1.mjs";
33
29
  import { Sha256 } from "./crypto/hashes/Sha256.mjs";
34
30
  import { Sha384 } from "./crypto/hashes/Sha384.mjs";
35
31
  import { Sha512 } from "./crypto/hashes/Sha512.mjs";
36
32
  import { Hasher } from "./crypto/hashes/Hasher.mjs";
33
+ import { JsonEncoder } from "./utils/JsonEncoder.mjs";
34
+ import { MessageValidator } from "./utils/MessageValidator.mjs";
35
+ import { JsonTransformer } from "./utils/JsonTransformer.mjs";
36
+ import { MultiBaseEncoder } from "./utils/MultiBaseEncoder.mjs";
37
37
  import { MultiHashEncoder } from "./utils/MultiHashEncoder.mjs";
38
38
  import timestamp, { addSecondsToDate, dateToSeconds, nowInSeconds } from "./utils/timestamp.mjs";
39
39
  import { Metadata } from "./storage/Metadata.mjs";
@@ -1,5 +1,6 @@
1
1
  import { Query, QueryOptions } from "../../storage/StorageService.mjs";
2
2
  import { SdJwtVcHeader, SdJwtVcPayload, SdJwtVcPresentOptions, SdJwtVcSignOptions, SdJwtVcStoreOptions, SdJwtVcVerifyOptions } from "./SdJwtVcOptions.mjs";
3
+ import { SdJwtVcTypeMetadata } from "./typeMetadata.mjs";
3
4
  import { SdJwtVc, SdJwtVcService } from "./SdJwtVcService.mjs";
4
5
  import { SdJwtVcRecord } from "./repository/SdJwtVcRecord.mjs";
5
6
  import "./repository/index.mjs";
@@ -38,6 +39,18 @@ declare class SdJwtVcApi {
38
39
  sdJwtVc?: SdJwtVc<Header, Payload> | undefined;
39
40
  error: Error;
40
41
  }>;
42
+ /**
43
+ * Fetches the type metadata for the `vct`. Only supports `https` VCT url for now.
44
+ *
45
+ * If fetching the VCT directly fails, it will fallback to the legacy vct path. If both
46
+ * fail, an error will be thrown, unless `throwErrorOnFetchError` is set to `false`.
47
+ *
48
+ * The integrity will always be verified if the metadata was resolved. The `extends` keyword is
49
+ * not resolved yet.
50
+ */
51
+ fetchTypeMetadata(sdJwtVc: SdJwtVc, options?: {
52
+ throwErrorOnFetchError?: boolean;
53
+ }): Promise<SdJwtVcTypeMetadata | undefined>;
41
54
  /**
42
55
  * Get and validate a sd-jwt-vc from a serialized JWT.
43
56
  */
@@ -1 +1 @@
1
- {"version":3,"file":"SdJwtVcApi.d.mts","names":[],"sources":["../../../src/modules/sd-jwt-vc/SdJwtVcApi.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;cAmBa,UAAA;;;EAAA,WAAA,CAAA,YAAU,EAIY,YAJZ,EAAA,cAAA,EAI0C,cAJ1C;EAIY,IAAA,CAAA,gBAKC,cALD,CAAA,CAAA,OAAA,EAK0B,kBAL1B,CAK6C,OAL7C,CAAA,CAAA,EAKqD,OALrD,CAKqD,OALrD,CAKqD,aALrD,EAKqD,cALrD,CAAA,CAAA;EAA8B;;;;;;;EAKuB,OAAA,CAAA,gBAWjD,cAXiD,GAWhC,cAXgC,CAAA,CAAA,OAAA,EAY3E,qBAZ2E,CAYrD,OAZqD,CAAA,CAAA,EAanF,OAbmF,CAAA,MAAA,CAAA;EAWjD;;;;;;;EAasD,MAAA,CAAA,eAAxD,aAAwD,EAAA,gBAAzB,cAAyB,CAAA,CAAA,OAAA,EAAA,oBAAA,CAAA,EAAoB,OAApB,CAAA;;;;;;;;EAAoB;;;EAOR,WAAA,CAAA,eAArE,aAAqE,EAAA,gBAAtC,cAAsC,CAAA,CAAA,cAAA,EAAA,MAAA,CAAA,EAAA,OAAA,CAAA,MAAA,EAAA,OAAA,CAAA;EAAA,KAAA,CAAA,OAAA,EAI3E,mBAJ2E,CAAA,EAIxD,OAJwD,CAIxD,aAJwD,CAAA;EAAA,OAAA,CAAA,EAAA,EAAA,MAAA,CAAA,EAQrE,OARqE,CAQ7D,aAR6D,CAAA;EAI3E,MAAA,CAAA,CAAA,EAQL,OARK,CAQG,KARH,CAQS,aART,CAAA,CAAA;EAAmB,cAAA,CAAA,KAAA,EAYZ,KAZY,CAYN,aAZM,CAAA,EAAA,YAAA,CAAA,EAYyB,YAZzB,CAAA,EAYwC,OAZxC,CAYgD,KAZhD,CAYsD,aAZtD,CAAA,CAAA;EAAA,UAAA,CAAA,EAAA,EAAA,MAAA,CAAA,EAgBb,OAhBa,CAAA,IAAA,CAAA;EAIL,MAAA,CAAA,aAAA,EAgBP,aAhBO,CAAA,EAgBM,OAhBN,CAAA,IAAA,CAAA"}
1
+ {"version":3,"file":"SdJwtVcApi.d.mts","names":[],"sources":["../../../src/modules/sd-jwt-vc/SdJwtVcApi.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;cAoBa,UAAA;;;EAAA,WAAA,CAAA,YAAU,EAIY,YAJZ,EAAA,cAAA,EAI0C,cAJ1C;EAIY,IAAA,CAAA,gBAKC,cALD,CAAA,CAAA,OAAA,EAK0B,kBAL1B,CAK6C,OAL7C,CAAA,CAAA,EAKqD,OALrD,CAKqD,OALrD,CAKqD,aALrD,EAKqD,cALrD,CAAA,CAAA;EAA8B;;;;;;;EAKuB,OAAA,CAAA,gBAWjD,cAXiD,GAWhC,cAXgC,CAAA,CAAA,OAAA,EAY3E,qBAZ2E,CAYrD,OAZqD,CAAA,CAAA,EAanF,OAbmF,CAAA,MAAA,CAAA;EAWjD;;;;;;;EAasD,MAAA,CAAA,eAAxD,aAAwD,EAAA,gBAAzB,cAAyB,CAAA,CAAA,OAAA,EAAA,oBAAA,CAAA,EAAoB,OAApB,CAAA;;;;;;;;EAAoB;;;;;;;;;EA2BnF,iBAAA,CAAA,OAAA,EAbjB,OAaiB,EAAA,OAAmB,CAAnB,EAAA;IAAmB,sBAAA,CAAA,EAAA,OAAA;EAAA,CAAA,CAAA,EAX5C,OAW4C,CAXpC,mBAWoC,GAAA,SAAA,CAAA;EAIL;;;EAIX,WAAA,CAAA,eAZG,aAYH,EAAA,gBAZkC,cAYlC,CAAA,CAAA,cAAA,EAAA,MAAA,CAAA,EAZwE,OAYxE,CAZwE,MAYxE,EAZwE,OAYxE,CAAA;EAAR,KAAA,CAAA,OAAA,EARK,mBAQL,CAAA,EARwB,OAQxB,CARwB,aAQxB,CAAA;EAIkB,OAAA,CAAA,EAAA,EAAA,MAAA,CAAA,EARP,OAQO,CARC,aAQD,CAAA;EAAN,MAAA,CAAA,CAAA,EAJZ,OAIY,CAJJ,KAII,CAJE,aAIF,CAAA,CAAA;EAAqC,cAAA,CAAA,KAAA,EAArC,KAAqC,CAA/B,aAA+B,CAAA,EAAA,YAAA,CAAA,EAAA,YAAA,CAAA,EAAe,OAAf,CAAuB,KAAvB,CAA6B,aAA7B,CAAA,CAAA;EAA6B,UAAA,CAAA,EAAA,EAAA,MAAA,CAAA,EAInE,OAJmE,CAAA,IAAA,CAAA;EAAN,MAAA,CAAA,aAAA,EAQ5D,aAR4D,CAAA,EAQ/C,OAR+C,CAAA,IAAA,CAAA"}
@@ -38,6 +38,18 @@ let SdJwtVcApi = class SdJwtVcApi$1 {
38
38
  return await this.sdJwtVcService.verify(this.agentContext, options);
39
39
  }
40
40
  /**
41
+ * Fetches the type metadata for the `vct`. Only supports `https` VCT url for now.
42
+ *
43
+ * If fetching the VCT directly fails, it will fallback to the legacy vct path. If both
44
+ * fail, an error will be thrown, unless `throwErrorOnFetchError` is set to `false`.
45
+ *
46
+ * The integrity will always be verified if the metadata was resolved. The `extends` keyword is
47
+ * not resolved yet.
48
+ */
49
+ async fetchTypeMetadata(sdJwtVc, options) {
50
+ return this.sdJwtVcService.fetchTypeMetadata(this.agentContext, sdJwtVc, options);
51
+ }
52
+ /**
41
53
  * Get and validate a sd-jwt-vc from a serialized JWT.
42
54
  */
43
55
  fromCompact(sdJwtVcCompact) {
@@ -1 +1 @@
1
- {"version":3,"file":"SdJwtVcApi.mjs","names":["SdJwtVcApi"],"sources":["../../../src/modules/sd-jwt-vc/SdJwtVcApi.ts"],"sourcesContent":["import { AgentContext } from '../../agent'\nimport { injectable } from '../../plugins'\nimport type { Query, QueryOptions } from '../../storage/StorageService'\nimport type { SdJwtVcRecord } from './repository'\nimport type {\n SdJwtVcHeader,\n SdJwtVcPayload,\n SdJwtVcPresentOptions,\n SdJwtVcSignOptions,\n SdJwtVcStoreOptions,\n SdJwtVcVerifyOptions,\n} from './SdJwtVcOptions'\n\nimport { SdJwtVcService } from './SdJwtVcService'\n\n/**\n * @public\n */\n@injectable()\nexport class SdJwtVcApi {\n private agentContext: AgentContext\n private sdJwtVcService: SdJwtVcService\n\n public constructor(agentContext: AgentContext, sdJwtVcService: SdJwtVcService) {\n this.agentContext = agentContext\n this.sdJwtVcService = sdJwtVcService\n }\n\n public async sign<Payload extends SdJwtVcPayload>(options: SdJwtVcSignOptions<Payload>) {\n return await this.sdJwtVcService.sign<Payload>(this.agentContext, options)\n }\n\n /**\n *\n * Create a compact presentation of the sd-jwt.\n * This presentation can be send in- or out-of-band to the verifier.\n *\n * Also, whether to include the holder key binding.\n */\n public async present<Payload extends SdJwtVcPayload = SdJwtVcPayload>(\n options: SdJwtVcPresentOptions<Payload>\n ): Promise<string> {\n return await this.sdJwtVcService.present(this.agentContext, options)\n }\n\n /**\n *\n * Verify an incoming sd-jwt. It will check whether everything is valid, but also returns parts of the validation.\n *\n * For example, you might still want to continue with a flow if not all the claims are included, but the signature is valid.\n *\n */\n public async verify<Header extends SdJwtVcHeader, Payload extends SdJwtVcPayload>(options: SdJwtVcVerifyOptions) {\n return await this.sdJwtVcService.verify<Header, Payload>(this.agentContext, options)\n }\n\n /**\n * Get and validate a sd-jwt-vc from a serialized JWT.\n */\n public fromCompact<Header extends SdJwtVcHeader, Payload extends SdJwtVcPayload>(sdJwtVcCompact: string) {\n return this.sdJwtVcService.fromCompact<Header, Payload>(sdJwtVcCompact)\n }\n\n public async store(options: SdJwtVcStoreOptions) {\n return await this.sdJwtVcService.store(this.agentContext, options)\n }\n\n public async getById(id: string): Promise<SdJwtVcRecord> {\n return await this.sdJwtVcService.getById(this.agentContext, id)\n }\n\n public async getAll(): Promise<Array<SdJwtVcRecord>> {\n return await this.sdJwtVcService.getAll(this.agentContext)\n }\n\n public async findAllByQuery(query: Query<SdJwtVcRecord>, queryOptions?: QueryOptions): Promise<Array<SdJwtVcRecord>> {\n return await this.sdJwtVcService.findByQuery(this.agentContext, query, queryOptions)\n }\n\n public async deleteById(id: string) {\n return await this.sdJwtVcService.deleteById(this.agentContext, id)\n }\n\n public async update(sdJwtVcRecord: SdJwtVcRecord) {\n return await this.sdJwtVcService.update(this.agentContext, sdJwtVcRecord)\n }\n}\n"],"mappings":";;;;;;;;;;;AAmBO,uBAAMA,aAAW;CAItB,AAAO,YAAY,cAA4B,gBAAgC;AAC7E,OAAK,eAAe;AACpB,OAAK,iBAAiB;;CAGxB,MAAa,KAAqC,SAAsC;AACtF,SAAO,MAAM,KAAK,eAAe,KAAc,KAAK,cAAc,QAAQ;;;;;;;;;CAU5E,MAAa,QACX,SACiB;AACjB,SAAO,MAAM,KAAK,eAAe,QAAQ,KAAK,cAAc,QAAQ;;;;;;;;;CAUtE,MAAa,OAAqE,SAA+B;AAC/G,SAAO,MAAM,KAAK,eAAe,OAAwB,KAAK,cAAc,QAAQ;;;;;CAMtF,AAAO,YAA0E,gBAAwB;AACvG,SAAO,KAAK,eAAe,YAA6B,eAAe;;CAGzE,MAAa,MAAM,SAA8B;AAC/C,SAAO,MAAM,KAAK,eAAe,MAAM,KAAK,cAAc,QAAQ;;CAGpE,MAAa,QAAQ,IAAoC;AACvD,SAAO,MAAM,KAAK,eAAe,QAAQ,KAAK,cAAc,GAAG;;CAGjE,MAAa,SAAwC;AACnD,SAAO,MAAM,KAAK,eAAe,OAAO,KAAK,aAAa;;CAG5D,MAAa,eAAe,OAA6B,cAA4D;AACnH,SAAO,MAAM,KAAK,eAAe,YAAY,KAAK,cAAc,OAAO,aAAa;;CAGtF,MAAa,WAAW,IAAY;AAClC,SAAO,MAAM,KAAK,eAAe,WAAW,KAAK,cAAc,GAAG;;CAGpE,MAAa,OAAO,eAA8B;AAChD,SAAO,MAAM,KAAK,eAAe,OAAO,KAAK,cAAc,cAAc;;;yBAlE5E,YAAY"}
1
+ {"version":3,"file":"SdJwtVcApi.mjs","names":["SdJwtVcApi"],"sources":["../../../src/modules/sd-jwt-vc/SdJwtVcApi.ts"],"sourcesContent":["import { AgentContext } from '../../agent'\nimport { injectable } from '../../plugins'\nimport type { Query, QueryOptions } from '../../storage/StorageService'\nimport type { SdJwtVcRecord } from './repository'\nimport type {\n SdJwtVcHeader,\n SdJwtVcPayload,\n SdJwtVcPresentOptions,\n SdJwtVcSignOptions,\n SdJwtVcStoreOptions,\n SdJwtVcVerifyOptions,\n} from './SdJwtVcOptions'\n\nimport { type SdJwtVc, SdJwtVcService } from './SdJwtVcService'\nimport type { SdJwtVcTypeMetadata } from './typeMetadata'\n\n/**\n * @public\n */\n@injectable()\nexport class SdJwtVcApi {\n private agentContext: AgentContext\n private sdJwtVcService: SdJwtVcService\n\n public constructor(agentContext: AgentContext, sdJwtVcService: SdJwtVcService) {\n this.agentContext = agentContext\n this.sdJwtVcService = sdJwtVcService\n }\n\n public async sign<Payload extends SdJwtVcPayload>(options: SdJwtVcSignOptions<Payload>) {\n return await this.sdJwtVcService.sign<Payload>(this.agentContext, options)\n }\n\n /**\n *\n * Create a compact presentation of the sd-jwt.\n * This presentation can be send in- or out-of-band to the verifier.\n *\n * Also, whether to include the holder key binding.\n */\n public async present<Payload extends SdJwtVcPayload = SdJwtVcPayload>(\n options: SdJwtVcPresentOptions<Payload>\n ): Promise<string> {\n return await this.sdJwtVcService.present(this.agentContext, options)\n }\n\n /**\n *\n * Verify an incoming sd-jwt. It will check whether everything is valid, but also returns parts of the validation.\n *\n * For example, you might still want to continue with a flow if not all the claims are included, but the signature is valid.\n *\n */\n public async verify<Header extends SdJwtVcHeader, Payload extends SdJwtVcPayload>(options: SdJwtVcVerifyOptions) {\n return await this.sdJwtVcService.verify<Header, Payload>(this.agentContext, options)\n }\n\n /**\n * Fetches the type metadata for the `vct`. Only supports `https` VCT url for now.\n *\n * If fetching the VCT directly fails, it will fallback to the legacy vct path. If both\n * fail, an error will be thrown, unless `throwErrorOnFetchError` is set to `false`.\n *\n * The integrity will always be verified if the metadata was resolved. The `extends` keyword is\n * not resolved yet.\n */\n public async fetchTypeMetadata(\n sdJwtVc: SdJwtVc,\n options?: { throwErrorOnFetchError?: boolean }\n ): Promise<SdJwtVcTypeMetadata | undefined> {\n return this.sdJwtVcService.fetchTypeMetadata(this.agentContext, sdJwtVc, options)\n }\n\n /**\n * Get and validate a sd-jwt-vc from a serialized JWT.\n */\n public fromCompact<Header extends SdJwtVcHeader, Payload extends SdJwtVcPayload>(sdJwtVcCompact: string) {\n return this.sdJwtVcService.fromCompact<Header, Payload>(sdJwtVcCompact)\n }\n\n public async store(options: SdJwtVcStoreOptions) {\n return await this.sdJwtVcService.store(this.agentContext, options)\n }\n\n public async getById(id: string): Promise<SdJwtVcRecord> {\n return await this.sdJwtVcService.getById(this.agentContext, id)\n }\n\n public async getAll(): Promise<Array<SdJwtVcRecord>> {\n return await this.sdJwtVcService.getAll(this.agentContext)\n }\n\n public async findAllByQuery(query: Query<SdJwtVcRecord>, queryOptions?: QueryOptions): Promise<Array<SdJwtVcRecord>> {\n return await this.sdJwtVcService.findByQuery(this.agentContext, query, queryOptions)\n }\n\n public async deleteById(id: string) {\n return await this.sdJwtVcService.deleteById(this.agentContext, id)\n }\n\n public async update(sdJwtVcRecord: SdJwtVcRecord) {\n return await this.sdJwtVcService.update(this.agentContext, sdJwtVcRecord)\n }\n}\n"],"mappings":";;;;;;;;;;;AAoBO,uBAAMA,aAAW;CAItB,AAAO,YAAY,cAA4B,gBAAgC;AAC7E,OAAK,eAAe;AACpB,OAAK,iBAAiB;;CAGxB,MAAa,KAAqC,SAAsC;AACtF,SAAO,MAAM,KAAK,eAAe,KAAc,KAAK,cAAc,QAAQ;;;;;;;;;CAU5E,MAAa,QACX,SACiB;AACjB,SAAO,MAAM,KAAK,eAAe,QAAQ,KAAK,cAAc,QAAQ;;;;;;;;;CAUtE,MAAa,OAAqE,SAA+B;AAC/G,SAAO,MAAM,KAAK,eAAe,OAAwB,KAAK,cAAc,QAAQ;;;;;;;;;;;CAYtF,MAAa,kBACX,SACA,SAC0C;AAC1C,SAAO,KAAK,eAAe,kBAAkB,KAAK,cAAc,SAAS,QAAQ;;;;;CAMnF,AAAO,YAA0E,gBAAwB;AACvG,SAAO,KAAK,eAAe,YAA6B,eAAe;;CAGzE,MAAa,MAAM,SAA8B;AAC/C,SAAO,MAAM,KAAK,eAAe,MAAM,KAAK,cAAc,QAAQ;;CAGpE,MAAa,QAAQ,IAAoC;AACvD,SAAO,MAAM,KAAK,eAAe,QAAQ,KAAK,cAAc,GAAG;;CAGjE,MAAa,SAAwC;AACnD,SAAO,MAAM,KAAK,eAAe,OAAO,KAAK,aAAa;;CAG5D,MAAa,eAAe,OAA6B,cAA4D;AACnH,SAAO,MAAM,KAAK,eAAe,YAAY,KAAK,cAAc,OAAO,aAAa;;CAGtF,MAAa,WAAW,IAAY;AAClC,SAAO,MAAM,KAAK,eAAe,WAAW,KAAK,cAAc,GAAG;;CAGpE,MAAa,OAAO,eAA8B;AAChD,SAAO,MAAM,KAAK,eAAe,OAAO,KAAK,cAAc,cAAc;;;yBAlF5E,YAAY"}
@@ -79,6 +79,13 @@ declare class SdJwtVcService {
79
79
  sdJwtVc?: SdJwtVc<Header, Payload>;
80
80
  error: Error;
81
81
  }>;
82
+ fetchTypeMetadata(agentContext: AgentContext, sdJwtVc: SdJwtVc, {
83
+ throwErrorOnFetchError,
84
+ throwErrorOnUnsupportedVctValue
85
+ }?: {
86
+ throwErrorOnFetchError?: boolean;
87
+ throwErrorOnUnsupportedVctValue?: boolean;
88
+ }): Promise<SdJwtVcTypeMetadata | undefined>;
82
89
  store(agentContext: AgentContext, options: SdJwtVcStoreOptions): Promise<SdJwtVcRecord>;
83
90
  getById(agentContext: AgentContext, id: string): Promise<SdJwtVcRecord>;
84
91
  getAll(agentContext: AgentContext): Promise<Array<SdJwtVcRecord>>;
@@ -1 +1 @@
1
- {"version":3,"file":"SdJwtVcService.d.mts","names":[],"sources":["../../../src/modules/sd-jwt-vc/SdJwtVcService.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"SdJwtVcService.d.mts","names":[],"sources":["../../../src/modules/sd-jwt-vc/SdJwtVcService.ts"],"sourcesContent":[],"mappings":"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"}
@@ -7,6 +7,7 @@ import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.99.0/helpers/
7
7
  import "../../agent/index.mjs";
8
8
  import { TypedArrayEncoder } from "../../utils/TypedArrayEncoder.mjs";
9
9
  import { Hasher } from "../../crypto/hashes/Hasher.mjs";
10
+ import { IntegrityVerifier } from "../../utils/IntegrityVerifier.mjs";
10
11
  import { dateToSeconds, nowInSeconds } from "../../utils/timestamp.mjs";
11
12
  import "../../utils/index.mjs";
12
13
  import { KeyManagementApi } from "../kms/KeyManagementApi.mjs";
@@ -124,7 +125,7 @@ let SdJwtVcService = class SdJwtVcService$1 {
124
125
  if (!leafCertificate.sanUriNames?.includes(iss) && !leafCertificate.sanDnsNames?.includes(getDomainFromUrl(iss))) throw new SdJwtVcError(`The 'iss' claim in the payload does not match a 'SAN-URI' name and the domain extracted from the HTTPS URI does not match a 'SAN-DNS' name in the x5c certificate. Either remove the 'iss' claim or make it match with at least one SAN-URI or DNS-URI entry`);
125
126
  }
126
127
  async verify(agentContext, { compactSdJwtVc, keyBinding, requiredClaimKeys, fetchTypeMetadata, trustedCertificates, now }) {
127
- const sdjwt = new SDJwtVcInstance({ ...this.getBaseSdJwtConfig(agentContext) });
128
+ const sdjwt = new SDJwtVcInstance(this.getBaseSdJwtConfig(agentContext));
128
129
  let sdJwtVc;
129
130
  try {
130
131
  sdJwtVc = await sdjwt.decode(compactSdJwtVc);
@@ -200,16 +201,10 @@ let SdJwtVcService = class SdJwtVcService$1 {
200
201
  sdJwtVc: returnSdJwtVc
201
202
  };
202
203
  }
203
- try {
204
- const vct = returnSdJwtVc.payload?.vct;
205
- if (fetchTypeMetadata && typeof vct === "string" && vct.startsWith("https://")) {
206
- const vctElements = vct.split("/");
207
- vctElements.splice(3, 0, ".well-known/vct");
208
- const vctUrl = vctElements.join("/");
209
- const response = await agentContext.config.agentDependencies.fetch(vctUrl);
210
- if (response.ok) returnSdJwtVc.typeMetadata = await response.json();
211
- }
212
- } catch (_error) {}
204
+ if (fetchTypeMetadata) returnSdJwtVc.typeMetadata = await this.fetchTypeMetadata(agentContext, returnSdJwtVc, {
205
+ throwErrorOnFetchError: false,
206
+ throwErrorOnUnsupportedVctValue: false
207
+ });
213
208
  } catch (error) {
214
209
  return {
215
210
  isValid: false,
@@ -222,6 +217,36 @@ let SdJwtVcService = class SdJwtVcService$1 {
222
217
  sdJwtVc: returnSdJwtVc
223
218
  };
224
219
  }
220
+ async fetchTypeMetadata(agentContext, sdJwtVc, { throwErrorOnFetchError = true, throwErrorOnUnsupportedVctValue = true } = {}) {
221
+ const vct = sdJwtVc.payload.vct;
222
+ const vctIntegrity = sdJwtVc.payload["vct#integrity"];
223
+ if (!vct || typeof vct !== "string" || !vct.startsWith("https://")) {
224
+ if (!throwErrorOnUnsupportedVctValue) return void 0;
225
+ throw new SdJwtVcError(`Unable to resolve type metadata for vct '${vct}'. Only https supported`);
226
+ }
227
+ let firstError;
228
+ const firstResponse = await agentContext.config.agentDependencies.fetch(vct).catch((error) => {
229
+ firstError = error;
230
+ });
231
+ let response = firstResponse;
232
+ if (!response || !response?.ok) {
233
+ const vctElements = vct.split("/");
234
+ vctElements.splice(3, 0, ".well-known/vct");
235
+ const legacyVctUrl = vctElements.join("/");
236
+ response = await agentContext.config.agentDependencies.fetch(legacyVctUrl).catch(() => void 0);
237
+ }
238
+ if (!response?.ok) {
239
+ if (!throwErrorOnFetchError) return void 0;
240
+ if (firstResponse) throw new SdJwtVcError(`Unable to resolve type metadata vct '${vct}'. Fetch returned a non-successful ${firstResponse.status} response. ${await firstResponse.text()}.`, { cause: firstError });
241
+ else throw new SdJwtVcError(`Unable to resolve type metadata vct '${vct}'. Fetch returned a non-successful response.`, { cause: firstError });
242
+ }
243
+ const typeMetadata = await response.clone().json();
244
+ if (vctIntegrity) {
245
+ if (typeof vctIntegrity !== "string") throw new SdJwtVcError(`Found 'vct#integrity' with value '${vctIntegrity}' but value was not of type 'string'.`);
246
+ IntegrityVerifier.verifyIntegrity(new Uint8Array(await response.arrayBuffer()), vctIntegrity);
247
+ }
248
+ return typeMetadata;
249
+ }
225
250
  async store(agentContext, options) {
226
251
  await this.sdJwtVcRepository.save(agentContext, options.record);
227
252
  return options.record;
@@ -1 +1 @@
1
- {"version":3,"file":"SdJwtVcService.mjs","names":["SdJwtVcService","sdJwtVc: SDJwt","returnSdJwtVc: SdJwtVc<Header, Payload>","publicJwk: PublicJwk","didUrl: string"],"sources":["../../../src/modules/sd-jwt-vc/SdJwtVcService.ts"],"sourcesContent":["import type { SDJwt } from '@sd-jwt/core'\nimport { decodeSdJwtSync } from '@sd-jwt/decode'\nimport { selectDisclosures } from '@sd-jwt/present'\nimport { SDJwtVcInstance } from '@sd-jwt/sd-jwt-vc'\nimport type { DisclosureFrame, PresentationFrame } from '@sd-jwt/types'\nimport { injectable } from 'tsyringe'\nimport { AgentContext } from '../../agent'\nimport { Hasher, JwtPayload } from '../../crypto'\nimport { CredoError } from '../../error'\nimport { X509Service } from '../../modules/x509/X509Service'\nimport type { Query, QueryOptions } from '../../storage/StorageService'\nimport type { JsonObject } from '../../types'\nimport { dateToSeconds, nowInSeconds, TypedArrayEncoder } from '../../utils'\nimport { getDomainFromUrl } from '../../utils/domain'\nimport { fetchWithTimeout } from '../../utils/fetch'\nimport { getPublicJwkFromVerificationMethod, parseDid } from '../dids'\nimport { KeyManagementApi, PublicJwk } from '../kms'\nimport { ClaimFormat } from '../vc/index'\nimport { type EncodedX509Certificate, X509Certificate, X509ModuleConfig } from '../x509'\nimport { decodeSdJwtVc, sdJwtVcHasher } from './decodeSdJwtVc'\nimport { buildDisclosureFrameForPayload } from './disclosureFrame'\nimport { SdJwtVcRecord, SdJwtVcRepository } from './repository'\nimport { SdJwtVcError } from './SdJwtVcError'\nimport type {\n SdJwtVcHeader,\n SdJwtVcIssuer,\n SdJwtVcPayload,\n SdJwtVcPresentOptions,\n SdJwtVcSignOptions,\n SdJwtVcStoreOptions,\n SdJwtVcVerifyOptions,\n} from './SdJwtVcOptions'\nimport type { SdJwtVcTypeMetadata } from './typeMetadata'\nimport {\n extractKeyFromHolderBinding,\n getSdJwtSigner,\n getSdJwtVerifier,\n parseHolderBindingFromCredential,\n resolveDidUrl,\n resolveSigningPublicJwkFromDidUrl,\n} from './utils'\n\ntype SdJwtVcConfig = SDJwtVcInstance['userConfig']\n\nexport interface SdJwtVc<\n Header extends SdJwtVcHeader = SdJwtVcHeader,\n Payload extends SdJwtVcPayload = SdJwtVcPayload,\n> {\n /**\n * claim format is convenience method added to all credential instances\n */\n claimFormat: ClaimFormat.SdJwtDc\n /**\n * encoded is convenience method added to all credential instances\n */\n encoded: string\n compact: string\n header: Header\n\n // TODO: payload type here is a lie, as it is the signed payload (so fields replaced with _sd)\n payload: Payload\n prettyClaims: Payload\n\n kbJwt?: {\n header: Record<string, unknown>\n payload: Record<string, unknown>\n }\n\n /**\n * The key id in the KMS bound to this SD-JWT VC, used for presentations.\n *\n * This will only be set on the holder side if defined on the SdJwtVcRecord\n */\n kmsKeyId?: string\n\n typeMetadata?: SdJwtVcTypeMetadata\n}\n\nexport interface VerificationResult {\n isValid: boolean\n isValidJwtPayload?: boolean\n isSignatureValid?: boolean\n isStatusValid?: boolean\n isNotBeforeValid?: boolean\n isExpiryTimeValid?: boolean\n areRequiredClaimsIncluded?: boolean\n isKeyBindingValid?: boolean\n containsExpectedKeyBinding?: boolean\n containsRequiredVcProperties?: boolean\n}\n\n/**\n * @internal\n */\n@injectable()\nexport class SdJwtVcService {\n private sdJwtVcRepository: SdJwtVcRepository\n\n public constructor(sdJwtVcRepository: SdJwtVcRepository) {\n this.sdJwtVcRepository = sdJwtVcRepository\n }\n\n public async sign<Payload extends SdJwtVcPayload>(\n agentContext: AgentContext,\n options: SdJwtVcSignOptions<Payload>\n ): Promise<SdJwtVc> {\n const { payload, disclosureFrame, hashingAlgorithm } = options\n\n // default is sha-256\n if (hashingAlgorithm && hashingAlgorithm !== 'sha-256') {\n throw new SdJwtVcError(`Unsupported hashing algorithm used: ${hashingAlgorithm}`)\n }\n\n const issuer = await this.extractKeyFromIssuer(agentContext, options.issuer, true)\n\n // holer binding is optional\n const holderBinding = options.holder ? await extractKeyFromHolderBinding(agentContext, options.holder) : undefined\n\n const header = {\n alg: issuer.alg,\n typ: options.headerType ?? 'dc+sd-jwt',\n kid: issuer.kid,\n x5c: issuer.x5c?.map((cert) => cert.toString('base64')),\n } as const\n\n const sdjwt = new SDJwtVcInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n signer: getSdJwtSigner(agentContext, issuer.publicJwk),\n hashAlg: 'sha-256',\n signAlg: issuer.alg,\n })\n\n if (!payload.vct || typeof payload.vct !== 'string') {\n throw new SdJwtVcError(\"Missing required parameter 'vct'\")\n }\n\n const compact = await sdjwt.issue(\n {\n ...payload,\n cnf: holderBinding?.cnf,\n iss: issuer.iss,\n iat: nowInSeconds(),\n vct: payload.vct,\n },\n disclosureFrame as DisclosureFrame<Payload>,\n { header }\n )\n\n const prettyClaims = (await sdjwt.getClaims(compact)) as Payload\n const a = await sdjwt.decode(compact)\n const sdjwtPayload = a.jwt?.payload as Payload | undefined\n if (!sdjwtPayload) {\n throw new SdJwtVcError('Invalid sd-jwt-vc state.')\n }\n\n return {\n compact,\n prettyClaims,\n header: header,\n payload: sdjwtPayload,\n claimFormat: ClaimFormat.SdJwtDc,\n encoded: compact,\n } satisfies SdJwtVc<typeof header, Payload>\n }\n\n public fromCompact<Header extends SdJwtVcHeader = SdJwtVcHeader, Payload extends SdJwtVcPayload = SdJwtVcPayload>(\n compactSdJwtVc: string,\n typeMetadata?: SdJwtVcTypeMetadata\n ): SdJwtVc<Header, Payload> {\n return decodeSdJwtVc(compactSdJwtVc, typeMetadata)\n }\n\n public applyDisclosuresForPayload(compactSdJwtVc: string, requestedPayload: JsonObject): SdJwtVc {\n const decoded = decodeSdJwtSync(compactSdJwtVc, Hasher.hash)\n const presentationFrame = buildDisclosureFrameForPayload(requestedPayload) ?? {}\n\n if (decoded.kbJwt) {\n throw new SdJwtVcError('Cannot apply limit disclosure on an sd-jwt with key binding jwt')\n }\n\n const requiredDisclosures = selectDisclosures(\n decoded.jwt.payload,\n // Map to sd-jwt disclosure format\n decoded.disclosures.map((d) => ({\n digest: d.digestSync({ alg: 'sha-256', hasher: Hasher.hash }),\n encoded: d.encode(),\n key: d.key,\n salt: d.salt,\n value: d.value,\n })),\n presentationFrame as { [key: string]: boolean }\n )\n const [jwt] = compactSdJwtVc.split('~')\n const disclosuresString =\n requiredDisclosures.length > 0 ? `${requiredDisclosures.map((d) => d.encoded).join('~')}~` : ''\n const sdJwt = `${jwt}~${disclosuresString}`\n const disclosedDecoded = decodeSdJwtVc(sdJwt)\n return disclosedDecoded\n }\n\n public async present<Payload extends SdJwtVcPayload = SdJwtVcPayload>(\n agentContext: AgentContext,\n { sdJwtVc, presentationFrame, verifierMetadata, additionalPayload }: SdJwtVcPresentOptions<Payload>\n ): Promise<string> {\n const sdjwt = new SDJwtVcInstance(this.getBaseSdJwtConfig(agentContext))\n const compactSdJwtVc = typeof sdJwtVc === 'string' ? sdJwtVc : sdJwtVc.compact\n const sdJwtVcInstance = await sdjwt.decode(compactSdJwtVc)\n\n const holderBinding = parseHolderBindingFromCredential(sdJwtVcInstance.jwt?.payload)\n if (!holderBinding && verifierMetadata) {\n throw new SdJwtVcError(\"Verifier metadata provided, but credential has no 'cnf' claim to create a KB-JWT from\")\n }\n\n const holder = holderBinding\n ? await extractKeyFromHolderBinding(agentContext, holderBinding, {\n forSigning: true,\n jwkKeyId: typeof sdJwtVc !== 'string' ? sdJwtVc.kmsKeyId : undefined,\n })\n : undefined\n sdjwt.config({\n kbSigner: holder ? getSdJwtSigner(agentContext, holder.publicJwk) : undefined,\n kbSignAlg: holder?.alg,\n })\n\n const compactDerivedSdJwtVc = await sdjwt.present(compactSdJwtVc, presentationFrame as PresentationFrame<Payload>, {\n kb: verifierMetadata\n ? {\n payload: {\n iat: verifierMetadata.issuedAt,\n nonce: verifierMetadata.nonce,\n aud: verifierMetadata.audience,\n ...additionalPayload,\n },\n }\n : undefined,\n })\n\n return compactDerivedSdJwtVc\n }\n\n private assertValidX5cJwtIssuer(\n agentContext: AgentContext,\n iss: string | undefined,\n leafCertificate: X509Certificate\n ) {\n // No 'iss' is allowed for X509\n if (!iss) return\n\n // If iss is present it MUST be an HTTPS url\n if (!iss.startsWith('https://') && !(iss.startsWith('http://') && agentContext.config.allowInsecureHttpUrls)) {\n throw new SdJwtVcError('The X509 certificate issuer must be a HTTPS URI.')\n }\n\n if (!leafCertificate.sanUriNames?.includes(iss) && !leafCertificate.sanDnsNames?.includes(getDomainFromUrl(iss))) {\n throw new SdJwtVcError(\n `The 'iss' claim in the payload does not match a 'SAN-URI' name and the domain extracted from the HTTPS URI does not match a 'SAN-DNS' name in the x5c certificate. Either remove the 'iss' claim or make it match with at least one SAN-URI or DNS-URI entry`\n )\n }\n }\n\n public async verify<Header extends SdJwtVcHeader = SdJwtVcHeader, Payload extends SdJwtVcPayload = SdJwtVcPayload>(\n agentContext: AgentContext,\n { compactSdJwtVc, keyBinding, requiredClaimKeys, fetchTypeMetadata, trustedCertificates, now }: SdJwtVcVerifyOptions\n ): Promise<\n | { isValid: true; sdJwtVc: SdJwtVc<Header, Payload> }\n | { isValid: false; sdJwtVc?: SdJwtVc<Header, Payload>; error: Error }\n > {\n const sdjwt = new SDJwtVcInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n // FIXME: will break if using url but no type metadata\n // https://github.com/openwallet-foundation/sd-jwt-js/issues/258\n // loadTypeMetadataFormat: false,\n })\n\n let sdJwtVc: SDJwt\n\n try {\n sdJwtVc = await sdjwt.decode(compactSdJwtVc)\n if (!sdJwtVc.jwt) throw new CredoError('Invalid sd-jwt-vc')\n } catch (error) {\n return {\n isValid: false,\n error,\n }\n }\n\n const returnSdJwtVc: SdJwtVc<Header, Payload> = {\n payload: sdJwtVc.jwt.payload as Payload,\n header: sdJwtVc.jwt.header as Header,\n compact: compactSdJwtVc,\n prettyClaims: await sdJwtVc.getClaims(sdJwtVcHasher),\n\n kbJwt: sdJwtVc.kbJwt\n ? {\n payload: sdJwtVc.kbJwt.payload as Record<string, unknown>,\n header: sdJwtVc.kbJwt.header as Record<string, unknown>,\n }\n : undefined,\n claimFormat: ClaimFormat.SdJwtDc,\n encoded: compactSdJwtVc,\n } satisfies SdJwtVc<Header, Payload>\n\n try {\n const credentialIssuer = await this.parseIssuerFromCredential(\n agentContext,\n sdJwtVc,\n returnSdJwtVc,\n trustedCertificates\n )\n const issuer = await this.extractKeyFromIssuer(agentContext, credentialIssuer)\n const holderBinding = parseHolderBindingFromCredential(sdJwtVc.jwt.payload)\n const holder = holderBinding ? await extractKeyFromHolderBinding(agentContext, holderBinding) : undefined\n\n sdjwt.config({\n verifier: getSdJwtVerifier(agentContext, issuer.publicJwk),\n kbVerifier: holder ? getSdJwtVerifier(agentContext, holder.publicJwk) : undefined,\n })\n\n try {\n await sdjwt.verify(compactSdJwtVc, {\n requiredClaimKeys: requiredClaimKeys ? [...requiredClaimKeys, 'vct'] : ['vct'],\n keyBindingNonce: keyBinding?.nonce,\n currentDate: dateToSeconds(now ?? new Date()),\n skewSeconds: 0,\n })\n } catch (error) {\n return {\n error,\n isValid: false,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n if (sdJwtVc.jwt.header?.typ !== 'vc+sd-jwt' && sdJwtVc.jwt.header?.typ !== 'dc+sd-jwt') {\n return {\n error: new SdJwtVcError(`SD-JWT VC header 'typ' must be 'dc+sd-jwt' or 'vc+sd-jwt'`),\n isValid: false,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n try {\n JwtPayload.fromJson(returnSdJwtVc.payload).validate({\n now: dateToSeconds(now ?? new Date()),\n skewTime: 0,\n })\n } catch (error) {\n return {\n error,\n isValid: false,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n // If keyBinding is present, verify the key binding\n try {\n if (keyBinding) {\n if (!sdJwtVc.kbJwt || !sdJwtVc.kbJwt.payload) {\n throw new SdJwtVcError('Keybinding is required for verification of the sd-jwt-vc')\n }\n\n // Assert `aud` and `nonce` claims\n if (sdJwtVc.kbJwt.payload.aud !== keyBinding.audience) {\n throw new SdJwtVcError('The key binding JWT does not contain the expected audience')\n }\n\n if (sdJwtVc.kbJwt.payload.nonce !== keyBinding.nonce) {\n throw new SdJwtVcError('The key binding JWT does not contain the expected nonce')\n }\n }\n } catch (error) {\n return {\n error,\n isValid: false,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n try {\n const vct = returnSdJwtVc.payload?.vct\n if (fetchTypeMetadata && typeof vct === 'string' && vct.startsWith('https://')) {\n // modify the uri based on https://www.ietf.org/archive/id/draft-ietf-oauth-sd-jwt-vc-04.html#section-6.3.1\n const vctElements = vct.split('/')\n vctElements.splice(3, 0, '.well-known/vct')\n const vctUrl = vctElements.join('/')\n\n const response = await agentContext.config.agentDependencies.fetch(vctUrl)\n if (response.ok) {\n const typeMetadata = await response.json()\n returnSdJwtVc.typeMetadata = typeMetadata as SdJwtVcTypeMetadata\n }\n }\n } catch (_error) {\n // we allow vct without type metadata for now\n }\n } catch (error) {\n return {\n isValid: false,\n error,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n return {\n isValid: true,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n public async store(agentContext: AgentContext, options: SdJwtVcStoreOptions) {\n await this.sdJwtVcRepository.save(agentContext, options.record)\n return options.record\n }\n\n public async getById(agentContext: AgentContext, id: string): Promise<SdJwtVcRecord> {\n return await this.sdJwtVcRepository.getById(agentContext, id)\n }\n\n public async getAll(agentContext: AgentContext): Promise<Array<SdJwtVcRecord>> {\n return await this.sdJwtVcRepository.getAll(agentContext)\n }\n\n public async findByQuery(\n agentContext: AgentContext,\n query: Query<SdJwtVcRecord>,\n queryOptions?: QueryOptions\n ): Promise<Array<SdJwtVcRecord>> {\n return await this.sdJwtVcRepository.findByQuery(agentContext, query, queryOptions)\n }\n\n public async deleteById(agentContext: AgentContext, id: string) {\n await this.sdJwtVcRepository.deleteById(agentContext, id)\n }\n\n public async update(agentContext: AgentContext, sdJwtVcRecord: SdJwtVcRecord) {\n await this.sdJwtVcRepository.update(agentContext, sdJwtVcRecord)\n }\n\n private async extractKeyFromIssuer(agentContext: AgentContext, issuer: SdJwtVcIssuer, forSigning = false) {\n if (issuer.method === 'did') {\n const parsedDid = parseDid(issuer.didUrl)\n if (!parsedDid.fragment) {\n throw new SdJwtVcError(\n `didUrl '${issuer.didUrl}' does not contain a '#'. Unable to derive key from did document`\n )\n }\n\n let publicJwk: PublicJwk\n if (forSigning) {\n publicJwk = await resolveSigningPublicJwkFromDidUrl(agentContext, issuer.didUrl)\n } else {\n const { verificationMethod } = await resolveDidUrl(agentContext, issuer.didUrl)\n publicJwk = getPublicJwkFromVerificationMethod(verificationMethod)\n }\n\n const supportedSignatureAlgorithms = publicJwk.supportedSignatureAlgorithms\n if (supportedSignatureAlgorithms.length === 0) {\n throw new SdJwtVcError(\n `No supported JWA signature algorithms found for key ${publicJwk.jwkTypeHumanDescription}`\n )\n }\n const alg = supportedSignatureAlgorithms[0]\n\n return {\n alg,\n publicJwk,\n iss: parsedDid.did,\n kid: `#${parsedDid.fragment}`,\n }\n }\n\n if (issuer.method === 'x5c') {\n const leafCertificate = issuer.x5c[0]\n if (!leafCertificate) {\n throw new SdJwtVcError(\"Empty 'x5c' array provided\")\n }\n\n if (forSigning && !leafCertificate.publicJwk.hasKeyId) {\n throw new SdJwtVcError(\"Expected leaf certificate in 'x5c' array to have a key id configured.\")\n }\n\n const publicJwk = leafCertificate.publicJwk\n const supportedSignatureAlgorithms = publicJwk.supportedSignatureAlgorithms\n if (supportedSignatureAlgorithms.length === 0) {\n throw new SdJwtVcError(\n `No supported JWA signature algorithms found for key ${publicJwk.jwkTypeHumanDescription}`\n )\n }\n const alg = supportedSignatureAlgorithms[0]\n\n this.assertValidX5cJwtIssuer(agentContext, issuer.issuer, leafCertificate)\n\n return {\n publicJwk,\n iss: issuer.issuer,\n x5c: issuer.x5c,\n alg,\n }\n }\n\n throw new SdJwtVcError(\"Unsupported credential issuer. Only 'did' and 'x5c' is supported at the moment.\")\n }\n\n private async parseIssuerFromCredential<Header extends SdJwtVcHeader, Payload extends SdJwtVcPayload>(\n agentContext: AgentContext,\n sdJwtVc: SDJwt<Header, Payload>,\n credoSdJwtVc: SdJwtVc<Header, Payload>,\n _trustedCertificates?: EncodedX509Certificate[]\n ): Promise<SdJwtVcIssuer> {\n const x509Config = agentContext.dependencyManager.resolve(X509ModuleConfig)\n if (!sdJwtVc.jwt?.payload) {\n throw new SdJwtVcError('Credential not exist')\n }\n\n const iss = sdJwtVc.jwt.payload.iss as string | undefined\n\n if (sdJwtVc.jwt.header?.x5c) {\n if (!Array.isArray(sdJwtVc.jwt.header.x5c)) {\n throw new SdJwtVcError('Invalid x5c header in credential. Not an array.')\n }\n if (sdJwtVc.jwt.header.x5c.length === 0) {\n throw new SdJwtVcError('Invalid x5c header in credential. Empty array.')\n }\n if (sdJwtVc.jwt.header.x5c.some((x5c) => typeof x5c !== 'string')) {\n throw new SdJwtVcError('Invalid x5c header in credential. Not an array of strings.')\n }\n\n let trustedCertificates = _trustedCertificates\n const certificateChain = sdJwtVc.jwt.header.x5c.map((cert) => X509Certificate.fromEncodedCertificate(cert))\n\n if (!trustedCertificates) {\n trustedCertificates =\n (await x509Config.getTrustedCertificatesForVerification?.(agentContext, {\n certificateChain,\n verification: {\n type: 'credential',\n credential: credoSdJwtVc,\n },\n })) ?? x509Config.trustedCertificates\n }\n\n if (!trustedCertificates) {\n throw new SdJwtVcError(\n 'No trusted certificates configured for X509 certificate chain validation. Issuer cannot be verified.'\n )\n }\n\n await X509Service.validateCertificateChain(agentContext, {\n certificateChain: sdJwtVc.jwt.header.x5c,\n trustedCertificates,\n })\n\n return {\n method: 'x5c',\n x5c: certificateChain,\n issuer: iss,\n }\n }\n\n if (iss?.startsWith('did:')) {\n // If `did` is used, we require a relative KID to be present to identify\n // the key used by issuer to sign the sd-jwt-vc\n\n if (!sdJwtVc.jwt?.header) {\n throw new SdJwtVcError('Credential does not contain a header')\n }\n\n if (!sdJwtVc.jwt.header.kid) {\n throw new SdJwtVcError('Credential does not contain a kid in the header')\n }\n\n const issuerKid = sdJwtVc.jwt.header.kid as string\n\n let didUrl: string\n if (issuerKid.startsWith('#')) {\n didUrl = `${iss}${issuerKid}`\n } else if (issuerKid.startsWith('did:')) {\n const didFromKid = parseDid(issuerKid)\n if (didFromKid.did !== iss) {\n throw new SdJwtVcError(\n `kid in header is an absolute DID URL, but the did (${didFromKid.did}) does not match with the 'iss' did (${iss})`\n )\n }\n\n didUrl = issuerKid\n } else {\n throw new SdJwtVcError(\n 'Invalid issuer kid for did. Only absolute or relative (starting with #) did urls are supported.'\n )\n }\n\n return {\n method: 'did',\n didUrl,\n }\n }\n\n throw new SdJwtVcError('Unsupported signing method for SD-JWT VC. Only did and x5c are supported at the moment.')\n }\n\n private getBaseSdJwtConfig(agentContext: AgentContext): SdJwtVcConfig {\n const kms = agentContext.resolve(KeyManagementApi)\n\n return {\n hasher: sdJwtVcHasher,\n statusListFetcher: this.getStatusListFetcher(agentContext),\n saltGenerator: (length) => TypedArrayEncoder.toBase64URL(kms.randomBytes({ length })).slice(0, length),\n }\n }\n\n private getStatusListFetcher(agentContext: AgentContext) {\n return async (uri: string) => {\n const response = await fetchWithTimeout(agentContext.config.agentDependencies.fetch, uri, {\n headers: {\n Accept: 'application/statuslist+jwt',\n },\n })\n\n if (!response.ok) {\n throw new CredoError(\n `Received invalid response with status ${\n response.status\n } when fetching status list from ${uri}. ${await response.text()}`\n )\n }\n\n return await response.text()\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SdJwtVcService.mjs","names":["SdJwtVcService","sdJwtVc: SDJwt","returnSdJwtVc: SdJwtVc<Header, Payload>","firstError: Error | undefined","publicJwk: PublicJwk","didUrl: string"],"sources":["../../../src/modules/sd-jwt-vc/SdJwtVcService.ts"],"sourcesContent":["import type { SDJwt } from '@sd-jwt/core'\nimport { decodeSdJwtSync } from '@sd-jwt/decode'\nimport { selectDisclosures } from '@sd-jwt/present'\nimport { SDJwtVcInstance } from '@sd-jwt/sd-jwt-vc'\nimport type { DisclosureFrame, PresentationFrame } from '@sd-jwt/types'\nimport { injectable } from 'tsyringe'\nimport { AgentContext } from '../../agent'\nimport { Hasher, JwtPayload } from '../../crypto'\nimport { CredoError } from '../../error'\nimport { X509Service } from '../../modules/x509/X509Service'\nimport type { Query, QueryOptions } from '../../storage/StorageService'\nimport type { JsonObject } from '../../types'\nimport { dateToSeconds, IntegrityVerifier, nowInSeconds, TypedArrayEncoder } from '../../utils'\nimport { getDomainFromUrl } from '../../utils/domain'\nimport { fetchWithTimeout } from '../../utils/fetch'\nimport { getPublicJwkFromVerificationMethod, parseDid } from '../dids'\nimport { KeyManagementApi, PublicJwk } from '../kms'\nimport { ClaimFormat } from '../vc/index'\nimport { type EncodedX509Certificate, X509Certificate, X509ModuleConfig } from '../x509'\nimport { decodeSdJwtVc, sdJwtVcHasher } from './decodeSdJwtVc'\nimport { buildDisclosureFrameForPayload } from './disclosureFrame'\nimport { SdJwtVcRecord, SdJwtVcRepository } from './repository'\nimport { SdJwtVcError } from './SdJwtVcError'\nimport type {\n SdJwtVcHeader,\n SdJwtVcIssuer,\n SdJwtVcPayload,\n SdJwtVcPresentOptions,\n SdJwtVcSignOptions,\n SdJwtVcStoreOptions,\n SdJwtVcVerifyOptions,\n} from './SdJwtVcOptions'\nimport type { SdJwtVcTypeMetadata } from './typeMetadata'\nimport {\n extractKeyFromHolderBinding,\n getSdJwtSigner,\n getSdJwtVerifier,\n parseHolderBindingFromCredential,\n resolveDidUrl,\n resolveSigningPublicJwkFromDidUrl,\n} from './utils'\n\ntype SdJwtVcConfig = SDJwtVcInstance['userConfig']\n\nexport interface SdJwtVc<\n Header extends SdJwtVcHeader = SdJwtVcHeader,\n Payload extends SdJwtVcPayload = SdJwtVcPayload,\n> {\n /**\n * claim format is convenience method added to all credential instances\n */\n claimFormat: ClaimFormat.SdJwtDc\n /**\n * encoded is convenience method added to all credential instances\n */\n encoded: string\n compact: string\n header: Header\n\n // TODO: payload type here is a lie, as it is the signed payload (so fields replaced with _sd)\n payload: Payload\n prettyClaims: Payload\n\n kbJwt?: {\n header: Record<string, unknown>\n payload: Record<string, unknown>\n }\n\n /**\n * The key id in the KMS bound to this SD-JWT VC, used for presentations.\n *\n * This will only be set on the holder side if defined on the SdJwtVcRecord\n */\n kmsKeyId?: string\n\n typeMetadata?: SdJwtVcTypeMetadata\n}\n\nexport interface VerificationResult {\n isValid: boolean\n isValidJwtPayload?: boolean\n isSignatureValid?: boolean\n isStatusValid?: boolean\n isNotBeforeValid?: boolean\n isExpiryTimeValid?: boolean\n areRequiredClaimsIncluded?: boolean\n isKeyBindingValid?: boolean\n containsExpectedKeyBinding?: boolean\n containsRequiredVcProperties?: boolean\n}\n\n/**\n * @internal\n */\n@injectable()\nexport class SdJwtVcService {\n private sdJwtVcRepository: SdJwtVcRepository\n\n public constructor(sdJwtVcRepository: SdJwtVcRepository) {\n this.sdJwtVcRepository = sdJwtVcRepository\n }\n\n public async sign<Payload extends SdJwtVcPayload>(\n agentContext: AgentContext,\n options: SdJwtVcSignOptions<Payload>\n ): Promise<SdJwtVc> {\n const { payload, disclosureFrame, hashingAlgorithm } = options\n\n // default is sha-256\n if (hashingAlgorithm && hashingAlgorithm !== 'sha-256') {\n throw new SdJwtVcError(`Unsupported hashing algorithm used: ${hashingAlgorithm}`)\n }\n\n const issuer = await this.extractKeyFromIssuer(agentContext, options.issuer, true)\n\n // holer binding is optional\n const holderBinding = options.holder ? await extractKeyFromHolderBinding(agentContext, options.holder) : undefined\n\n const header = {\n alg: issuer.alg,\n typ: options.headerType ?? 'dc+sd-jwt',\n kid: issuer.kid,\n x5c: issuer.x5c?.map((cert) => cert.toString('base64')),\n } as const\n\n const sdjwt = new SDJwtVcInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n signer: getSdJwtSigner(agentContext, issuer.publicJwk),\n hashAlg: 'sha-256',\n signAlg: issuer.alg,\n })\n\n if (!payload.vct || typeof payload.vct !== 'string') {\n throw new SdJwtVcError(\"Missing required parameter 'vct'\")\n }\n\n const compact = await sdjwt.issue(\n {\n ...payload,\n cnf: holderBinding?.cnf,\n iss: issuer.iss,\n iat: nowInSeconds(),\n vct: payload.vct,\n },\n disclosureFrame as DisclosureFrame<Payload>,\n { header }\n )\n\n const prettyClaims = (await sdjwt.getClaims(compact)) as Payload\n const a = await sdjwt.decode(compact)\n const sdjwtPayload = a.jwt?.payload as Payload | undefined\n if (!sdjwtPayload) {\n throw new SdJwtVcError('Invalid sd-jwt-vc state.')\n }\n\n return {\n compact,\n prettyClaims,\n header: header,\n payload: sdjwtPayload,\n claimFormat: ClaimFormat.SdJwtDc,\n encoded: compact,\n } satisfies SdJwtVc<typeof header, Payload>\n }\n\n public fromCompact<Header extends SdJwtVcHeader = SdJwtVcHeader, Payload extends SdJwtVcPayload = SdJwtVcPayload>(\n compactSdJwtVc: string,\n typeMetadata?: SdJwtVcTypeMetadata\n ): SdJwtVc<Header, Payload> {\n return decodeSdJwtVc(compactSdJwtVc, typeMetadata)\n }\n\n public applyDisclosuresForPayload(compactSdJwtVc: string, requestedPayload: JsonObject): SdJwtVc {\n const decoded = decodeSdJwtSync(compactSdJwtVc, Hasher.hash)\n const presentationFrame = buildDisclosureFrameForPayload(requestedPayload) ?? {}\n\n if (decoded.kbJwt) {\n throw new SdJwtVcError('Cannot apply limit disclosure on an sd-jwt with key binding jwt')\n }\n\n const requiredDisclosures = selectDisclosures(\n decoded.jwt.payload,\n // Map to sd-jwt disclosure format\n decoded.disclosures.map((d) => ({\n digest: d.digestSync({ alg: 'sha-256', hasher: Hasher.hash }),\n encoded: d.encode(),\n key: d.key,\n salt: d.salt,\n value: d.value,\n })),\n presentationFrame as { [key: string]: boolean }\n )\n const [jwt] = compactSdJwtVc.split('~')\n const disclosuresString =\n requiredDisclosures.length > 0 ? `${requiredDisclosures.map((d) => d.encoded).join('~')}~` : ''\n const sdJwt = `${jwt}~${disclosuresString}`\n const disclosedDecoded = decodeSdJwtVc(sdJwt)\n return disclosedDecoded\n }\n\n public async present<Payload extends SdJwtVcPayload = SdJwtVcPayload>(\n agentContext: AgentContext,\n { sdJwtVc, presentationFrame, verifierMetadata, additionalPayload }: SdJwtVcPresentOptions<Payload>\n ): Promise<string> {\n const sdjwt = new SDJwtVcInstance(this.getBaseSdJwtConfig(agentContext))\n const compactSdJwtVc = typeof sdJwtVc === 'string' ? sdJwtVc : sdJwtVc.compact\n const sdJwtVcInstance = await sdjwt.decode(compactSdJwtVc)\n\n const holderBinding = parseHolderBindingFromCredential(sdJwtVcInstance.jwt?.payload)\n if (!holderBinding && verifierMetadata) {\n throw new SdJwtVcError(\"Verifier metadata provided, but credential has no 'cnf' claim to create a KB-JWT from\")\n }\n\n const holder = holderBinding\n ? await extractKeyFromHolderBinding(agentContext, holderBinding, {\n forSigning: true,\n jwkKeyId: typeof sdJwtVc !== 'string' ? sdJwtVc.kmsKeyId : undefined,\n })\n : undefined\n sdjwt.config({\n kbSigner: holder ? getSdJwtSigner(agentContext, holder.publicJwk) : undefined,\n kbSignAlg: holder?.alg,\n })\n\n const compactDerivedSdJwtVc = await sdjwt.present(compactSdJwtVc, presentationFrame as PresentationFrame<Payload>, {\n kb: verifierMetadata\n ? {\n payload: {\n iat: verifierMetadata.issuedAt,\n nonce: verifierMetadata.nonce,\n aud: verifierMetadata.audience,\n ...additionalPayload,\n },\n }\n : undefined,\n })\n\n return compactDerivedSdJwtVc\n }\n\n private assertValidX5cJwtIssuer(\n agentContext: AgentContext,\n iss: string | undefined,\n leafCertificate: X509Certificate\n ) {\n // No 'iss' is allowed for X509\n if (!iss) return\n\n // If iss is present it MUST be an HTTPS url\n if (!iss.startsWith('https://') && !(iss.startsWith('http://') && agentContext.config.allowInsecureHttpUrls)) {\n throw new SdJwtVcError('The X509 certificate issuer must be a HTTPS URI.')\n }\n\n if (!leafCertificate.sanUriNames?.includes(iss) && !leafCertificate.sanDnsNames?.includes(getDomainFromUrl(iss))) {\n throw new SdJwtVcError(\n `The 'iss' claim in the payload does not match a 'SAN-URI' name and the domain extracted from the HTTPS URI does not match a 'SAN-DNS' name in the x5c certificate. Either remove the 'iss' claim or make it match with at least one SAN-URI or DNS-URI entry`\n )\n }\n }\n\n public async verify<Header extends SdJwtVcHeader = SdJwtVcHeader, Payload extends SdJwtVcPayload = SdJwtVcPayload>(\n agentContext: AgentContext,\n { compactSdJwtVc, keyBinding, requiredClaimKeys, fetchTypeMetadata, trustedCertificates, now }: SdJwtVcVerifyOptions\n ): Promise<\n | { isValid: true; sdJwtVc: SdJwtVc<Header, Payload> }\n | { isValid: false; sdJwtVc?: SdJwtVc<Header, Payload>; error: Error }\n > {\n const sdjwt = new SDJwtVcInstance(this.getBaseSdJwtConfig(agentContext))\n let sdJwtVc: SDJwt\n\n try {\n sdJwtVc = await sdjwt.decode(compactSdJwtVc)\n if (!sdJwtVc.jwt) throw new CredoError('Invalid sd-jwt-vc')\n } catch (error) {\n return {\n isValid: false,\n error,\n }\n }\n\n const returnSdJwtVc: SdJwtVc<Header, Payload> = {\n payload: sdJwtVc.jwt.payload as Payload,\n header: sdJwtVc.jwt.header as Header,\n compact: compactSdJwtVc,\n prettyClaims: await sdJwtVc.getClaims(sdJwtVcHasher),\n\n kbJwt: sdJwtVc.kbJwt\n ? {\n payload: sdJwtVc.kbJwt.payload as Record<string, unknown>,\n header: sdJwtVc.kbJwt.header as Record<string, unknown>,\n }\n : undefined,\n claimFormat: ClaimFormat.SdJwtDc,\n encoded: compactSdJwtVc,\n } satisfies SdJwtVc<Header, Payload>\n\n try {\n const credentialIssuer = await this.parseIssuerFromCredential(\n agentContext,\n sdJwtVc,\n returnSdJwtVc,\n trustedCertificates\n )\n const issuer = await this.extractKeyFromIssuer(agentContext, credentialIssuer)\n const holderBinding = parseHolderBindingFromCredential(sdJwtVc.jwt.payload)\n const holder = holderBinding ? await extractKeyFromHolderBinding(agentContext, holderBinding) : undefined\n\n sdjwt.config({\n verifier: getSdJwtVerifier(agentContext, issuer.publicJwk),\n kbVerifier: holder ? getSdJwtVerifier(agentContext, holder.publicJwk) : undefined,\n })\n\n try {\n await sdjwt.verify(compactSdJwtVc, {\n requiredClaimKeys: requiredClaimKeys ? [...requiredClaimKeys, 'vct'] : ['vct'],\n keyBindingNonce: keyBinding?.nonce,\n currentDate: dateToSeconds(now ?? new Date()),\n skewSeconds: 0,\n })\n } catch (error) {\n return {\n error,\n isValid: false,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n if (sdJwtVc.jwt.header?.typ !== 'vc+sd-jwt' && sdJwtVc.jwt.header?.typ !== 'dc+sd-jwt') {\n return {\n error: new SdJwtVcError(`SD-JWT VC header 'typ' must be 'dc+sd-jwt' or 'vc+sd-jwt'`),\n isValid: false,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n try {\n JwtPayload.fromJson(returnSdJwtVc.payload).validate({\n now: dateToSeconds(now ?? new Date()),\n skewTime: 0,\n })\n } catch (error) {\n return {\n error,\n isValid: false,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n // If keyBinding is present, verify the key binding\n try {\n if (keyBinding) {\n if (!sdJwtVc.kbJwt || !sdJwtVc.kbJwt.payload) {\n throw new SdJwtVcError('Keybinding is required for verification of the sd-jwt-vc')\n }\n\n // Assert `aud` and `nonce` claims\n if (sdJwtVc.kbJwt.payload.aud !== keyBinding.audience) {\n throw new SdJwtVcError('The key binding JWT does not contain the expected audience')\n }\n\n if (sdJwtVc.kbJwt.payload.nonce !== keyBinding.nonce) {\n throw new SdJwtVcError('The key binding JWT does not contain the expected nonce')\n }\n }\n } catch (error) {\n return {\n error,\n isValid: false,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n if (fetchTypeMetadata) {\n // We allow vct without type metadata for now (and don't fail if the retrieval fails)\n // Integrity check must pass though.\n returnSdJwtVc.typeMetadata = await this.fetchTypeMetadata(agentContext, returnSdJwtVc, {\n throwErrorOnFetchError: false,\n throwErrorOnUnsupportedVctValue: false,\n })\n }\n } catch (error) {\n return {\n isValid: false,\n error,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n return {\n isValid: true,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n public async fetchTypeMetadata(\n agentContext: AgentContext,\n sdJwtVc: SdJwtVc,\n {\n throwErrorOnFetchError = true,\n throwErrorOnUnsupportedVctValue = true,\n }: { throwErrorOnFetchError?: boolean; throwErrorOnUnsupportedVctValue?: boolean } = {}\n ) {\n const vct = sdJwtVc.payload.vct\n const vctIntegrity = sdJwtVc.payload['vct#integrity']\n if (!vct || typeof vct !== 'string' || !vct.startsWith('https://')) {\n if (!throwErrorOnUnsupportedVctValue) return undefined\n throw new SdJwtVcError(`Unable to resolve type metadata for vct '${vct}'. Only https supported`)\n }\n\n let firstError: Error | undefined\n\n // Fist try the new type metadata URL\n // We add a catch, so that if e.g. the request fails due to CORS (which throws an error\n // we will still continue trying the legacy url)\n const firstResponse = await agentContext.config.agentDependencies.fetch(vct).catch((error) => {\n firstError = error\n return undefined\n })\n let response = firstResponse\n\n // If the response is not ok, try the legacy URL (will be removed in 0.7)\n if (!response || !response?.ok) {\n // modify the uri based on https://www.ietf.org/archive/id/draft-ietf-oauth-sd-jwt-vc-04.html#section-6.3.1\n const vctElements = vct.split('/')\n vctElements.splice(3, 0, '.well-known/vct')\n const legacyVctUrl = vctElements.join('/')\n\n response = await agentContext.config.agentDependencies.fetch(legacyVctUrl).catch(() => undefined)\n }\n\n if (!response?.ok) {\n if (!throwErrorOnFetchError) return undefined\n\n if (firstResponse) {\n throw new SdJwtVcError(\n `Unable to resolve type metadata vct '${vct}'. Fetch returned a non-successful ${firstResponse.status} response. ${await firstResponse.text()}.`,\n { cause: firstError }\n )\n } else {\n throw new SdJwtVcError(\n `Unable to resolve type metadata vct '${vct}'. Fetch returned a non-successful response.`,\n { cause: firstError }\n )\n }\n }\n\n const typeMetadata = (await response.clone().json()) as SdJwtVcTypeMetadata\n if (vctIntegrity) {\n if (typeof vctIntegrity !== 'string') {\n throw new SdJwtVcError(`Found 'vct#integrity' with value '${vctIntegrity}' but value was not of type 'string'.`)\n }\n\n IntegrityVerifier.verifyIntegrity(new Uint8Array(await response.arrayBuffer()), vctIntegrity)\n }\n\n return typeMetadata\n }\n\n public async store(agentContext: AgentContext, options: SdJwtVcStoreOptions) {\n await this.sdJwtVcRepository.save(agentContext, options.record)\n return options.record\n }\n\n public async getById(agentContext: AgentContext, id: string): Promise<SdJwtVcRecord> {\n return await this.sdJwtVcRepository.getById(agentContext, id)\n }\n\n public async getAll(agentContext: AgentContext): Promise<Array<SdJwtVcRecord>> {\n return await this.sdJwtVcRepository.getAll(agentContext)\n }\n\n public async findByQuery(\n agentContext: AgentContext,\n query: Query<SdJwtVcRecord>,\n queryOptions?: QueryOptions\n ): Promise<Array<SdJwtVcRecord>> {\n return await this.sdJwtVcRepository.findByQuery(agentContext, query, queryOptions)\n }\n\n public async deleteById(agentContext: AgentContext, id: string) {\n await this.sdJwtVcRepository.deleteById(agentContext, id)\n }\n\n public async update(agentContext: AgentContext, sdJwtVcRecord: SdJwtVcRecord) {\n await this.sdJwtVcRepository.update(agentContext, sdJwtVcRecord)\n }\n\n private async extractKeyFromIssuer(agentContext: AgentContext, issuer: SdJwtVcIssuer, forSigning = false) {\n if (issuer.method === 'did') {\n const parsedDid = parseDid(issuer.didUrl)\n if (!parsedDid.fragment) {\n throw new SdJwtVcError(\n `didUrl '${issuer.didUrl}' does not contain a '#'. Unable to derive key from did document`\n )\n }\n\n let publicJwk: PublicJwk\n if (forSigning) {\n publicJwk = await resolveSigningPublicJwkFromDidUrl(agentContext, issuer.didUrl)\n } else {\n const { verificationMethod } = await resolveDidUrl(agentContext, issuer.didUrl)\n publicJwk = getPublicJwkFromVerificationMethod(verificationMethod)\n }\n\n const supportedSignatureAlgorithms = publicJwk.supportedSignatureAlgorithms\n if (supportedSignatureAlgorithms.length === 0) {\n throw new SdJwtVcError(\n `No supported JWA signature algorithms found for key ${publicJwk.jwkTypeHumanDescription}`\n )\n }\n const alg = supportedSignatureAlgorithms[0]\n\n return {\n alg,\n publicJwk,\n iss: parsedDid.did,\n kid: `#${parsedDid.fragment}`,\n }\n }\n\n if (issuer.method === 'x5c') {\n const leafCertificate = issuer.x5c[0]\n if (!leafCertificate) {\n throw new SdJwtVcError(\"Empty 'x5c' array provided\")\n }\n\n if (forSigning && !leafCertificate.publicJwk.hasKeyId) {\n throw new SdJwtVcError(\"Expected leaf certificate in 'x5c' array to have a key id configured.\")\n }\n\n const publicJwk = leafCertificate.publicJwk\n const supportedSignatureAlgorithms = publicJwk.supportedSignatureAlgorithms\n if (supportedSignatureAlgorithms.length === 0) {\n throw new SdJwtVcError(\n `No supported JWA signature algorithms found for key ${publicJwk.jwkTypeHumanDescription}`\n )\n }\n const alg = supportedSignatureAlgorithms[0]\n\n this.assertValidX5cJwtIssuer(agentContext, issuer.issuer, leafCertificate)\n\n return {\n publicJwk,\n iss: issuer.issuer,\n x5c: issuer.x5c,\n alg,\n }\n }\n\n throw new SdJwtVcError(\"Unsupported credential issuer. Only 'did' and 'x5c' is supported at the moment.\")\n }\n\n private async parseIssuerFromCredential<Header extends SdJwtVcHeader, Payload extends SdJwtVcPayload>(\n agentContext: AgentContext,\n sdJwtVc: SDJwt<Header, Payload>,\n credoSdJwtVc: SdJwtVc<Header, Payload>,\n _trustedCertificates?: EncodedX509Certificate[]\n ): Promise<SdJwtVcIssuer> {\n const x509Config = agentContext.dependencyManager.resolve(X509ModuleConfig)\n if (!sdJwtVc.jwt?.payload) {\n throw new SdJwtVcError('Credential not exist')\n }\n\n const iss = sdJwtVc.jwt.payload.iss as string | undefined\n\n if (sdJwtVc.jwt.header?.x5c) {\n if (!Array.isArray(sdJwtVc.jwt.header.x5c)) {\n throw new SdJwtVcError('Invalid x5c header in credential. Not an array.')\n }\n if (sdJwtVc.jwt.header.x5c.length === 0) {\n throw new SdJwtVcError('Invalid x5c header in credential. Empty array.')\n }\n if (sdJwtVc.jwt.header.x5c.some((x5c) => typeof x5c !== 'string')) {\n throw new SdJwtVcError('Invalid x5c header in credential. Not an array of strings.')\n }\n\n let trustedCertificates = _trustedCertificates\n const certificateChain = sdJwtVc.jwt.header.x5c.map((cert) => X509Certificate.fromEncodedCertificate(cert))\n\n if (!trustedCertificates) {\n trustedCertificates =\n (await x509Config.getTrustedCertificatesForVerification?.(agentContext, {\n certificateChain,\n verification: {\n type: 'credential',\n credential: credoSdJwtVc,\n },\n })) ?? x509Config.trustedCertificates\n }\n\n if (!trustedCertificates) {\n throw new SdJwtVcError(\n 'No trusted certificates configured for X509 certificate chain validation. Issuer cannot be verified.'\n )\n }\n\n await X509Service.validateCertificateChain(agentContext, {\n certificateChain: sdJwtVc.jwt.header.x5c,\n trustedCertificates,\n })\n\n return {\n method: 'x5c',\n x5c: certificateChain,\n issuer: iss,\n }\n }\n\n if (iss?.startsWith('did:')) {\n // If `did` is used, we require a relative KID to be present to identify\n // the key used by issuer to sign the sd-jwt-vc\n\n if (!sdJwtVc.jwt?.header) {\n throw new SdJwtVcError('Credential does not contain a header')\n }\n\n if (!sdJwtVc.jwt.header.kid) {\n throw new SdJwtVcError('Credential does not contain a kid in the header')\n }\n\n const issuerKid = sdJwtVc.jwt.header.kid as string\n\n let didUrl: string\n if (issuerKid.startsWith('#')) {\n didUrl = `${iss}${issuerKid}`\n } else if (issuerKid.startsWith('did:')) {\n const didFromKid = parseDid(issuerKid)\n if (didFromKid.did !== iss) {\n throw new SdJwtVcError(\n `kid in header is an absolute DID URL, but the did (${didFromKid.did}) does not match with the 'iss' did (${iss})`\n )\n }\n\n didUrl = issuerKid\n } else {\n throw new SdJwtVcError(\n 'Invalid issuer kid for did. Only absolute or relative (starting with #) did urls are supported.'\n )\n }\n\n return {\n method: 'did',\n didUrl,\n }\n }\n\n throw new SdJwtVcError('Unsupported signing method for SD-JWT VC. Only did and x5c are supported at the moment.')\n }\n\n private getBaseSdJwtConfig(agentContext: AgentContext): SdJwtVcConfig {\n const kms = agentContext.resolve(KeyManagementApi)\n\n return {\n hasher: sdJwtVcHasher,\n statusListFetcher: this.getStatusListFetcher(agentContext),\n saltGenerator: (length) => TypedArrayEncoder.toBase64URL(kms.randomBytes({ length })).slice(0, length),\n }\n }\n\n private getStatusListFetcher(agentContext: AgentContext) {\n return async (uri: string) => {\n const response = await fetchWithTimeout(agentContext.config.agentDependencies.fetch, uri, {\n headers: {\n Accept: 'application/statuslist+jwt',\n },\n })\n\n if (!response.ok) {\n throw new CredoError(\n `Received invalid response with status ${\n response.status\n } when fetching status list from ${uri}. ${await response.text()}`\n )\n }\n\n return await response.text()\n }\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
 
2
2
 
3
- import { JsonTransformer } from "../../../utils/JsonTransformer.mjs";
4
3
  import { Hasher } from "../../../crypto/hashes/Hasher.mjs";
4
+ import { JsonTransformer } from "../../../utils/JsonTransformer.mjs";
5
5
  import "../../../utils/index.mjs";
6
6
  import { BaseRecord } from "../../../storage/BaseRecord.mjs";
7
7
  import { uuid } from "../../../utils/uuid.mjs";
@@ -62,9 +62,6 @@ interface SdJwtVcTypeMetadata {
62
62
  'extends#integrity'?: string;
63
63
  display?: SdJwtVcTypeMetadataDisplay[];
64
64
  claims?: SdJwtVcTypeMetadataClaim[];
65
- schema?: object;
66
- schema_uri?: string;
67
- 'schema_uri#integrity'?: string;
68
65
  }
69
66
  //#endregion
70
67
  export { SdJwtVcTypeMetadata, SdJwtVcTypeMetadataClaim, SdJwtVcTypeMetadataDisplay, SdJwtVcTypeMetadataRenderingMethodSimple, SdJwtVcTypeMetadataRenderingMethodSvgTemplate };
@@ -1 +1 @@
1
- {"version":3,"file":"jsonld.d.mts","names":[],"sources":["../../../../../src/modules/vc/data-integrity/libraries/jsonld.ts"],"sourcesContent":[],"mappings":";UAIiB,MAAA;;;EAAA,KAAA,CAAA,QAAM,EAAA,GAAA,EAAA,cAAA,EAAA,GAAA,EAAA,OAAA,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA;EAiBN,QAAA,CAAA,QAAA,EAAA,GAAA,EAAoB,OAGzB,CAHyB,EAAA,GAGzB,CAAA,EAAA,GAAM;EAGN,MAAA,CAAA,QAAA,EAAc,GAAA,EAAA,OAA4B,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA;;;;UANrC,oBAAA;;;YAGL;;KAGA,cAAA,oBAAkC,QAAQ"}
1
+ {"version":3,"file":"jsonld.d.mts","names":[],"sources":["../../../../../src/modules/vc/data-integrity/libraries/jsonld.ts"],"sourcesContent":[],"mappings":";UAIiB,MAAA;;;EAAA,KAAA,CAAA,QAAM,EAAA,GAAA,EAAA,cAAA,EAAA,GAAA,EAAA,OAAA,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA;EAiBN,QAAA,CAAA,QAAA,EAAA,GAAA,EAAoB,OAGzB,CAHyB,EAGzB,GAAA,CAAA,EAAA,GAAM;EAGN,MAAA,CAAA,QAAA,EAAc,GAAA,EAAA,OAA4B,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA;;;;UANrC,oBAAA;;;YAGL;;KAGA,cAAA,oBAAkC,QAAQ"}
@@ -0,0 +1,118 @@
1
+
2
+
3
+ import { CredoError } from "../error/CredoError.mjs";
4
+ import "../error/index.mjs";
5
+ import { TypedArrayEncoder } from "./TypedArrayEncoder.mjs";
6
+ import { Hasher } from "../crypto/hashes/Hasher.mjs";
7
+
8
+ //#region src/utils/IntegrityVerifier.ts
9
+ /**
10
+ * Verifies Subresource Integrity (SRI) metadata according to W3C specification.
11
+ *
12
+ * This class implements the verification logic for integrity metadata strings
13
+ * as defined in the W3C Subresource Integrity specification.
14
+ *
15
+ * @see https://www.w3.org/TR/SRI/
16
+ */
17
+ var IntegrityVerifier = class IntegrityVerifier {
18
+ /**
19
+ * Verifies the integrity of raw data against provided integrity metadata.
20
+ *
21
+ * @param data - The data to verify
22
+ * @param integrityMetadata - The integrity metadata string (e.g., "sha256-...")
23
+ * @throws {CredoError} if verification fails
24
+ */
25
+ static verifyIntegrity(data, integrityMetadata) {
26
+ const parsedMetadata = IntegrityVerifier.parseIntegrityMetadata(integrityMetadata);
27
+ if (parsedMetadata.length === 0) throw new CredoError(`Integrity check failed. Parsed integrity metadata is empty.`);
28
+ const strongestMetadata = IntegrityVerifier.getStrongestMetadata(parsedMetadata);
29
+ for (const metadata of strongestMetadata) if (IntegrityVerifier.applyAlgorithmToBytes(data, metadata.alg) === metadata.val) return;
30
+ throw new CredoError(`Integrity check failed. None of the provided hashes match the computed hash for the response.`);
31
+ }
32
+ /**
33
+ * Parses integrity metadata string into structured format.
34
+ *
35
+ * @param metadata - The integrity metadata string
36
+ * @returns Array of parsed metadata objects
37
+ */
38
+ static parseIntegrityMetadata(metadata) {
39
+ const result = [];
40
+ const validAlgorithms = [
41
+ "sha256",
42
+ "sha384",
43
+ "sha512"
44
+ ];
45
+ const items = metadata.trim().split(/\s+/);
46
+ for (const item of items) {
47
+ if (!item) continue;
48
+ const [algorithmExpression] = item.split("?");
49
+ const parts = algorithmExpression.split("-");
50
+ if (parts.length < 2) continue;
51
+ const algorithm = parts[0].toLowerCase();
52
+ const base64Value = parts.slice(1).join("-");
53
+ if (validAlgorithms.includes(algorithm)) result.push({
54
+ alg: algorithm,
55
+ val: base64Value
56
+ });
57
+ }
58
+ return result;
59
+ }
60
+ /**
61
+ * Returns the metadata for the strongest algorithm(s) in the set.
62
+ *
63
+ * @param metadataSet - Array of parsed metadata
64
+ * @returns Array containing only the strongest algorithm's metadata
65
+ */
66
+ static getStrongestMetadata(metadataSet) {
67
+ if (metadataSet.length === 0) return [];
68
+ const algorithmPriority = {
69
+ sha256: 0,
70
+ sha384: 1,
71
+ sha512: 2
72
+ };
73
+ let strongest = null;
74
+ const result = [];
75
+ for (const item of metadataSet) {
76
+ if (!strongest) {
77
+ strongest = item;
78
+ result.push(item);
79
+ continue;
80
+ }
81
+ const currentIndex = algorithmPriority[strongest.alg];
82
+ const newIndex = algorithmPriority[item.alg];
83
+ if (newIndex > currentIndex) {
84
+ strongest = item;
85
+ result.length = 0;
86
+ result.push(item);
87
+ } else if (newIndex === currentIndex) result.push(item);
88
+ }
89
+ return result;
90
+ }
91
+ /**
92
+ * Applies the specified hash algorithm to the given bytes.
93
+ *
94
+ * @param bytes - The bytes to hash
95
+ * @param algorithm - The hash algorithm name
96
+ * @returns Base64-encoded hash value
97
+ */
98
+ static applyAlgorithmToBytes(bytes, algorithm) {
99
+ let hashResult;
100
+ switch (algorithm) {
101
+ case "sha256":
102
+ hashResult = Hasher.hash(bytes, "sha-256");
103
+ break;
104
+ case "sha384":
105
+ hashResult = Hasher.hash(bytes, "sha-384");
106
+ break;
107
+ case "sha512":
108
+ hashResult = Hasher.hash(bytes, "sha-512");
109
+ break;
110
+ default: throw new CredoError(`Unsupported hash algorithm: ${algorithm}`);
111
+ }
112
+ return TypedArrayEncoder.toBase64(hashResult);
113
+ }
114
+ };
115
+
116
+ //#endregion
117
+ export { IntegrityVerifier };
118
+ //# sourceMappingURL=IntegrityVerifier.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntegrityVerifier.mjs","names":["result: Array<{ alg: string; val: string }>","algorithmPriority: Record<string, number>","strongest: { alg: string; val: string } | null","hashResult: Uint8Array"],"sources":["../../src/utils/IntegrityVerifier.ts"],"sourcesContent":["import { Hasher } from '../crypto/hashes/Hasher'\nimport { CredoError } from '../error'\nimport { TypedArrayEncoder } from './TypedArrayEncoder'\n\n/**\n * Verifies Subresource Integrity (SRI) metadata according to W3C specification.\n *\n * This class implements the verification logic for integrity metadata strings\n * as defined in the W3C Subresource Integrity specification.\n *\n * @see https://www.w3.org/TR/SRI/\n */\n// biome-ignore lint/complexity/noStaticOnlyClass: no explanation\nexport class IntegrityVerifier {\n /**\n * Verifies the integrity of raw data against provided integrity metadata.\n *\n * @param data - The data to verify\n * @param integrityMetadata - The integrity metadata string (e.g., \"sha256-...\")\n * @throws {CredoError} if verification fails\n */\n public static verifyIntegrity(data: Uint8Array, integrityMetadata: string): void {\n const parsedMetadata = IntegrityVerifier.parseIntegrityMetadata(integrityMetadata)\n\n // If metadata is empty, no verification is required\n if (parsedMetadata.length === 0) {\n throw new CredoError(`Integrity check failed. Parsed integrity metadata is empty.`)\n }\n\n // Get the strongest algorithm's metadata\n const strongestMetadata = IntegrityVerifier.getStrongestMetadata(parsedMetadata)\n\n // Try to match any of the strongest hashes\n for (const metadata of strongestMetadata) {\n const actualValue = IntegrityVerifier.applyAlgorithmToBytes(data, metadata.alg)\n if (actualValue === metadata.val) {\n return\n }\n }\n\n throw new CredoError(\n `Integrity check failed. None of the provided hashes match the computed hash for the response.`\n )\n }\n\n /**\n * Parses integrity metadata string into structured format.\n *\n * @param metadata - The integrity metadata string\n * @returns Array of parsed metadata objects\n */\n private static parseIntegrityMetadata(metadata: string): Array<{ alg: string; val: string }> {\n const result: Array<{ alg: string; val: string }> = []\n const validAlgorithms = ['sha256', 'sha384', 'sha512']\n\n // Split by whitespace\n const items = metadata.trim().split(/\\s+/)\n\n for (const item of items) {\n if (!item) continue\n\n // Remove options (anything after '?')\n const [algorithmExpression] = item.split('?')\n\n // Split algorithm and base64 value\n const parts = algorithmExpression.split('-')\n if (parts.length < 2) continue\n\n const algorithm = parts[0].toLowerCase()\n const base64Value = parts.slice(1).join('-') // Rejoin in case base64 contains hyphens\n\n // Only include supported algorithms\n if (validAlgorithms.includes(algorithm)) {\n result.push({ alg: algorithm, val: base64Value })\n }\n }\n\n return result\n }\n\n /**\n * Returns the metadata for the strongest algorithm(s) in the set.\n *\n * @param metadataSet - Array of parsed metadata\n * @returns Array containing only the strongest algorithm's metadata\n */\n private static getStrongestMetadata(\n metadataSet: Array<{ alg: string; val: string }>\n ): Array<{ alg: string; val: string }> {\n if (metadataSet.length === 0) {\n return []\n }\n\n // Algorithm priority (higher = stronger)\n const algorithmPriority: Record<string, number> = {\n sha256: 0,\n sha384: 1,\n sha512: 2,\n }\n\n let strongest: { alg: string; val: string } | null = null\n const result: Array<{ alg: string; val: string }> = []\n\n for (const item of metadataSet) {\n if (!strongest) {\n strongest = item\n result.push(item)\n continue\n }\n\n const currentIndex = algorithmPriority[strongest.alg]\n const newIndex = algorithmPriority[item.alg]\n\n if (newIndex > currentIndex) {\n // Found a stronger algorithm, replace all\n strongest = item\n result.length = 0\n result.push(item)\n } else if (newIndex === currentIndex) {\n // Same strength, add to results\n result.push(item)\n }\n // If newIndex < currentIndex, ignore (weaker algorithm)\n }\n\n return result\n }\n\n /**\n * Applies the specified hash algorithm to the given bytes.\n *\n * @param bytes - The bytes to hash\n * @param algorithm - The hash algorithm name\n * @returns Base64-encoded hash value\n */\n private static applyAlgorithmToBytes(bytes: Uint8Array, algorithm: string): string {\n let hashResult: Uint8Array\n\n switch (algorithm) {\n case 'sha256':\n hashResult = Hasher.hash(bytes, 'sha-256')\n break\n case 'sha384':\n hashResult = Hasher.hash(bytes, 'sha-384')\n break\n case 'sha512':\n hashResult = Hasher.hash(bytes, 'sha-512')\n break\n default:\n throw new CredoError(`Unsupported hash algorithm: ${algorithm}`)\n }\n\n return TypedArrayEncoder.toBase64(hashResult)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAaA,IAAa,oBAAb,MAAa,kBAAkB;;;;;;;;CAQ7B,OAAc,gBAAgB,MAAkB,mBAAiC;EAC/E,MAAM,iBAAiB,kBAAkB,uBAAuB,kBAAkB;AAGlF,MAAI,eAAe,WAAW,EAC5B,OAAM,IAAI,WAAW,8DAA8D;EAIrF,MAAM,oBAAoB,kBAAkB,qBAAqB,eAAe;AAGhF,OAAK,MAAM,YAAY,kBAErB,KADoB,kBAAkB,sBAAsB,MAAM,SAAS,IAAI,KAC3D,SAAS,IAC3B;AAIJ,QAAM,IAAI,WACR,gGACD;;;;;;;;CASH,OAAe,uBAAuB,UAAuD;EAC3F,MAAMA,SAA8C,EAAE;EACtD,MAAM,kBAAkB;GAAC;GAAU;GAAU;GAAS;EAGtD,MAAM,QAAQ,SAAS,MAAM,CAAC,MAAM,MAAM;AAE1C,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,CAAC,KAAM;GAGX,MAAM,CAAC,uBAAuB,KAAK,MAAM,IAAI;GAG7C,MAAM,QAAQ,oBAAoB,MAAM,IAAI;AAC5C,OAAI,MAAM,SAAS,EAAG;GAEtB,MAAM,YAAY,MAAM,GAAG,aAAa;GACxC,MAAM,cAAc,MAAM,MAAM,EAAE,CAAC,KAAK,IAAI;AAG5C,OAAI,gBAAgB,SAAS,UAAU,CACrC,QAAO,KAAK;IAAE,KAAK;IAAW,KAAK;IAAa,CAAC;;AAIrD,SAAO;;;;;;;;CAST,OAAe,qBACb,aACqC;AACrC,MAAI,YAAY,WAAW,EACzB,QAAO,EAAE;EAIX,MAAMC,oBAA4C;GAChD,QAAQ;GACR,QAAQ;GACR,QAAQ;GACT;EAED,IAAIC,YAAiD;EACrD,MAAMF,SAA8C,EAAE;AAEtD,OAAK,MAAM,QAAQ,aAAa;AAC9B,OAAI,CAAC,WAAW;AACd,gBAAY;AACZ,WAAO,KAAK,KAAK;AACjB;;GAGF,MAAM,eAAe,kBAAkB,UAAU;GACjD,MAAM,WAAW,kBAAkB,KAAK;AAExC,OAAI,WAAW,cAAc;AAE3B,gBAAY;AACZ,WAAO,SAAS;AAChB,WAAO,KAAK,KAAK;cACR,aAAa,aAEtB,QAAO,KAAK,KAAK;;AAKrB,SAAO;;;;;;;;;CAUT,OAAe,sBAAsB,OAAmB,WAA2B;EACjF,IAAIG;AAEJ,UAAQ,WAAR;GACE,KAAK;AACH,iBAAa,OAAO,KAAK,OAAO,UAAU;AAC1C;GACF,KAAK;AACH,iBAAa,OAAO,KAAK,OAAO,UAAU;AAC1C;GACF,KAAK;AACH,iBAAa,OAAO,KAAK,OAAO,UAAU;AAC1C;GACF,QACE,OAAM,IAAI,WAAW,+BAA+B,YAAY;;AAGpE,SAAO,kBAAkB,SAAS,WAAW"}
@@ -6,6 +6,7 @@ import { areObjectsEqual } from "./objectEquality.mjs";
6
6
  import { deepEquality, equalsIgnoreOrder, equalsWithOrder } from "./deepEquality.mjs";
7
7
  import { TypedArrayEncoder } from "./TypedArrayEncoder.mjs";
8
8
  import { indyDidFromPublicKeyBase58, isDid } from "./did.mjs";
9
+ import { IntegrityVerifier } from "./IntegrityVerifier.mjs";
9
10
  import { JsonEncoder } from "./JsonEncoder.mjs";
10
11
  import { MessageValidator } from "./MessageValidator.mjs";
11
12
  import { JsonTransformer } from "./JsonTransformer.mjs";
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  ".": "./build/index.mjs",
5
5
  "./package.json": "./package.json"
6
6
  },
7
- "version": "0.6.2-alpha-20251210145840",
7
+ "version": "0.6.2-alpha-20251211115250",
8
8
  "files": [
9
9
  "build"
10
10
  ],