@credo-ts/core 0.6.2-alpha-20251210145840 → 0.6.2-alpha-20251211122719
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 +4 -4
- package/build/modules/sd-jwt-vc/SdJwtVcApi.d.mts +13 -0
- package/build/modules/sd-jwt-vc/SdJwtVcApi.d.mts.map +1 -1
- package/build/modules/sd-jwt-vc/SdJwtVcApi.mjs +12 -0
- package/build/modules/sd-jwt-vc/SdJwtVcApi.mjs.map +1 -1
- package/build/modules/sd-jwt-vc/SdJwtVcService.d.mts +12 -1
- package/build/modules/sd-jwt-vc/SdJwtVcService.d.mts.map +1 -1
- package/build/modules/sd-jwt-vc/SdJwtVcService.mjs +47 -19
- package/build/modules/sd-jwt-vc/SdJwtVcService.mjs.map +1 -1
- package/build/modules/sd-jwt-vc/decodeSdJwtVc.mjs +2 -0
- package/build/modules/sd-jwt-vc/decodeSdJwtVc.mjs.map +1 -1
- package/build/modules/sd-jwt-vc/repository/SdJwtVcRecord.mjs +1 -1
- package/build/modules/sd-jwt-vc/typeMetadata.d.mts +0 -3
- package/build/utils/IntegrityVerifier.mjs +118 -0
- package/build/utils/IntegrityVerifier.mjs.map +1 -0
- package/build/utils/index.mjs +1 -0
- package/package.json +1 -1
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":"
|
|
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":";;;;;;;;;;;
|
|
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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Query, QueryOptions } from "../../storage/StorageService.mjs";
|
|
2
2
|
import { JsonObject } from "../../types.mjs";
|
|
3
3
|
import { ClaimFormat } from "../vc/models/ClaimFormat.mjs";
|
|
4
|
-
import { SdJwtVcHeader, SdJwtVcPayload, SdJwtVcPresentOptions, SdJwtVcSignOptions, SdJwtVcStoreOptions, SdJwtVcVerifyOptions } from "./SdJwtVcOptions.mjs";
|
|
4
|
+
import { SdJwtVcHeader, SdJwtVcHolderBinding, SdJwtVcPayload, SdJwtVcPresentOptions, SdJwtVcSignOptions, SdJwtVcStoreOptions, SdJwtVcVerifyOptions } from "./SdJwtVcOptions.mjs";
|
|
5
5
|
import { SdJwtVcTypeMetadata } from "./typeMetadata.mjs";
|
|
6
6
|
import { SdJwtVcRecord } from "./repository/SdJwtVcRecord.mjs";
|
|
7
7
|
import { SdJwtVcRepository } from "./repository/SdJwtVcRepository.mjs";
|
|
@@ -22,6 +22,10 @@ interface SdJwtVc<Header extends SdJwtVcHeader = SdJwtVcHeader, Payload extends
|
|
|
22
22
|
encoded: string;
|
|
23
23
|
compact: string;
|
|
24
24
|
header: Header;
|
|
25
|
+
/**
|
|
26
|
+
* The holder of the credential
|
|
27
|
+
*/
|
|
28
|
+
holder: SdJwtVcHolderBinding | undefined;
|
|
25
29
|
payload: Payload;
|
|
26
30
|
prettyClaims: Payload;
|
|
27
31
|
kbJwt?: {
|
|
@@ -79,6 +83,13 @@ declare class SdJwtVcService {
|
|
|
79
83
|
sdJwtVc?: SdJwtVc<Header, Payload>;
|
|
80
84
|
error: Error;
|
|
81
85
|
}>;
|
|
86
|
+
fetchTypeMetadata(agentContext: AgentContext, sdJwtVc: SdJwtVc, {
|
|
87
|
+
throwErrorOnFetchError,
|
|
88
|
+
throwErrorOnUnsupportedVctValue
|
|
89
|
+
}?: {
|
|
90
|
+
throwErrorOnFetchError?: boolean;
|
|
91
|
+
throwErrorOnUnsupportedVctValue?: boolean;
|
|
92
|
+
}): Promise<SdJwtVcTypeMetadata | undefined>;
|
|
82
93
|
store(agentContext: AgentContext, options: SdJwtVcStoreOptions): Promise<SdJwtVcRecord>;
|
|
83
94
|
getById(agentContext: AgentContext, id: string): Promise<SdJwtVcRecord>;
|
|
84
95
|
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":";;;;;;;;;;;;;
|
|
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";
|
|
@@ -52,28 +53,29 @@ let SdJwtVcService = class SdJwtVcService$1 {
|
|
|
52
53
|
kid: issuer.kid,
|
|
53
54
|
x5c: issuer.x5c?.map((cert) => cert.toString("base64"))
|
|
54
55
|
};
|
|
55
|
-
const
|
|
56
|
+
const sdJwt = new SDJwtVcInstance({
|
|
56
57
|
...this.getBaseSdJwtConfig(agentContext),
|
|
57
58
|
signer: getSdJwtSigner(agentContext, issuer.publicJwk),
|
|
58
59
|
hashAlg: "sha-256",
|
|
59
60
|
signAlg: issuer.alg
|
|
60
61
|
});
|
|
61
62
|
if (!payload.vct || typeof payload.vct !== "string") throw new SdJwtVcError("Missing required parameter 'vct'");
|
|
62
|
-
const compact = await
|
|
63
|
+
const compact = await sdJwt.issue({
|
|
63
64
|
...payload,
|
|
64
65
|
cnf: holderBinding?.cnf,
|
|
65
66
|
iss: issuer.iss,
|
|
66
67
|
iat: nowInSeconds(),
|
|
67
68
|
vct: payload.vct
|
|
68
69
|
}, disclosureFrame, { header });
|
|
69
|
-
const prettyClaims = await
|
|
70
|
-
const
|
|
71
|
-
if (!
|
|
70
|
+
const prettyClaims = await sdJwt.getClaims(compact);
|
|
71
|
+
const sdJwtPayload = (await sdJwt.decode(compact)).jwt?.payload;
|
|
72
|
+
if (!sdJwtPayload) throw new SdJwtVcError("Invalid sd-jwt-vc state.");
|
|
72
73
|
return {
|
|
73
74
|
compact,
|
|
74
75
|
prettyClaims,
|
|
75
76
|
header,
|
|
76
|
-
|
|
77
|
+
holder: options.holder,
|
|
78
|
+
payload: sdJwtPayload,
|
|
77
79
|
claimFormat: ClaimFormat.SdJwtDc,
|
|
78
80
|
encoded: compact
|
|
79
81
|
};
|
|
@@ -124,11 +126,13 @@ let SdJwtVcService = class SdJwtVcService$1 {
|
|
|
124
126
|
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
127
|
}
|
|
126
128
|
async verify(agentContext, { compactSdJwtVc, keyBinding, requiredClaimKeys, fetchTypeMetadata, trustedCertificates, now }) {
|
|
127
|
-
const sdjwt = new SDJwtVcInstance(
|
|
129
|
+
const sdjwt = new SDJwtVcInstance(this.getBaseSdJwtConfig(agentContext));
|
|
128
130
|
let sdJwtVc;
|
|
131
|
+
let holderBinding;
|
|
129
132
|
try {
|
|
130
133
|
sdJwtVc = await sdjwt.decode(compactSdJwtVc);
|
|
131
134
|
if (!sdJwtVc.jwt) throw new CredoError("Invalid sd-jwt-vc");
|
|
135
|
+
holderBinding = parseHolderBindingFromCredential(sdJwtVc.jwt.payload) ?? void 0;
|
|
132
136
|
} catch (error) {
|
|
133
137
|
return {
|
|
134
138
|
isValid: false,
|
|
@@ -140,6 +144,7 @@ let SdJwtVcService = class SdJwtVcService$1 {
|
|
|
140
144
|
header: sdJwtVc.jwt.header,
|
|
141
145
|
compact: compactSdJwtVc,
|
|
142
146
|
prettyClaims: await sdJwtVc.getClaims(sdJwtVcHasher),
|
|
147
|
+
holder: holderBinding,
|
|
143
148
|
kbJwt: sdJwtVc.kbJwt ? {
|
|
144
149
|
payload: sdJwtVc.kbJwt.payload,
|
|
145
150
|
header: sdJwtVc.kbJwt.header
|
|
@@ -150,8 +155,7 @@ let SdJwtVcService = class SdJwtVcService$1 {
|
|
|
150
155
|
try {
|
|
151
156
|
const credentialIssuer = await this.parseIssuerFromCredential(agentContext, sdJwtVc, returnSdJwtVc, trustedCertificates);
|
|
152
157
|
const issuer = await this.extractKeyFromIssuer(agentContext, credentialIssuer);
|
|
153
|
-
const
|
|
154
|
-
const holder = holderBinding ? await extractKeyFromHolderBinding(agentContext, holderBinding) : void 0;
|
|
158
|
+
const holder = returnSdJwtVc.holder ? await extractKeyFromHolderBinding(agentContext, returnSdJwtVc.holder) : void 0;
|
|
155
159
|
sdjwt.config({
|
|
156
160
|
verifier: getSdJwtVerifier(agentContext, issuer.publicJwk),
|
|
157
161
|
kbVerifier: holder ? getSdJwtVerifier(agentContext, holder.publicJwk) : void 0
|
|
@@ -200,16 +204,10 @@ let SdJwtVcService = class SdJwtVcService$1 {
|
|
|
200
204
|
sdJwtVc: returnSdJwtVc
|
|
201
205
|
};
|
|
202
206
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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) {}
|
|
207
|
+
if (fetchTypeMetadata) returnSdJwtVc.typeMetadata = await this.fetchTypeMetadata(agentContext, returnSdJwtVc, {
|
|
208
|
+
throwErrorOnFetchError: false,
|
|
209
|
+
throwErrorOnUnsupportedVctValue: false
|
|
210
|
+
});
|
|
213
211
|
} catch (error) {
|
|
214
212
|
return {
|
|
215
213
|
isValid: false,
|
|
@@ -222,6 +220,36 @@ let SdJwtVcService = class SdJwtVcService$1 {
|
|
|
222
220
|
sdJwtVc: returnSdJwtVc
|
|
223
221
|
};
|
|
224
222
|
}
|
|
223
|
+
async fetchTypeMetadata(agentContext, sdJwtVc, { throwErrorOnFetchError = true, throwErrorOnUnsupportedVctValue = true } = {}) {
|
|
224
|
+
const vct = sdJwtVc.payload.vct;
|
|
225
|
+
const vctIntegrity = sdJwtVc.payload["vct#integrity"];
|
|
226
|
+
if (!vct || typeof vct !== "string" || !vct.startsWith("https://")) {
|
|
227
|
+
if (!throwErrorOnUnsupportedVctValue) return void 0;
|
|
228
|
+
throw new SdJwtVcError(`Unable to resolve type metadata for vct '${vct}'. Only https supported`);
|
|
229
|
+
}
|
|
230
|
+
let firstError;
|
|
231
|
+
const firstResponse = await agentContext.config.agentDependencies.fetch(vct).catch((error) => {
|
|
232
|
+
firstError = error;
|
|
233
|
+
});
|
|
234
|
+
let response = firstResponse;
|
|
235
|
+
if (!response || !response?.ok) {
|
|
236
|
+
const vctElements = vct.split("/");
|
|
237
|
+
vctElements.splice(3, 0, ".well-known/vct");
|
|
238
|
+
const legacyVctUrl = vctElements.join("/");
|
|
239
|
+
response = await agentContext.config.agentDependencies.fetch(legacyVctUrl).catch(() => void 0);
|
|
240
|
+
}
|
|
241
|
+
if (!response?.ok) {
|
|
242
|
+
if (!throwErrorOnFetchError) return void 0;
|
|
243
|
+
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 });
|
|
244
|
+
else throw new SdJwtVcError(`Unable to resolve type metadata vct '${vct}'. Fetch returned a non-successful response.`, { cause: firstError });
|
|
245
|
+
}
|
|
246
|
+
const typeMetadata = await response.clone().json();
|
|
247
|
+
if (vctIntegrity) {
|
|
248
|
+
if (typeof vctIntegrity !== "string") throw new SdJwtVcError(`Found 'vct#integrity' with value '${vctIntegrity}' but value was not of type 'string'.`);
|
|
249
|
+
IntegrityVerifier.verifyIntegrity(new Uint8Array(await response.arrayBuffer()), vctIntegrity);
|
|
250
|
+
}
|
|
251
|
+
return typeMetadata;
|
|
252
|
+
}
|
|
225
253
|
async store(agentContext, options) {
|
|
226
254
|
await this.sdJwtVcRepository.save(agentContext, options.record);
|
|
227
255
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+FO,2BAAMA,iBAAe;CAG1B,AAAO,YAAY,mBAAsC;AACvD,OAAK,oBAAoB;;CAG3B,MAAa,KACX,cACA,SACkB;EAClB,MAAM,EAAE,SAAS,iBAAiB,qBAAqB;AAGvD,MAAI,oBAAoB,qBAAqB,UAC3C,OAAM,IAAI,aAAa,uCAAuC,mBAAmB;EAGnF,MAAM,SAAS,MAAM,KAAK,qBAAqB,cAAc,QAAQ,QAAQ,KAAK;EAGlF,MAAM,gBAAgB,QAAQ,SAAS,MAAM,4BAA4B,cAAc,QAAQ,OAAO,GAAG;EAEzG,MAAM,SAAS;GACb,KAAK,OAAO;GACZ,KAAK,QAAQ,cAAc;GAC3B,KAAK,OAAO;GACZ,KAAK,OAAO,KAAK,KAAK,SAAS,KAAK,SAAS,SAAS,CAAC;GACxD;EAED,MAAM,QAAQ,IAAI,gBAAgB;GAChC,GAAG,KAAK,mBAAmB,aAAa;GACxC,QAAQ,eAAe,cAAc,OAAO,UAAU;GACtD,SAAS;GACT,SAAS,OAAO;GACjB,CAAC;AAEF,MAAI,CAAC,QAAQ,OAAO,OAAO,QAAQ,QAAQ,SACzC,OAAM,IAAI,aAAa,mCAAmC;EAG5D,MAAM,UAAU,MAAM,MAAM,MAC1B;GACE,GAAG;GACH,KAAK,eAAe;GACpB,KAAK,OAAO;GACZ,KAAK,cAAc;GACnB,KAAK,QAAQ;GACd,EACD,iBACA,EAAE,QAAQ,CACX;EAED,MAAM,eAAgB,MAAM,MAAM,UAAU,QAAQ;EAEpD,MAAM,gBADI,MAAM,MAAM,OAAO,QAAQ,EACd,KAAK;AAC5B,MAAI,CAAC,aACH,OAAM,IAAI,aAAa,2BAA2B;AAGpD,SAAO;GACL;GACA;GACQ;GACR,SAAS;GACT,aAAa,YAAY;GACzB,SAAS;GACV;;CAGH,AAAO,YACL,gBACA,cAC0B;AAC1B,SAAO,cAAc,gBAAgB,aAAa;;CAGpD,AAAO,2BAA2B,gBAAwB,kBAAuC;EAC/F,MAAM,UAAU,gBAAgB,gBAAgB,OAAO,KAAK;EAC5D,MAAM,oBAAoB,+BAA+B,iBAAiB,IAAI,EAAE;AAEhF,MAAI,QAAQ,MACV,OAAM,IAAI,aAAa,kEAAkE;EAG3F,MAAM,sBAAsB,kBAC1B,QAAQ,IAAI,SAEZ,QAAQ,YAAY,KAAK,OAAO;GAC9B,QAAQ,EAAE,WAAW;IAAE,KAAK;IAAW,QAAQ,OAAO;IAAM,CAAC;GAC7D,SAAS,EAAE,QAAQ;GACnB,KAAK,EAAE;GACP,MAAM,EAAE;GACR,OAAO,EAAE;GACV,EAAE,EACH,kBACD;EACD,MAAM,CAAC,OAAO,eAAe,MAAM,IAAI;AAKvC,SADyB,cADX,GAAG,IAAI,GADnB,oBAAoB,SAAS,IAAI,GAAG,oBAAoB,KAAK,MAAM,EAAE,QAAQ,CAAC,KAAK,IAAI,CAAC,KAAK,KAElD;;CAI/C,MAAa,QACX,cACA,EAAE,SAAS,mBAAmB,kBAAkB,qBAC/B;EACjB,MAAM,QAAQ,IAAI,gBAAgB,KAAK,mBAAmB,aAAa,CAAC;EACxE,MAAM,iBAAiB,OAAO,YAAY,WAAW,UAAU,QAAQ;EAGvE,MAAM,gBAAgB,kCAFE,MAAM,MAAM,OAAO,eAAe,EAEa,KAAK,QAAQ;AACpF,MAAI,CAAC,iBAAiB,iBACpB,OAAM,IAAI,aAAa,wFAAwF;EAGjH,MAAM,SAAS,gBACX,MAAM,4BAA4B,cAAc,eAAe;GAC7D,YAAY;GACZ,UAAU,OAAO,YAAY,WAAW,QAAQ,WAAW;GAC5D,CAAC,GACF;AACJ,QAAM,OAAO;GACX,UAAU,SAAS,eAAe,cAAc,OAAO,UAAU,GAAG;GACpE,WAAW,QAAQ;GACpB,CAAC;AAeF,SAb8B,MAAM,MAAM,QAAQ,gBAAgB,mBAAiD,EACjH,IAAI,mBACA,EACE,SAAS;GACP,KAAK,iBAAiB;GACtB,OAAO,iBAAiB;GACxB,KAAK,iBAAiB;GACtB,GAAG;GACJ,EACF,GACD,QACL,CAAC;;CAKJ,AAAQ,wBACN,cACA,KACA,iBACA;AAEA,MAAI,CAAC,IAAK;AAGV,MAAI,CAAC,IAAI,WAAW,WAAW,IAAI,EAAE,IAAI,WAAW,UAAU,IAAI,aAAa,OAAO,uBACpF,OAAM,IAAI,aAAa,mDAAmD;AAG5E,MAAI,CAAC,gBAAgB,aAAa,SAAS,IAAI,IAAI,CAAC,gBAAgB,aAAa,SAAS,iBAAiB,IAAI,CAAC,CAC9G,OAAM,IAAI,aACR,+PACD;;CAIL,MAAa,OACX,cACA,EAAE,gBAAgB,YAAY,mBAAmB,mBAAmB,qBAAqB,OAIzF;EACA,MAAM,QAAQ,IAAI,gBAAgB,EAChC,GAAG,KAAK,mBAAmB,aAAa,EAIzC,CAAC;EAEF,IAAIC;AAEJ,MAAI;AACF,aAAU,MAAM,MAAM,OAAO,eAAe;AAC5C,OAAI,CAAC,QAAQ,IAAK,OAAM,IAAI,WAAW,oBAAoB;WACpD,OAAO;AACd,UAAO;IACL,SAAS;IACT;IACD;;EAGH,MAAMC,gBAA0C;GAC9C,SAAS,QAAQ,IAAI;GACrB,QAAQ,QAAQ,IAAI;GACpB,SAAS;GACT,cAAc,MAAM,QAAQ,UAAU,cAAc;GAEpD,OAAO,QAAQ,QACX;IACE,SAAS,QAAQ,MAAM;IACvB,QAAQ,QAAQ,MAAM;IACvB,GACD;GACJ,aAAa,YAAY;GACzB,SAAS;GACV;AAED,MAAI;GACF,MAAM,mBAAmB,MAAM,KAAK,0BAClC,cACA,SACA,eACA,oBACD;GACD,MAAM,SAAS,MAAM,KAAK,qBAAqB,cAAc,iBAAiB;GAC9E,MAAM,gBAAgB,iCAAiC,QAAQ,IAAI,QAAQ;GAC3E,MAAM,SAAS,gBAAgB,MAAM,4BAA4B,cAAc,cAAc,GAAG;AAEhG,SAAM,OAAO;IACX,UAAU,iBAAiB,cAAc,OAAO,UAAU;IAC1D,YAAY,SAAS,iBAAiB,cAAc,OAAO,UAAU,GAAG;IACzE,CAAC;AAEF,OAAI;AACF,UAAM,MAAM,OAAO,gBAAgB;KACjC,mBAAmB,oBAAoB,CAAC,GAAG,mBAAmB,MAAM,GAAG,CAAC,MAAM;KAC9E,iBAAiB,YAAY;KAC7B,aAAa,cAAc,uBAAO,IAAI,MAAM,CAAC;KAC7C,aAAa;KACd,CAAC;YACK,OAAO;AACd,WAAO;KACL;KACA,SAAS;KACT,SAAS;KACV;;AAGH,OAAI,QAAQ,IAAI,QAAQ,QAAQ,eAAe,QAAQ,IAAI,QAAQ,QAAQ,YACzE,QAAO;IACL,OAAO,IAAI,aAAa,4DAA4D;IACpF,SAAS;IACT,SAAS;IACV;AAGH,OAAI;AACF,eAAW,SAAS,cAAc,QAAQ,CAAC,SAAS;KAClD,KAAK,cAAc,uBAAO,IAAI,MAAM,CAAC;KACrC,UAAU;KACX,CAAC;YACK,OAAO;AACd,WAAO;KACL;KACA,SAAS;KACT,SAAS;KACV;;AAIH,OAAI;AACF,QAAI,YAAY;AACd,SAAI,CAAC,QAAQ,SAAS,CAAC,QAAQ,MAAM,QACnC,OAAM,IAAI,aAAa,2DAA2D;AAIpF,SAAI,QAAQ,MAAM,QAAQ,QAAQ,WAAW,SAC3C,OAAM,IAAI,aAAa,6DAA6D;AAGtF,SAAI,QAAQ,MAAM,QAAQ,UAAU,WAAW,MAC7C,OAAM,IAAI,aAAa,0DAA0D;;YAG9E,OAAO;AACd,WAAO;KACL;KACA,SAAS;KACT,SAAS;KACV;;AAGH,OAAI;IACF,MAAM,MAAM,cAAc,SAAS;AACnC,QAAI,qBAAqB,OAAO,QAAQ,YAAY,IAAI,WAAW,WAAW,EAAE;KAE9E,MAAM,cAAc,IAAI,MAAM,IAAI;AAClC,iBAAY,OAAO,GAAG,GAAG,kBAAkB;KAC3C,MAAM,SAAS,YAAY,KAAK,IAAI;KAEpC,MAAM,WAAW,MAAM,aAAa,OAAO,kBAAkB,MAAM,OAAO;AAC1E,SAAI,SAAS,GAEX,eAAc,eADO,MAAM,SAAS,MAAM;;YAIvC,QAAQ;WAGV,OAAO;AACd,UAAO;IACL,SAAS;IACT;IACA,SAAS;IACV;;AAGH,SAAO;GACL,SAAS;GACT,SAAS;GACV;;CAGH,MAAa,MAAM,cAA4B,SAA8B;AAC3E,QAAM,KAAK,kBAAkB,KAAK,cAAc,QAAQ,OAAO;AAC/D,SAAO,QAAQ;;CAGjB,MAAa,QAAQ,cAA4B,IAAoC;AACnF,SAAO,MAAM,KAAK,kBAAkB,QAAQ,cAAc,GAAG;;CAG/D,MAAa,OAAO,cAA2D;AAC7E,SAAO,MAAM,KAAK,kBAAkB,OAAO,aAAa;;CAG1D,MAAa,YACX,cACA,OACA,cAC+B;AAC/B,SAAO,MAAM,KAAK,kBAAkB,YAAY,cAAc,OAAO,aAAa;;CAGpF,MAAa,WAAW,cAA4B,IAAY;AAC9D,QAAM,KAAK,kBAAkB,WAAW,cAAc,GAAG;;CAG3D,MAAa,OAAO,cAA4B,eAA8B;AAC5E,QAAM,KAAK,kBAAkB,OAAO,cAAc,cAAc;;CAGlE,MAAc,qBAAqB,cAA4B,QAAuB,aAAa,OAAO;AACxG,MAAI,OAAO,WAAW,OAAO;GAC3B,MAAM,YAAY,SAAS,OAAO,OAAO;AACzC,OAAI,CAAC,UAAU,SACb,OAAM,IAAI,aACR,WAAW,OAAO,OAAO,kEAC1B;GAGH,IAAIC;AACJ,OAAI,WACF,aAAY,MAAM,kCAAkC,cAAc,OAAO,OAAO;QAC3E;IACL,MAAM,EAAE,uBAAuB,MAAM,cAAc,cAAc,OAAO,OAAO;AAC/E,gBAAY,mCAAmC,mBAAmB;;GAGpE,MAAM,+BAA+B,UAAU;AAC/C,OAAI,6BAA6B,WAAW,EAC1C,OAAM,IAAI,aACR,uDAAuD,UAAU,0BAClE;AAIH,UAAO;IACL,KAHU,6BAA6B;IAIvC;IACA,KAAK,UAAU;IACf,KAAK,IAAI,UAAU;IACpB;;AAGH,MAAI,OAAO,WAAW,OAAO;GAC3B,MAAM,kBAAkB,OAAO,IAAI;AACnC,OAAI,CAAC,gBACH,OAAM,IAAI,aAAa,6BAA6B;AAGtD,OAAI,cAAc,CAAC,gBAAgB,UAAU,SAC3C,OAAM,IAAI,aAAa,wEAAwE;GAGjG,MAAM,YAAY,gBAAgB;GAClC,MAAM,+BAA+B,UAAU;AAC/C,OAAI,6BAA6B,WAAW,EAC1C,OAAM,IAAI,aACR,uDAAuD,UAAU,0BAClE;GAEH,MAAM,MAAM,6BAA6B;AAEzC,QAAK,wBAAwB,cAAc,OAAO,QAAQ,gBAAgB;AAE1E,UAAO;IACL;IACA,KAAK,OAAO;IACZ,KAAK,OAAO;IACZ;IACD;;AAGH,QAAM,IAAI,aAAa,kFAAkF;;CAG3G,MAAc,0BACZ,cACA,SACA,cACA,sBACwB;EACxB,MAAM,aAAa,aAAa,kBAAkB,QAAQ,iBAAiB;AAC3E,MAAI,CAAC,QAAQ,KAAK,QAChB,OAAM,IAAI,aAAa,uBAAuB;EAGhD,MAAM,MAAM,QAAQ,IAAI,QAAQ;AAEhC,MAAI,QAAQ,IAAI,QAAQ,KAAK;AAC3B,OAAI,CAAC,MAAM,QAAQ,QAAQ,IAAI,OAAO,IAAI,CACxC,OAAM,IAAI,aAAa,kDAAkD;AAE3E,OAAI,QAAQ,IAAI,OAAO,IAAI,WAAW,EACpC,OAAM,IAAI,aAAa,iDAAiD;AAE1E,OAAI,QAAQ,IAAI,OAAO,IAAI,MAAM,QAAQ,OAAO,QAAQ,SAAS,CAC/D,OAAM,IAAI,aAAa,6DAA6D;GAGtF,IAAI,sBAAsB;GAC1B,MAAM,mBAAmB,QAAQ,IAAI,OAAO,IAAI,KAAK,SAAS,gBAAgB,uBAAuB,KAAK,CAAC;AAE3G,OAAI,CAAC,oBACH,uBACG,MAAM,WAAW,wCAAwC,cAAc;IACtE;IACA,cAAc;KACZ,MAAM;KACN,YAAY;KACb;IACF,CAAC,IAAK,WAAW;AAGtB,OAAI,CAAC,oBACH,OAAM,IAAI,aACR,uGACD;AAGH,SAAM,YAAY,yBAAyB,cAAc;IACvD,kBAAkB,QAAQ,IAAI,OAAO;IACrC;IACD,CAAC;AAEF,UAAO;IACL,QAAQ;IACR,KAAK;IACL,QAAQ;IACT;;AAGH,MAAI,KAAK,WAAW,OAAO,EAAE;AAI3B,OAAI,CAAC,QAAQ,KAAK,OAChB,OAAM,IAAI,aAAa,uCAAuC;AAGhE,OAAI,CAAC,QAAQ,IAAI,OAAO,IACtB,OAAM,IAAI,aAAa,kDAAkD;GAG3E,MAAM,YAAY,QAAQ,IAAI,OAAO;GAErC,IAAIC;AACJ,OAAI,UAAU,WAAW,IAAI,CAC3B,UAAS,GAAG,MAAM;YACT,UAAU,WAAW,OAAO,EAAE;IACvC,MAAM,aAAa,SAAS,UAAU;AACtC,QAAI,WAAW,QAAQ,IACrB,OAAM,IAAI,aACR,sDAAsD,WAAW,IAAI,uCAAuC,IAAI,GACjH;AAGH,aAAS;SAET,OAAM,IAAI,aACR,kGACD;AAGH,UAAO;IACL,QAAQ;IACR;IACD;;AAGH,QAAM,IAAI,aAAa,0FAA0F;;CAGnH,AAAQ,mBAAmB,cAA2C;EACpE,MAAM,MAAM,aAAa,QAAQ,iBAAiB;AAElD,SAAO;GACL,QAAQ;GACR,mBAAmB,KAAK,qBAAqB,aAAa;GAC1D,gBAAgB,WAAW,kBAAkB,YAAY,IAAI,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,GAAG,OAAO;GACvG;;CAGH,AAAQ,qBAAqB,cAA4B;AACvD,SAAO,OAAO,QAAgB;GAC5B,MAAM,WAAW,MAAM,iBAAiB,aAAa,OAAO,kBAAkB,OAAO,KAAK,EACxF,SAAS,EACP,QAAQ,8BACT,EACF,CAAC;AAEF,OAAI,CAAC,SAAS,GACZ,OAAM,IAAI,WACR,yCACE,SAAS,OACV,kCAAkC,IAAI,IAAI,MAAM,SAAS,MAAM,GACjE;AAGH,UAAO,MAAM,SAAS,MAAM;;;;6BAphBjC,YAAY"}
|
|
1
|
+
{"version":3,"file":"SdJwtVcService.mjs","names":["SdJwtVcService","sdJwtVc: SDJwt","holderBinding: SdJwtVcHolderBinding | undefined","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 SdJwtVcHolderBinding,\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 /**\n * The holder of the credential\n */\n holder: SdJwtVcHolderBinding | undefined\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 decoded = await sdJwt.decode(compact)\n const sdJwtPayload = decoded.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 holder: options.holder,\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 let holderBinding: SdJwtVcHolderBinding | undefined\n\n try {\n sdJwtVc = await sdjwt.decode(compactSdJwtVc)\n if (!sdJwtVc.jwt) throw new CredoError('Invalid sd-jwt-vc')\n holderBinding = parseHolderBindingFromCredential(sdJwtVc.jwt.payload) ?? undefined\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 holder: holderBinding,\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 holder = returnSdJwtVc.holder\n ? await extractKeyFromHolderBinding(agentContext, returnSdJwtVc.holder)\n : 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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"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { Hasher } from "../../crypto/hashes/Hasher.mjs";
|
|
4
4
|
import { ClaimFormat } from "../vc/models/ClaimFormat.mjs";
|
|
5
5
|
import "../../crypto/index.mjs";
|
|
6
|
+
import { parseHolderBindingFromCredential } from "./utils.mjs";
|
|
6
7
|
import "../vc/index.mjs";
|
|
7
8
|
import { decodeSdJwtSync, getClaimsSync } from "@sd-jwt/decode";
|
|
8
9
|
|
|
@@ -17,6 +18,7 @@ function decodeSdJwtVc(compactSdJwtVc, typeMetadata) {
|
|
|
17
18
|
compact: compactSdJwtVc,
|
|
18
19
|
header: jwt.header,
|
|
19
20
|
payload: jwt.payload,
|
|
21
|
+
holder: parseHolderBindingFromCredential(jwt.payload) ?? void 0,
|
|
20
22
|
prettyClaims,
|
|
21
23
|
claimFormat: ClaimFormat.SdJwtDc,
|
|
22
24
|
encoded: compactSdJwtVc,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decodeSdJwtVc.mjs","names":[],"sources":["../../../src/modules/sd-jwt-vc/decodeSdJwtVc.ts"],"sourcesContent":["import { decodeSdJwtSync, getClaimsSync } from '@sd-jwt/decode'\nimport { Hasher } from '../../crypto'\nimport { ClaimFormat } from '../vc/index'\nimport type { SdJwtVcHeader, SdJwtVcPayload } from './SdJwtVcOptions'\nimport type { SdJwtVc } from './SdJwtVcService'\nimport type { SdJwtVcTypeMetadata } from './typeMetadata'\n\nexport function sdJwtVcHasher(data: string | ArrayBufferLike, alg: string) {\n return Hasher.hash(typeof data === 'string' ? data : new Uint8Array(data), alg)\n}\n\nexport function decodeSdJwtVc<\n Header extends SdJwtVcHeader = SdJwtVcHeader,\n Payload extends SdJwtVcPayload = SdJwtVcPayload,\n>(compactSdJwtVc: string, typeMetadata?: SdJwtVcTypeMetadata): SdJwtVc<Header, Payload> {\n // NOTE: we use decodeSdJwtSync so we can make this method sync\n const { jwt, disclosures, kbJwt } = decodeSdJwtSync(compactSdJwtVc, sdJwtVcHasher)\n const prettyClaims = getClaimsSync(jwt.payload, disclosures, sdJwtVcHasher)\n\n return {\n compact: compactSdJwtVc,\n header: jwt.header as Header,\n payload: jwt.payload as Payload,\n prettyClaims: prettyClaims as Payload,\n claimFormat: ClaimFormat.SdJwtDc,\n encoded: compactSdJwtVc,\n kbJwt: kbJwt\n ? {\n payload: kbJwt.payload as Record<string, unknown>,\n header: kbJwt.header as Record<string, unknown>,\n }\n : undefined,\n ...(typeMetadata && { typeMetadata }),\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"decodeSdJwtVc.mjs","names":[],"sources":["../../../src/modules/sd-jwt-vc/decodeSdJwtVc.ts"],"sourcesContent":["import { decodeSdJwtSync, getClaimsSync } from '@sd-jwt/decode'\nimport { Hasher } from '../../crypto'\nimport { ClaimFormat } from '../vc/index'\nimport type { SdJwtVcHeader, SdJwtVcPayload } from './SdJwtVcOptions'\nimport type { SdJwtVc } from './SdJwtVcService'\nimport type { SdJwtVcTypeMetadata } from './typeMetadata'\nimport { parseHolderBindingFromCredential } from './utils'\n\nexport function sdJwtVcHasher(data: string | ArrayBufferLike, alg: string) {\n return Hasher.hash(typeof data === 'string' ? data : new Uint8Array(data), alg)\n}\n\nexport function decodeSdJwtVc<\n Header extends SdJwtVcHeader = SdJwtVcHeader,\n Payload extends SdJwtVcPayload = SdJwtVcPayload,\n>(compactSdJwtVc: string, typeMetadata?: SdJwtVcTypeMetadata): SdJwtVc<Header, Payload> {\n // NOTE: we use decodeSdJwtSync so we can make this method sync\n const { jwt, disclosures, kbJwt } = decodeSdJwtSync(compactSdJwtVc, sdJwtVcHasher)\n const prettyClaims = getClaimsSync(jwt.payload, disclosures, sdJwtVcHasher)\n\n return {\n compact: compactSdJwtVc,\n header: jwt.header as Header,\n payload: jwt.payload as Payload,\n holder: parseHolderBindingFromCredential(jwt.payload) ?? undefined,\n prettyClaims: prettyClaims as Payload,\n claimFormat: ClaimFormat.SdJwtDc,\n encoded: compactSdJwtVc,\n kbJwt: kbJwt\n ? {\n payload: kbJwt.payload as Record<string, unknown>,\n header: kbJwt.header as Record<string, unknown>,\n }\n : undefined,\n ...(typeMetadata && { typeMetadata }),\n }\n}\n"],"mappings":";;;;;;;;;;AAQA,SAAgB,cAAc,MAAgC,KAAa;AACzE,QAAO,OAAO,KAAK,OAAO,SAAS,WAAW,OAAO,IAAI,WAAW,KAAK,EAAE,IAAI;;AAGjF,SAAgB,cAGd,gBAAwB,cAA8D;CAEtF,MAAM,EAAE,KAAK,aAAa,UAAU,gBAAgB,gBAAgB,cAAc;CAClF,MAAM,eAAe,cAAc,IAAI,SAAS,aAAa,cAAc;AAE3E,QAAO;EACL,SAAS;EACT,QAAQ,IAAI;EACZ,SAAS,IAAI;EACb,QAAQ,iCAAiC,IAAI,QAAQ,IAAI;EAC3C;EACd,aAAa,YAAY;EACzB,SAAS;EACT,OAAO,QACH;GACE,SAAS,MAAM;GACf,QAAQ,MAAM;GACf,GACD;EACJ,GAAI,gBAAgB,EAAE,cAAc;EACrC"}
|
|
@@ -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 };
|
|
@@ -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"}
|
package/build/utils/index.mjs
CHANGED
|
@@ -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";
|