@sphereon/ssi-sdk.credential-vcdm2-sdjwt-provider 0.34.1-next.85
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/LICENSE +201 -0
- package/README.md +6 -0
- package/dist/index.cjs +896 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +39 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +865 -0
- package/dist/index.js.map +1 -0
- package/package.json +94 -0
- package/src/__tests__/issue-verify-flow-vcdm2-jose.test.ts +141 -0
- package/src/agent/CredentialProviderVcdm2SdJwt.ts +641 -0
- package/src/did-jwt/JWT.ts +634 -0
- package/src/did-jwt/SignerAlgorithm.ts +67 -0
- package/src/did-jwt/VerifierAlgorithm.ts +167 -0
- package/src/did-jwt/util.ts +407 -0
- package/src/index.ts +1 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,896 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
|
|
31
|
+
// src/index.ts
|
|
32
|
+
var index_exports = {};
|
|
33
|
+
__export(index_exports, {
|
|
34
|
+
CredentialProviderVcdm2SdJwt: () => CredentialProviderVcdm2SdJwt
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// src/agent/CredentialProviderVcdm2SdJwt.ts
|
|
39
|
+
var import_ssi_sdk_ext = require("@sphereon/ssi-sdk-ext.identifier-resolution");
|
|
40
|
+
var import_ssi_sdk_ext2 = require("@sphereon/ssi-sdk-ext.key-utils");
|
|
41
|
+
var import_ssi_sdk = require("@sphereon/ssi-sdk.agent-config");
|
|
42
|
+
var import_ssi_sdk2 = require("@sphereon/ssi-sdk.core");
|
|
43
|
+
var import_ssi_sdk3 = require("@sphereon/ssi-sdk.credential-vcdm");
|
|
44
|
+
var import_ssi_types = require("@sphereon/ssi-types");
|
|
45
|
+
var import_debug = __toESM(require("debug"), 1);
|
|
46
|
+
var import_did_jwt3 = require("did-jwt");
|
|
47
|
+
var import_did_jwt_vc = require("did-jwt-vc");
|
|
48
|
+
|
|
49
|
+
// src/did-jwt/JWT.ts
|
|
50
|
+
var import_canonicalize = __toESM(require("canonicalize"), 1);
|
|
51
|
+
var import_did_resolver = require("did-resolver");
|
|
52
|
+
|
|
53
|
+
// src/did-jwt/util.ts
|
|
54
|
+
var u8a = __toESM(require("uint8arrays"), 1);
|
|
55
|
+
var import_ed25519 = require("@noble/curves/ed25519");
|
|
56
|
+
var import_multiformats = require("multiformats");
|
|
57
|
+
var import_multibase = require("multibase");
|
|
58
|
+
var import_secp256k1 = require("@noble/curves/secp256k1");
|
|
59
|
+
var import_p256 = require("@noble/curves/p256");
|
|
60
|
+
function bytesToBase64url(b) {
|
|
61
|
+
return u8a.toString(b, "base64url");
|
|
62
|
+
}
|
|
63
|
+
__name(bytesToBase64url, "bytesToBase64url");
|
|
64
|
+
function base64ToBytes(s) {
|
|
65
|
+
const inputBase64Url = s.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
66
|
+
return u8a.fromString(inputBase64Url, "base64url");
|
|
67
|
+
}
|
|
68
|
+
__name(base64ToBytes, "base64ToBytes");
|
|
69
|
+
function base58ToBytes(s) {
|
|
70
|
+
return u8a.fromString(s, "base58btc");
|
|
71
|
+
}
|
|
72
|
+
__name(base58ToBytes, "base58ToBytes");
|
|
73
|
+
var VM_TO_KEY_TYPE = {
|
|
74
|
+
Secp256k1SignatureVerificationKey2018: "Secp256k1",
|
|
75
|
+
Secp256k1VerificationKey2018: "Secp256k1",
|
|
76
|
+
EcdsaSecp256k1VerificationKey2019: "Secp256k1",
|
|
77
|
+
EcdsaPublicKeySecp256k1: "Secp256k1",
|
|
78
|
+
EcdsaSecp256k1RecoveryMethod2020: "Secp256k1",
|
|
79
|
+
EcdsaSecp256r1VerificationKey2019: "P-256",
|
|
80
|
+
Ed25519VerificationKey2018: "Ed25519",
|
|
81
|
+
Ed25519VerificationKey2020: "Ed25519",
|
|
82
|
+
ED25519SignatureVerification: "Ed25519",
|
|
83
|
+
X25519KeyAgreementKey2019: "X25519",
|
|
84
|
+
X25519KeyAgreementKey2020: "X25519",
|
|
85
|
+
ConditionalProof2022: void 0,
|
|
86
|
+
JsonWebKey2020: void 0,
|
|
87
|
+
Multikey: void 0
|
|
88
|
+
};
|
|
89
|
+
var supportedCodecs = {
|
|
90
|
+
"ed25519-pub": 237,
|
|
91
|
+
"x25519-pub": 236,
|
|
92
|
+
"secp256k1-pub": 231,
|
|
93
|
+
"bls12_381-g1-pub": 234,
|
|
94
|
+
"bls12_381-g2-pub": 235,
|
|
95
|
+
"p256-pub": 4608
|
|
96
|
+
};
|
|
97
|
+
var CODEC_TO_KEY_TYPE = {
|
|
98
|
+
"bls12_381-g1-pub": "Bls12381G1",
|
|
99
|
+
"bls12_381-g2-pub": "Bls12381G2",
|
|
100
|
+
"ed25519-pub": "Ed25519",
|
|
101
|
+
"p256-pub": "P-256",
|
|
102
|
+
"secp256k1-pub": "Secp256k1",
|
|
103
|
+
"x25519-pub": "X25519"
|
|
104
|
+
};
|
|
105
|
+
function extractPublicKeyBytes(pk) {
|
|
106
|
+
if (pk.publicKeyBase58) {
|
|
107
|
+
return {
|
|
108
|
+
keyBytes: base58ToBytes(pk.publicKeyBase58),
|
|
109
|
+
keyType: VM_TO_KEY_TYPE[pk.type]
|
|
110
|
+
};
|
|
111
|
+
} else if (pk.publicKeyBase64) {
|
|
112
|
+
return {
|
|
113
|
+
keyBytes: base64ToBytes(pk.publicKeyBase64),
|
|
114
|
+
keyType: VM_TO_KEY_TYPE[pk.type]
|
|
115
|
+
};
|
|
116
|
+
} else if (pk.publicKeyHex) {
|
|
117
|
+
return {
|
|
118
|
+
keyBytes: hexToBytes(pk.publicKeyHex),
|
|
119
|
+
keyType: VM_TO_KEY_TYPE[pk.type]
|
|
120
|
+
};
|
|
121
|
+
} else if (pk.publicKeyJwk && pk.publicKeyJwk.crv === "secp256k1" && pk.publicKeyJwk.x && pk.publicKeyJwk.y) {
|
|
122
|
+
return {
|
|
123
|
+
keyBytes: import_secp256k1.secp256k1.ProjectivePoint.fromAffine({
|
|
124
|
+
x: bytesToBigInt(base64ToBytes(pk.publicKeyJwk.x)),
|
|
125
|
+
y: bytesToBigInt(base64ToBytes(pk.publicKeyJwk.y))
|
|
126
|
+
}).toRawBytes(false),
|
|
127
|
+
keyType: "Secp256k1"
|
|
128
|
+
};
|
|
129
|
+
} else if (pk.publicKeyJwk && pk.publicKeyJwk.crv === "P-256" && pk.publicKeyJwk.x && pk.publicKeyJwk.y) {
|
|
130
|
+
return {
|
|
131
|
+
keyBytes: import_p256.p256.ProjectivePoint.fromAffine({
|
|
132
|
+
x: bytesToBigInt(base64ToBytes(pk.publicKeyJwk.x)),
|
|
133
|
+
y: bytesToBigInt(base64ToBytes(pk.publicKeyJwk.y))
|
|
134
|
+
}).toRawBytes(false),
|
|
135
|
+
keyType: "P-256"
|
|
136
|
+
};
|
|
137
|
+
} else if (pk.publicKeyJwk && pk.publicKeyJwk.kty === "OKP" && [
|
|
138
|
+
"Ed25519",
|
|
139
|
+
"X25519"
|
|
140
|
+
].includes(pk.publicKeyJwk.crv ?? "") && pk.publicKeyJwk.x) {
|
|
141
|
+
return {
|
|
142
|
+
keyBytes: base64ToBytes(pk.publicKeyJwk.x),
|
|
143
|
+
keyType: pk.publicKeyJwk.crv
|
|
144
|
+
};
|
|
145
|
+
} else if (pk.publicKeyMultibase) {
|
|
146
|
+
const { keyBytes, keyType } = multibaseToBytes(pk.publicKeyMultibase);
|
|
147
|
+
return {
|
|
148
|
+
keyBytes,
|
|
149
|
+
keyType: keyType ?? VM_TO_KEY_TYPE[pk.type]
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
keyBytes: new Uint8Array()
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
__name(extractPublicKeyBytes, "extractPublicKeyBytes");
|
|
157
|
+
function multibaseToBytes(s) {
|
|
158
|
+
const bytes = (0, import_multibase.decode)(s);
|
|
159
|
+
if ([
|
|
160
|
+
32,
|
|
161
|
+
33,
|
|
162
|
+
48,
|
|
163
|
+
64,
|
|
164
|
+
65,
|
|
165
|
+
96
|
|
166
|
+
].includes(bytes.length)) {
|
|
167
|
+
return {
|
|
168
|
+
keyBytes: bytes
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
const [codec, length] = import_multiformats.varint.decode(bytes);
|
|
173
|
+
const possibleCodec = Object.entries(supportedCodecs).filter(([, code]) => code === codec)?.[0][0] ?? "";
|
|
174
|
+
return {
|
|
175
|
+
keyBytes: bytes.slice(length),
|
|
176
|
+
keyType: CODEC_TO_KEY_TYPE[possibleCodec]
|
|
177
|
+
};
|
|
178
|
+
} catch (e) {
|
|
179
|
+
return {
|
|
180
|
+
keyBytes: bytes
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
__name(multibaseToBytes, "multibaseToBytes");
|
|
185
|
+
function hexToBytes(s, minLength) {
|
|
186
|
+
let input = s.startsWith("0x") ? s.substring(2) : s;
|
|
187
|
+
if (input.length % 2 !== 0) {
|
|
188
|
+
input = `0${input}`;
|
|
189
|
+
}
|
|
190
|
+
if (minLength) {
|
|
191
|
+
const paddedLength = Math.max(input.length, minLength * 2);
|
|
192
|
+
input = input.padStart(paddedLength, "00");
|
|
193
|
+
}
|
|
194
|
+
return u8a.fromString(input.toLowerCase(), "base16");
|
|
195
|
+
}
|
|
196
|
+
__name(hexToBytes, "hexToBytes");
|
|
197
|
+
function bytesToHex(b) {
|
|
198
|
+
return u8a.toString(b, "base16");
|
|
199
|
+
}
|
|
200
|
+
__name(bytesToHex, "bytesToHex");
|
|
201
|
+
function bytesToBigInt(b) {
|
|
202
|
+
return BigInt(`0x` + u8a.toString(b, "base16"));
|
|
203
|
+
}
|
|
204
|
+
__name(bytesToBigInt, "bytesToBigInt");
|
|
205
|
+
function stringToBytes(s) {
|
|
206
|
+
return u8a.fromString(s, "utf-8");
|
|
207
|
+
}
|
|
208
|
+
__name(stringToBytes, "stringToBytes");
|
|
209
|
+
function toJose({ r, s, recoveryParam }, recoverable) {
|
|
210
|
+
const jose = new Uint8Array(recoverable ? 65 : 64);
|
|
211
|
+
jose.set(u8a.fromString(r, "base16"), 0);
|
|
212
|
+
jose.set(u8a.fromString(s, "base16"), 32);
|
|
213
|
+
if (recoverable) {
|
|
214
|
+
if (typeof recoveryParam === "undefined") {
|
|
215
|
+
throw new Error("Signer did not return a recoveryParam");
|
|
216
|
+
}
|
|
217
|
+
jose[64] = recoveryParam;
|
|
218
|
+
}
|
|
219
|
+
return bytesToBase64url(jose);
|
|
220
|
+
}
|
|
221
|
+
__name(toJose, "toJose");
|
|
222
|
+
function fromJose(signature) {
|
|
223
|
+
const signatureBytes = base64ToBytes(signature);
|
|
224
|
+
if (signatureBytes.length < 64 || signatureBytes.length > 65) {
|
|
225
|
+
throw new TypeError(`Wrong size for signature. Expected 64 or 65 bytes, but got ${signatureBytes.length}`);
|
|
226
|
+
}
|
|
227
|
+
const r = bytesToHex(signatureBytes.slice(0, 32));
|
|
228
|
+
const s = bytesToHex(signatureBytes.slice(32, 64));
|
|
229
|
+
const recoveryParam = signatureBytes.length === 65 ? signatureBytes[64] : void 0;
|
|
230
|
+
return {
|
|
231
|
+
r,
|
|
232
|
+
s,
|
|
233
|
+
recoveryParam
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
__name(fromJose, "fromJose");
|
|
237
|
+
|
|
238
|
+
// src/did-jwt/SignerAlgorithm.ts
|
|
239
|
+
function instanceOfEcdsaSignature(object) {
|
|
240
|
+
return typeof object === "object" && "r" in object && "s" in object;
|
|
241
|
+
}
|
|
242
|
+
__name(instanceOfEcdsaSignature, "instanceOfEcdsaSignature");
|
|
243
|
+
function ES256SignerAlg() {
|
|
244
|
+
return /* @__PURE__ */ __name(async function sign(payload, signer) {
|
|
245
|
+
const signature = await signer(payload);
|
|
246
|
+
if (instanceOfEcdsaSignature(signature)) {
|
|
247
|
+
return toJose(signature);
|
|
248
|
+
} else {
|
|
249
|
+
return signature;
|
|
250
|
+
}
|
|
251
|
+
}, "sign");
|
|
252
|
+
}
|
|
253
|
+
__name(ES256SignerAlg, "ES256SignerAlg");
|
|
254
|
+
function ES256KSignerAlg(recoverable) {
|
|
255
|
+
return /* @__PURE__ */ __name(async function sign(payload, signer) {
|
|
256
|
+
const signature = await signer(payload);
|
|
257
|
+
if (instanceOfEcdsaSignature(signature)) {
|
|
258
|
+
return toJose(signature, recoverable);
|
|
259
|
+
} else {
|
|
260
|
+
if (recoverable && typeof fromJose(signature).recoveryParam === "undefined") {
|
|
261
|
+
throw new Error(`not_supported: ES256K-R not supported when signer doesn't provide a recovery param`);
|
|
262
|
+
}
|
|
263
|
+
return signature;
|
|
264
|
+
}
|
|
265
|
+
}, "sign");
|
|
266
|
+
}
|
|
267
|
+
__name(ES256KSignerAlg, "ES256KSignerAlg");
|
|
268
|
+
function Ed25519SignerAlg() {
|
|
269
|
+
return /* @__PURE__ */ __name(async function sign(payload, signer) {
|
|
270
|
+
const signature = await signer(payload);
|
|
271
|
+
if (!instanceOfEcdsaSignature(signature)) {
|
|
272
|
+
return signature;
|
|
273
|
+
} else {
|
|
274
|
+
throw new Error("invalid_config: expected a signer function that returns a string instead of signature object");
|
|
275
|
+
}
|
|
276
|
+
}, "sign");
|
|
277
|
+
}
|
|
278
|
+
__name(Ed25519SignerAlg, "Ed25519SignerAlg");
|
|
279
|
+
var algorithms = {
|
|
280
|
+
ES256: ES256SignerAlg(),
|
|
281
|
+
ES256K: ES256KSignerAlg(),
|
|
282
|
+
// This is a non-standard algorithm but retained for backwards compatibility
|
|
283
|
+
// see https://github.com/decentralized-identity/did-jwt/issues/146
|
|
284
|
+
"ES256K-R": ES256KSignerAlg(true),
|
|
285
|
+
// This is actually incorrect but retained for backwards compatibility
|
|
286
|
+
// see https://github.com/decentralized-identity/did-jwt/issues/130
|
|
287
|
+
Ed25519: Ed25519SignerAlg(),
|
|
288
|
+
EdDSA: Ed25519SignerAlg()
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
// src/did-jwt/VerifierAlgorithm.ts
|
|
292
|
+
var import_did_jwt = require("did-jwt");
|
|
293
|
+
var import_secp256k12 = require("@noble/curves/secp256k1");
|
|
294
|
+
var import_p2562 = require("@noble/curves/p256");
|
|
295
|
+
var import_ed255192 = require("@noble/curves/ed25519");
|
|
296
|
+
var u8a2 = __toESM(require("uint8arrays"), 1);
|
|
297
|
+
var import_sha256 = require("@noble/hashes/sha256");
|
|
298
|
+
function sha256(payload) {
|
|
299
|
+
const data = typeof payload === "string" ? u8a2.fromString(payload) : payload;
|
|
300
|
+
return (0, import_sha256.sha256)(data);
|
|
301
|
+
}
|
|
302
|
+
__name(sha256, "sha256");
|
|
303
|
+
function toSignatureObject(signature, recoverable = false) {
|
|
304
|
+
const rawSig = base64ToBytes(signature);
|
|
305
|
+
if (rawSig.length !== (recoverable ? 65 : 64)) {
|
|
306
|
+
throw new Error("wrong signature length");
|
|
307
|
+
}
|
|
308
|
+
const r = bytesToHex(rawSig.slice(0, 32));
|
|
309
|
+
const s = bytesToHex(rawSig.slice(32, 64));
|
|
310
|
+
const sigObj = {
|
|
311
|
+
r,
|
|
312
|
+
s
|
|
313
|
+
};
|
|
314
|
+
if (recoverable) {
|
|
315
|
+
sigObj.recoveryParam = rawSig[64];
|
|
316
|
+
}
|
|
317
|
+
return sigObj;
|
|
318
|
+
}
|
|
319
|
+
__name(toSignatureObject, "toSignatureObject");
|
|
320
|
+
function toSignatureObject2(signature, recoverable = false) {
|
|
321
|
+
const bytes = base64ToBytes(signature);
|
|
322
|
+
if (bytes.length !== (recoverable ? 65 : 64)) {
|
|
323
|
+
throw new Error("wrong signature length");
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
compact: bytes.slice(0, 64),
|
|
327
|
+
recovery: bytes[64]
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
__name(toSignatureObject2, "toSignatureObject2");
|
|
331
|
+
function verifyES256(data, signature, authenticators) {
|
|
332
|
+
const hash2 = sha256(data);
|
|
333
|
+
const sig = import_p2562.p256.Signature.fromCompact(toSignatureObject2(signature).compact);
|
|
334
|
+
const fullPublicKeys = authenticators.filter((a) => !a.ethereumAddress && !a.blockchainAccountId);
|
|
335
|
+
const signer = fullPublicKeys.find((pk) => {
|
|
336
|
+
try {
|
|
337
|
+
const { keyBytes } = extractPublicKeyBytes(pk);
|
|
338
|
+
return import_p2562.p256.verify(sig, hash2, keyBytes);
|
|
339
|
+
} catch (err) {
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
if (!signer) throw new Error("invalid_signature: Signature invalid for JWT");
|
|
344
|
+
return signer;
|
|
345
|
+
}
|
|
346
|
+
__name(verifyES256, "verifyES256");
|
|
347
|
+
function verifyES256K(data, signature, authenticators) {
|
|
348
|
+
const hash2 = sha256(data);
|
|
349
|
+
const signatureNormalized = import_secp256k12.secp256k1.Signature.fromCompact(base64ToBytes(signature)).normalizeS();
|
|
350
|
+
const fullPublicKeys = authenticators.filter((a) => {
|
|
351
|
+
return !a.ethereumAddress && !a.blockchainAccountId;
|
|
352
|
+
});
|
|
353
|
+
const blockchainAddressKeys = authenticators.filter((a) => {
|
|
354
|
+
return a.ethereumAddress || a.blockchainAccountId;
|
|
355
|
+
});
|
|
356
|
+
let signer = fullPublicKeys.find((pk) => {
|
|
357
|
+
try {
|
|
358
|
+
const { keyBytes } = extractPublicKeyBytes(pk);
|
|
359
|
+
return import_secp256k12.secp256k1.verify(signatureNormalized, hash2, keyBytes);
|
|
360
|
+
} catch (err) {
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
if (!signer && blockchainAddressKeys.length > 0) {
|
|
365
|
+
signer = verifyRecoverableES256K(data, signature, blockchainAddressKeys);
|
|
366
|
+
}
|
|
367
|
+
if (!signer) throw new Error("invalid_signature: Signature invalid for JWT");
|
|
368
|
+
return signer;
|
|
369
|
+
}
|
|
370
|
+
__name(verifyES256K, "verifyES256K");
|
|
371
|
+
function verifyRecoverableES256K(data, signature, authenticators) {
|
|
372
|
+
const signatures = [];
|
|
373
|
+
if (signature.length > 86) {
|
|
374
|
+
signatures.push(toSignatureObject2(signature, true));
|
|
375
|
+
} else {
|
|
376
|
+
const so = toSignatureObject2(signature, false);
|
|
377
|
+
signatures.push({
|
|
378
|
+
...so,
|
|
379
|
+
recovery: 0
|
|
380
|
+
});
|
|
381
|
+
signatures.push({
|
|
382
|
+
...so,
|
|
383
|
+
recovery: 1
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
const hash2 = sha256(data);
|
|
387
|
+
const checkSignatureAgainstSigner = /* @__PURE__ */ __name((sigObj) => {
|
|
388
|
+
const signature2 = import_secp256k12.secp256k1.Signature.fromCompact(sigObj.compact).addRecoveryBit(sigObj.recovery || 0);
|
|
389
|
+
const recoveredPublicKey = signature2.recoverPublicKey(hash2);
|
|
390
|
+
const recoveredAddress = (0, import_did_jwt.toEthereumAddress)(recoveredPublicKey.toHex(false)).toLowerCase();
|
|
391
|
+
const recoveredPublicKeyHex = recoveredPublicKey.toHex(false);
|
|
392
|
+
const recoveredCompressedPublicKeyHex = recoveredPublicKey.toHex(true);
|
|
393
|
+
return authenticators.find((a) => {
|
|
394
|
+
const { keyBytes } = extractPublicKeyBytes(a);
|
|
395
|
+
const keyHex = bytesToHex(keyBytes);
|
|
396
|
+
return keyHex === recoveredPublicKeyHex || keyHex === recoveredCompressedPublicKeyHex || a.ethereumAddress?.toLowerCase() === recoveredAddress || a.blockchainAccountId?.split("@eip155")?.[0].toLowerCase() === recoveredAddress;
|
|
397
|
+
});
|
|
398
|
+
}, "checkSignatureAgainstSigner");
|
|
399
|
+
for (const signature2 of signatures) {
|
|
400
|
+
const verificationMethod = checkSignatureAgainstSigner(signature2);
|
|
401
|
+
if (verificationMethod) return verificationMethod;
|
|
402
|
+
}
|
|
403
|
+
throw new Error("invalid_signature: Signature invalid for JWT");
|
|
404
|
+
}
|
|
405
|
+
__name(verifyRecoverableES256K, "verifyRecoverableES256K");
|
|
406
|
+
function verifyEd25519(data, signature, authenticators) {
|
|
407
|
+
const clear = stringToBytes(data);
|
|
408
|
+
const signatureBytes = base64ToBytes(signature);
|
|
409
|
+
const signer = authenticators.find((a) => {
|
|
410
|
+
const { keyBytes, keyType } = extractPublicKeyBytes(a);
|
|
411
|
+
if (keyType === "Ed25519") {
|
|
412
|
+
return import_ed255192.ed25519.verify(signatureBytes, clear, keyBytes);
|
|
413
|
+
} else {
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
if (!signer) throw new Error("invalid_signature: Signature invalid for JWT");
|
|
418
|
+
return signer;
|
|
419
|
+
}
|
|
420
|
+
__name(verifyEd25519, "verifyEd25519");
|
|
421
|
+
var algorithms2 = {
|
|
422
|
+
ES256: verifyES256,
|
|
423
|
+
ES256K: verifyES256K,
|
|
424
|
+
// This is a non-standard algorithm but retained for backwards compatibility
|
|
425
|
+
// see https://github.com/decentralized-identity/did-jwt/issues/146
|
|
426
|
+
"ES256K-R": verifyRecoverableES256K,
|
|
427
|
+
// This is actually incorrect but retained for backwards compatibility
|
|
428
|
+
// see https://github.com/decentralized-identity/did-jwt/issues/130
|
|
429
|
+
Ed25519: verifyEd25519,
|
|
430
|
+
EdDSA: verifyEd25519
|
|
431
|
+
};
|
|
432
|
+
function VerifierAlgorithm(alg) {
|
|
433
|
+
const impl = algorithms2[alg];
|
|
434
|
+
if (!impl) throw new Error(`not_supported: Unsupported algorithm ${alg}`);
|
|
435
|
+
return impl;
|
|
436
|
+
}
|
|
437
|
+
__name(VerifierAlgorithm, "VerifierAlgorithm");
|
|
438
|
+
VerifierAlgorithm.toSignatureObject = toSignatureObject;
|
|
439
|
+
|
|
440
|
+
// src/did-jwt/JWT.ts
|
|
441
|
+
var import_did_jwt2 = require("did-jwt");
|
|
442
|
+
var SELF_ISSUED_V2 = "https://self-issued.me/v2";
|
|
443
|
+
var SELF_ISSUED_V2_VC_INTEROP = "https://self-issued.me/v2/openid-vc";
|
|
444
|
+
var SELF_ISSUED_V0_1 = "https://self-issued.me";
|
|
445
|
+
|
|
446
|
+
// src/agent/CredentialProviderVcdm2SdJwt.ts
|
|
447
|
+
var import_ssi_sdk4 = require("@sphereon/ssi-sdk.sd-jwt");
|
|
448
|
+
var debug = (0, import_debug.default)("sphereon:ssi-sdk:credential-vcdm2-sdjwt");
|
|
449
|
+
var CredentialProviderVcdm2SdJwt = class {
|
|
450
|
+
static {
|
|
451
|
+
__name(this, "CredentialProviderVcdm2SdJwt");
|
|
452
|
+
}
|
|
453
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.matchKeyForType} */
|
|
454
|
+
matchKeyForType(key) {
|
|
455
|
+
return this.matchKeyForJWT(key);
|
|
456
|
+
}
|
|
457
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.getTypeProofFormat} */
|
|
458
|
+
getTypeProofFormat() {
|
|
459
|
+
return "vc+sd-jwt";
|
|
460
|
+
}
|
|
461
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.canIssueCredentialType} */
|
|
462
|
+
canIssueCredentialType(args) {
|
|
463
|
+
const format = args.proofFormat.toLowerCase();
|
|
464
|
+
return format === "vc+sd-jwt" || format === "vcdm2_sdjwt";
|
|
465
|
+
}
|
|
466
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.canVerifyDocumentType */
|
|
467
|
+
canVerifyDocumentType(args) {
|
|
468
|
+
const { document } = args;
|
|
469
|
+
const jwt = typeof document === "string" ? document : document?.proof?.jwt;
|
|
470
|
+
if (!jwt) {
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
const { payload } = (0, import_did_jwt3.decodeJWT)(jwt.split("~")[0]);
|
|
474
|
+
return (0, import_ssi_types.isVcdm2Credential)(payload);
|
|
475
|
+
}
|
|
476
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.createVerifiableCredential} */
|
|
477
|
+
async createVerifiableCredential(args, context) {
|
|
478
|
+
const { keyRef } = args;
|
|
479
|
+
const agent = assertContext(context).agent;
|
|
480
|
+
const { credential, issuer } = (0, import_ssi_sdk3.preProcessCredentialPayload)(args);
|
|
481
|
+
if (!(0, import_ssi_types.isVcdm2Credential)(credential)) {
|
|
482
|
+
return Promise.reject(new Error("invalid_argument: credential must be a VCDM2 credential. Context: " + credential["@context"]));
|
|
483
|
+
} else if (!(0, import_ssi_sdk.contextHasPlugin)(context, "createSdJwtVc")) {
|
|
484
|
+
return Promise.reject(new Error("invalid_argument: SD-JWT plugin not available. Please install @sphereon/ssi-sdk.sd-jwt and configure agent for VCDM2 SD-JWT"));
|
|
485
|
+
}
|
|
486
|
+
let identifier;
|
|
487
|
+
try {
|
|
488
|
+
identifier = await agent.didManagerGet({
|
|
489
|
+
did: issuer
|
|
490
|
+
});
|
|
491
|
+
} catch (e) {
|
|
492
|
+
return Promise.reject(new Error(`invalid_argument: ${credential.issuer} must be a DID managed by this agent. ${e}`));
|
|
493
|
+
}
|
|
494
|
+
const managedIdentifier = await agent.identifierManagedGetByDid({
|
|
495
|
+
identifier: identifier.did,
|
|
496
|
+
kmsKeyRef: keyRef
|
|
497
|
+
});
|
|
498
|
+
const key = await (0, import_ssi_sdk3.pickSigningKey)({
|
|
499
|
+
identifier,
|
|
500
|
+
kmsKeyRef: keyRef
|
|
501
|
+
}, context);
|
|
502
|
+
const alg = await (0, import_ssi_sdk_ext2.signatureAlgorithmFromKey)({
|
|
503
|
+
key
|
|
504
|
+
});
|
|
505
|
+
debug("Signing VC with", identifier.did, alg);
|
|
506
|
+
credential.issuer = {
|
|
507
|
+
id: identifier.did
|
|
508
|
+
};
|
|
509
|
+
const result = await context.agent.createSdJwtVc({
|
|
510
|
+
type: "vc+sd-jwt",
|
|
511
|
+
credentialPayload: credential,
|
|
512
|
+
resolution: managedIdentifier,
|
|
513
|
+
disclosureFrame: args.opts?.disclosureFrame
|
|
514
|
+
});
|
|
515
|
+
const jwt = result.credential.split("~")[0];
|
|
516
|
+
const normalized = (0, import_did_jwt_vc.normalizeCredential)(jwt);
|
|
517
|
+
normalized.proof.jwt = result.credential;
|
|
518
|
+
return normalized;
|
|
519
|
+
}
|
|
520
|
+
/** {@inheritdoc ICredentialVerifier.verifyCredential} */
|
|
521
|
+
async verifyCredential(args, context) {
|
|
522
|
+
let {
|
|
523
|
+
credential,
|
|
524
|
+
policies
|
|
525
|
+
/*...otherOptions*/
|
|
526
|
+
} = args;
|
|
527
|
+
const uniform = import_ssi_types.CredentialMapper.toUniformCredential(credential);
|
|
528
|
+
if (!(0, import_ssi_types.isVcdm2Credential)(uniform)) {
|
|
529
|
+
return Promise.reject(new Error("invalid_argument: credential must be a VCDM2 credential. Context: " + uniform["@context"]));
|
|
530
|
+
} else if (!(0, import_ssi_sdk.contextHasPlugin)(context, "createSdJwtVc")) {
|
|
531
|
+
return Promise.reject(new Error("invalid_argument: SD-JWT plugin not available. Please install @sphereon/ssi-sdk.sd-jwt and configure agent for VCDM2 SD-JWT"));
|
|
532
|
+
}
|
|
533
|
+
let verificationResult = {
|
|
534
|
+
verified: false
|
|
535
|
+
};
|
|
536
|
+
let jwt = typeof credential === "string" ? credential : (0, import_ssi_sdk2.asArray)(uniform.proof)?.[0]?.jwt;
|
|
537
|
+
if (!jwt) {
|
|
538
|
+
return Promise.reject(new Error("invalid_argument: credential must be a VCDM2 credential in JOSE format (string)"));
|
|
539
|
+
}
|
|
540
|
+
try {
|
|
541
|
+
const result = await context.agent.verifySdJwtVc({
|
|
542
|
+
credential: jwt
|
|
543
|
+
});
|
|
544
|
+
if (result.payload) {
|
|
545
|
+
verificationResult = {
|
|
546
|
+
verified: true,
|
|
547
|
+
results: [
|
|
548
|
+
{
|
|
549
|
+
credential,
|
|
550
|
+
verified: true,
|
|
551
|
+
log: [
|
|
552
|
+
{
|
|
553
|
+
id: "valid_signature",
|
|
554
|
+
valid: true
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
id: "issuer_did_resolves",
|
|
558
|
+
valid: true
|
|
559
|
+
}
|
|
560
|
+
]
|
|
561
|
+
}
|
|
562
|
+
]
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
} catch (e) {
|
|
566
|
+
verificationResult = {
|
|
567
|
+
verified: false,
|
|
568
|
+
error: {
|
|
569
|
+
message: e.message,
|
|
570
|
+
errorCode: e.name
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
policies = {
|
|
575
|
+
...policies,
|
|
576
|
+
nbf: policies?.nbf ?? policies?.issuanceDate ?? policies?.validFrom,
|
|
577
|
+
iat: policies?.iat ?? policies?.issuanceDate ?? policies?.validFrom,
|
|
578
|
+
exp: policies?.exp ?? policies?.expirationDate ?? policies?.validUntil,
|
|
579
|
+
aud: policies?.aud ?? policies?.audience
|
|
580
|
+
};
|
|
581
|
+
verificationResult = await verifierSignature({
|
|
582
|
+
jwt: jwt.split("~")[0],
|
|
583
|
+
policies
|
|
584
|
+
}, context);
|
|
585
|
+
return verificationResult;
|
|
586
|
+
}
|
|
587
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.createVerifiablePresentation} */
|
|
588
|
+
async createVerifiablePresentation(args, context) {
|
|
589
|
+
const { presentation, holder } = (0, import_ssi_sdk3.preProcessPresentation)(args);
|
|
590
|
+
let {
|
|
591
|
+
domain,
|
|
592
|
+
challenge,
|
|
593
|
+
keyRef
|
|
594
|
+
/* removeOriginalFields, keyRef, now, ...otherOptions*/
|
|
595
|
+
} = args;
|
|
596
|
+
const agent = assertContext(context).agent;
|
|
597
|
+
const managedIdentifier = await agent.identifierManagedGetByDid({
|
|
598
|
+
identifier: holder,
|
|
599
|
+
kmsKeyRef: keyRef
|
|
600
|
+
});
|
|
601
|
+
const identifier = managedIdentifier.identifier;
|
|
602
|
+
const key = await (0, import_ssi_sdk3.pickSigningKey)({
|
|
603
|
+
identifier: managedIdentifier.identifier,
|
|
604
|
+
kmsKeyRef: managedIdentifier.kmsKeyRef
|
|
605
|
+
}, context);
|
|
606
|
+
debug("Signing VC with", identifier.did);
|
|
607
|
+
let alg = "ES256";
|
|
608
|
+
if (key.type === "Ed25519") {
|
|
609
|
+
alg = "EdDSA";
|
|
610
|
+
} else if (key.type === "Secp256k1") {
|
|
611
|
+
alg = "ES256K";
|
|
612
|
+
}
|
|
613
|
+
const header = {
|
|
614
|
+
kid: key.meta.verificationMethod.id ?? key.kid,
|
|
615
|
+
alg,
|
|
616
|
+
typ: "vp+jwt",
|
|
617
|
+
cty: "vp"
|
|
618
|
+
};
|
|
619
|
+
const payload = {
|
|
620
|
+
...presentation,
|
|
621
|
+
...domain && {
|
|
622
|
+
aud: domain
|
|
623
|
+
},
|
|
624
|
+
...challenge && {
|
|
625
|
+
nonce: challenge
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
const jwt = await agent.jwtCreateJwsCompactSignature({
|
|
629
|
+
mode: "did",
|
|
630
|
+
issuer: managedIdentifier,
|
|
631
|
+
payload,
|
|
632
|
+
protectedHeader: header,
|
|
633
|
+
clientIdScheme: "did"
|
|
634
|
+
});
|
|
635
|
+
debug(jwt);
|
|
636
|
+
return (0, import_did_jwt_vc.normalizePresentation)(jwt.jwt);
|
|
637
|
+
}
|
|
638
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.verifyPresentation} */
|
|
639
|
+
async verifyPresentation(args, context) {
|
|
640
|
+
let { presentation, domain, challenge, fetchRemoteContexts, policies, ...otherOptions } = args;
|
|
641
|
+
let jwt;
|
|
642
|
+
if (typeof presentation === "string") {
|
|
643
|
+
jwt = presentation;
|
|
644
|
+
} else {
|
|
645
|
+
jwt = (0, import_ssi_sdk2.asArray)(presentation.proof)[0].jwt;
|
|
646
|
+
}
|
|
647
|
+
const resolver = {
|
|
648
|
+
resolve: /* @__PURE__ */ __name((didUrl) => context.agent.resolveDid({
|
|
649
|
+
didUrl,
|
|
650
|
+
options: otherOptions?.resolutionOptions
|
|
651
|
+
}), "resolve")
|
|
652
|
+
};
|
|
653
|
+
let audience = domain;
|
|
654
|
+
if (!audience) {
|
|
655
|
+
const { payload } = await (0, import_did_jwt3.decodeJWT)(jwt);
|
|
656
|
+
if (payload.aud) {
|
|
657
|
+
const intendedAudience = (0, import_ssi_sdk2.asArray)(payload.aud);
|
|
658
|
+
const managedDids = await context.agent.didManagerFind();
|
|
659
|
+
const filtered = managedDids.filter((identifier) => intendedAudience.includes(identifier.did));
|
|
660
|
+
if (filtered.length > 0) {
|
|
661
|
+
audience = filtered[0].did;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
let message, errorCode;
|
|
666
|
+
try {
|
|
667
|
+
const result = await (0, import_did_jwt_vc.verifyPresentation)(jwt, resolver, {
|
|
668
|
+
challenge,
|
|
669
|
+
domain,
|
|
670
|
+
audience,
|
|
671
|
+
policies: {
|
|
672
|
+
...policies,
|
|
673
|
+
nbf: policies?.nbf ?? policies?.issuanceDate,
|
|
674
|
+
iat: policies?.iat ?? policies?.issuanceDate,
|
|
675
|
+
exp: policies?.exp ?? policies?.expirationDate,
|
|
676
|
+
aud: policies?.aud ?? policies?.audience
|
|
677
|
+
},
|
|
678
|
+
...otherOptions
|
|
679
|
+
});
|
|
680
|
+
if (result) {
|
|
681
|
+
return {
|
|
682
|
+
verified: true,
|
|
683
|
+
results: [
|
|
684
|
+
{
|
|
685
|
+
verified: true,
|
|
686
|
+
presentation: result.verifiablePresentation,
|
|
687
|
+
log: [
|
|
688
|
+
{
|
|
689
|
+
id: "valid_signature",
|
|
690
|
+
valid: true
|
|
691
|
+
}
|
|
692
|
+
]
|
|
693
|
+
}
|
|
694
|
+
]
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
} catch (e) {
|
|
698
|
+
message = e.message;
|
|
699
|
+
errorCode = e.errorCode;
|
|
700
|
+
}
|
|
701
|
+
return {
|
|
702
|
+
verified: false,
|
|
703
|
+
error: {
|
|
704
|
+
message,
|
|
705
|
+
errorCode: errorCode ? errorCode : message?.split(":")[0]
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Checks if a key is suitable for signing JWT payloads.
|
|
711
|
+
* @param key - the key to check
|
|
712
|
+
* @param context - the Veramo agent context, unused here
|
|
713
|
+
*
|
|
714
|
+
* @beta
|
|
715
|
+
*/
|
|
716
|
+
matchKeyForJWT(key) {
|
|
717
|
+
switch (key.type) {
|
|
718
|
+
case "Ed25519":
|
|
719
|
+
case "Secp256r1":
|
|
720
|
+
return true;
|
|
721
|
+
case "Secp256k1":
|
|
722
|
+
return (0, import_ssi_sdk2.intersect)(key.meta?.algorithms ?? [], [
|
|
723
|
+
"ES256K",
|
|
724
|
+
"ES256K-R"
|
|
725
|
+
]).length > 0;
|
|
726
|
+
default:
|
|
727
|
+
return false;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
wrapSigner(context, key, algorithm) {
|
|
731
|
+
return async (data) => {
|
|
732
|
+
const result = await context.agent.keyManagerSign({
|
|
733
|
+
keyRef: key.kid,
|
|
734
|
+
data,
|
|
735
|
+
algorithm
|
|
736
|
+
});
|
|
737
|
+
return result;
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
async function verifierSignature({ jwt, policies }, verifierContext) {
|
|
742
|
+
let credIssuer = void 0;
|
|
743
|
+
const context = assertContext(verifierContext);
|
|
744
|
+
const agent = context.agent;
|
|
745
|
+
const {
|
|
746
|
+
payload,
|
|
747
|
+
header
|
|
748
|
+
/*signature, data*/
|
|
749
|
+
} = (0, import_did_jwt3.decodeJWT)(jwt);
|
|
750
|
+
if (!payload.issuer) {
|
|
751
|
+
throw new Error(`${import_did_jwt3.JWT_ERROR.INVALID_JWT}: JWT iss or client_id are required`);
|
|
752
|
+
}
|
|
753
|
+
const issuer = (0, import_ssi_sdk4.getIssuerFromSdJwt)(payload);
|
|
754
|
+
if (issuer === SELF_ISSUED_V2 || issuer === SELF_ISSUED_V2_VC_INTEROP) {
|
|
755
|
+
if (!payload.credentialSubject.id) {
|
|
756
|
+
throw new Error(`${import_did_jwt3.JWT_ERROR.INVALID_JWT}: JWT credentialSubject.id is required`);
|
|
757
|
+
}
|
|
758
|
+
if (typeof payload.sub_jwk === "undefined") {
|
|
759
|
+
credIssuer = payload.sub;
|
|
760
|
+
} else {
|
|
761
|
+
credIssuer = (header.kid || "").split("#")[0];
|
|
762
|
+
}
|
|
763
|
+
} else if (issuer === SELF_ISSUED_V0_1) {
|
|
764
|
+
if (!payload.did) {
|
|
765
|
+
throw new Error(`${import_did_jwt3.JWT_ERROR.INVALID_JWT}: JWT did is required`);
|
|
766
|
+
}
|
|
767
|
+
credIssuer = payload.did;
|
|
768
|
+
} else if (!issuer && payload.scope === "openid" && payload.redirect_uri) {
|
|
769
|
+
if (!payload.client_id) {
|
|
770
|
+
throw new Error(`${import_did_jwt3.JWT_ERROR.INVALID_JWT}: JWT client_id is required`);
|
|
771
|
+
}
|
|
772
|
+
credIssuer = payload.client_id;
|
|
773
|
+
} else if (issuer?.indexOf("did:") === 0) {
|
|
774
|
+
credIssuer = issuer;
|
|
775
|
+
} else if (header.kid?.indexOf("did:") === 0) {
|
|
776
|
+
credIssuer = (header.kid || "").split("#")[0];
|
|
777
|
+
} else if (typeof payload.issuer === "string") {
|
|
778
|
+
credIssuer = payload.issuer;
|
|
779
|
+
} else if (payload.issuer?.id) {
|
|
780
|
+
credIssuer = payload.issuer.id;
|
|
781
|
+
}
|
|
782
|
+
if (!credIssuer) {
|
|
783
|
+
throw new Error(`${import_did_jwt3.JWT_ERROR.INVALID_JWT}: No DID has been found in the JWT`);
|
|
784
|
+
}
|
|
785
|
+
let resolution = void 0;
|
|
786
|
+
try {
|
|
787
|
+
resolution = await agent.identifierExternalResolve({
|
|
788
|
+
identifier: credIssuer
|
|
789
|
+
});
|
|
790
|
+
} catch (e) {
|
|
791
|
+
}
|
|
792
|
+
const credential = import_ssi_types.CredentialMapper.toUniformCredential(jwt);
|
|
793
|
+
const validFromError = policies.nbf !== false && policies.iat !== false && "validFrom" in credential && !!credential.validFrom && Date.parse(credential.validFrom) > (/* @__PURE__ */ new Date()).getTime();
|
|
794
|
+
const expired = policies.exp !== false && "validUntil" in credential && !!credential.validUntil && Date.parse(credential.validUntil) < (/* @__PURE__ */ new Date()).getTime();
|
|
795
|
+
const didOpts = {
|
|
796
|
+
method: "did",
|
|
797
|
+
identifier: credIssuer
|
|
798
|
+
};
|
|
799
|
+
const jwtResult = await agent.jwtVerifyJwsSignature({
|
|
800
|
+
jws: jwt,
|
|
801
|
+
// @ts-ignore
|
|
802
|
+
jwk: resolution?.jwks[0].jwk,
|
|
803
|
+
opts: {
|
|
804
|
+
...(0, import_ssi_sdk_ext.isDidIdentifier)(credIssuer) && {
|
|
805
|
+
did: didOpts
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
});
|
|
809
|
+
const error = jwtResult.error || expired || !resolution;
|
|
810
|
+
const errorMessage = expired ? "Credential is expired" : validFromError ? "Credential is not valid yet" : !resolution ? `Issuer ${credIssuer} could not be resolved` : jwtResult.message;
|
|
811
|
+
if (error) {
|
|
812
|
+
const log2 = [
|
|
813
|
+
{
|
|
814
|
+
id: "valid_signature",
|
|
815
|
+
valid: !jwtResult.error
|
|
816
|
+
},
|
|
817
|
+
{
|
|
818
|
+
id: "issuer_did_resolves",
|
|
819
|
+
valid: resolution != void 0
|
|
820
|
+
},
|
|
821
|
+
{
|
|
822
|
+
id: "validFrom",
|
|
823
|
+
valid: policies.nbf !== false && !validFromError
|
|
824
|
+
},
|
|
825
|
+
{
|
|
826
|
+
id: "expiration",
|
|
827
|
+
valid: policies.exp !== false && !expired
|
|
828
|
+
}
|
|
829
|
+
];
|
|
830
|
+
return {
|
|
831
|
+
verified: false,
|
|
832
|
+
error: {
|
|
833
|
+
message: errorMessage,
|
|
834
|
+
errorCode: jwtResult.name
|
|
835
|
+
},
|
|
836
|
+
log: log2,
|
|
837
|
+
results: [
|
|
838
|
+
{
|
|
839
|
+
verified: false,
|
|
840
|
+
credential: jwt,
|
|
841
|
+
log: log2,
|
|
842
|
+
error: {
|
|
843
|
+
message: errorMessage,
|
|
844
|
+
errorCode: jwtResult.name
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
],
|
|
848
|
+
payload,
|
|
849
|
+
didResolutionResult: resolution,
|
|
850
|
+
jwt
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
const log = [
|
|
854
|
+
{
|
|
855
|
+
id: "valid_signature",
|
|
856
|
+
valid: true
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
id: "issuer_did_resolves",
|
|
860
|
+
valid: true
|
|
861
|
+
},
|
|
862
|
+
{
|
|
863
|
+
id: "validFrom",
|
|
864
|
+
valid: true
|
|
865
|
+
},
|
|
866
|
+
{
|
|
867
|
+
id: "expiration",
|
|
868
|
+
valid: true
|
|
869
|
+
}
|
|
870
|
+
];
|
|
871
|
+
return {
|
|
872
|
+
verified: true,
|
|
873
|
+
log,
|
|
874
|
+
results: [
|
|
875
|
+
{
|
|
876
|
+
verified: true,
|
|
877
|
+
credential,
|
|
878
|
+
log
|
|
879
|
+
}
|
|
880
|
+
],
|
|
881
|
+
payload,
|
|
882
|
+
didResolutionResult: resolution,
|
|
883
|
+
jwt
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
__name(verifierSignature, "verifierSignature");
|
|
887
|
+
function assertContext(context) {
|
|
888
|
+
if (!(0, import_ssi_sdk.contextHasPlugin)(context, "jwtPrepareJws")) {
|
|
889
|
+
throw Error("JwtService plugin not found, which is required for JWT signing in the VCDM2 SD-JWT credential provider. Please add the JwtService plugin to your agent configuration.");
|
|
890
|
+
} else if (!(0, import_ssi_sdk.contextHasPlugin)(context, "identifierManagedGet")) {
|
|
891
|
+
throw Error("Identifier resolution plugin not found, which is required for JWT signing in the VCDM2 SD-JWT credential provider. Please add the JwtService plugin to your agent configuration.");
|
|
892
|
+
}
|
|
893
|
+
return context;
|
|
894
|
+
}
|
|
895
|
+
__name(assertContext, "assertContext");
|
|
896
|
+
//# sourceMappingURL=index.cjs.map
|