@originator-profile/verify 0.5.3 → 0.6.0-beta.1

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/dist/index.cjs DELETED
@@ -1,1245 +0,0 @@
1
- 'use strict';
2
-
3
- var securingMechanism = require('@originator-profile/securing-mechanism');
4
- var sign = require('@originator-profile/sign');
5
- var cryptography = require('@originator-profile/cryptography');
6
- var model = require('@originator-profile/model');
7
- var zod = require('zod');
8
-
9
- class CaInvalid extends Error {
10
- constructor(message, result) {
11
- super(message);
12
- this.result = result;
13
- }
14
- static get code() {
15
- return "ERR_CONTENT_ATTESTATION_INVALID";
16
- }
17
- code = CaInvalid.code;
18
- }
19
- class CaVerifyFailed extends Error {
20
- constructor(message, result) {
21
- super(message);
22
- this.result = result;
23
- }
24
- static get code() {
25
- return "ERR_CONTENT_ATTESTATION_VERIFY_FAILED";
26
- }
27
- code = CaVerifyFailed.code;
28
- }
29
-
30
- const supportedHashAlgorithms = {
31
- /** SHA-256 hash algorithm */
32
- sha256: "SHA-256",
33
- /** SHA-384 hash algorithm */
34
- sha384: "SHA-384",
35
- /** SHA-512 hash algorithm */
36
- sha512: "SHA-512"
37
- };
38
- function getPrioritizedHashAlgorithm(a, b) {
39
- if (a === b) return "";
40
- if (!(a in supportedHashAlgorithms)) {
41
- return b in supportedHashAlgorithms ? b : "";
42
- }
43
- if (!(b in supportedHashAlgorithms)) {
44
- return a in supportedHashAlgorithms ? a : "";
45
- }
46
- return a < b ? b : a;
47
- }
48
- const IntegrityMetadataRegex = /^(?<alg>sha256|sha384|sha512)-(?<val>(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?)(?:[?](?<opt>[\x21-\x7e]*))?$/;
49
- const SeparatorRegex = /[^\x21-\x7e]+/;
50
- class IntegrityMetadata {
51
- /** Hash algorithm */
52
- alg;
53
- /** The base64-encoded hash value of the resource */
54
- val;
55
- /** Optional additional attributes */
56
- opt;
57
- /**
58
- * Creates an instance of `IntegrityMetadata` from a given object or string.
59
- * @param integrity The integrity metadata input, which can be a string or object.
60
- * @example
61
- * ```js
62
- * new IntegrityMetadata("sha256-MV9b23bQeMQ7isAGTkoBZGErH853yGk0W/yUx1iU7dM=")
63
- * ```
64
- *
65
- * or
66
- *
67
- * ```js
68
- * new IntegrityMetadata({
69
- * alg: "sha256",
70
- * val: "MV9b23bQeMQ7isAGTkoBZGErH853yGk0W/yUx1iU7dM=",
71
- * })
72
- * ```
73
- */
74
- constructor(integrity) {
75
- const integrityString = typeof integrity === "object" && integrity !== null ? IntegrityMetadata.stringify(integrity) : String(integrity ?? "").trim();
76
- const {
77
- alg = "",
78
- val = "",
79
- opt
80
- } = IntegrityMetadataRegex.exec(integrityString)?.groups ?? {};
81
- Object.assign(this, {
82
- alg,
83
- val,
84
- opt: opt?.split("?") ?? []
85
- });
86
- }
87
- /**
88
- * Compares the current integrity metadata with another object or string.
89
- * @param integrity The integrity metadata to compare with.
90
- * @returns `true` if the integrity metadata matches, `false` otherwise.
91
- * @example
92
- * ```js
93
- * integrityMetadata.match("sha256-MV9b23bQeMQ7isAGTkoBZGErH853yGk0W/yUx1iU7dM=")
94
- * ```
95
- *
96
- * or
97
- *
98
- * ```js
99
- * integrityMetadata.match({
100
- * alg: "sha256",
101
- * val: "MV9b23bQeMQ7isAGTkoBZGErH853yGk0W/yUx1iU7dM=",
102
- * })
103
- * ```
104
- */
105
- match(integrity) {
106
- const { alg, val } = new IntegrityMetadata(integrity);
107
- if (!alg) return false;
108
- if (!val) return false;
109
- if (!(alg in supportedHashAlgorithms)) return false;
110
- return alg === this.alg && val === this.val;
111
- }
112
- /**
113
- * Converts the integrity metadata into a string representation.
114
- * @returns The string representation of the integrity metadata.
115
- */
116
- toString() {
117
- return IntegrityMetadata.stringify(this);
118
- }
119
- /**
120
- * Converts the integrity metadata into a JSON string.
121
- * @returns The JSON string representation of the integrity metadata.
122
- */
123
- toJSON() {
124
- return this.toString();
125
- }
126
- /**
127
- * Static method to stringify an integrity metadata object.
128
- * @param integrity The integrity metadata object to stringify.
129
- * @returns The stringified integrity metadata.
130
- * @example
131
- * ```js
132
- * IntegrityMetadata.stringify({
133
- * alg: "sha256",
134
- * val: "MV9b23bQeMQ7isAGTkoBZGErH853yGk0W/yUx1iU7dM=",
135
- * }) // "sha256-MV9b23bQeMQ7isAGTkoBZGErH853yGk0W/yUx1iU7dM="
136
- * ```
137
- */
138
- static stringify({ alg, val, opt = [] }) {
139
- if (!alg) return "";
140
- if (!val) return "";
141
- if (!(alg in supportedHashAlgorithms)) return "";
142
- return `${alg}-${[val, ...opt].join("?")}`;
143
- }
144
- }
145
- async function createIntegrityMetadata(hashAlgorithm, data, opt = []) {
146
- const alg = hashAlgorithm.toLowerCase();
147
- if (!(alg in supportedHashAlgorithms)) {
148
- return new IntegrityMetadata("");
149
- }
150
- const hashAlgorithmIdentifier = supportedHashAlgorithms[alg];
151
- const arrayBuffer = await crypto.subtle.digest(hashAlgorithmIdentifier, data);
152
- const val = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));
153
- const integrity = IntegrityMetadata.stringify({ alg, val, opt });
154
- return new IntegrityMetadata(integrity);
155
- }
156
- class IntegrityMetadataSet {
157
- #set;
158
- #getPrioritizedHashAlgorithm = getPrioritizedHashAlgorithm;
159
- /**
160
- * Create an instance of `IntegrityMetadataSet` from integrity metadata or an array of integrity
161
- * metadata.
162
- * @param integrity The integrity metadata or an array of integrity metadata.
163
- * @param options Optional configuration options for hash algorithm prioritization.
164
- * @example
165
- * ```js
166
- * new IntegrityMetadataSet([
167
- * "sha256-MV9b23bQeMQ7isAGTkoBZGErH853yGk0W/yUx1iU7dM=",
168
- * "sha384-VbxVaw0v4Pzlgrpf4Huq//A1ZTY4x6wNVJTCpkwL6hzFczHHwSpFzbyn9MNKCJ7r",
169
- * "sha512-wVJ82JPBJHc9gRkRlwyP5uhX1t9dySJr2KFgYUwM2WOk3eorlLt9NgIe+dhl1c6ilKgt1JoLsmn1H256V/eUIQ==",
170
- * ])
171
- * ```
172
- *
173
- * or
174
- *
175
- * ```js
176
- * new IntegrityMetadataSet(`
177
- * sha256-MV9b23bQeMQ7isAGTkoBZGErH853yGk0W/yUx1iU7dM=
178
- * sha384-VbxVaw0v4Pzlgrpf4Huq//A1ZTY4x6wNVJTCpkwL6hzFczHHwSpFzbyn9MNKCJ7r
179
- * sha512-wVJ82JPBJHc9gRkRlwyP5uhX1t9dySJr2KFgYUwM2WOk3eorlLt9NgIe+dhl1c6ilKgt1JoLsmn1H256V/eUIQ==
180
- * `)
181
- * ```
182
- */
183
- constructor(integrity, {
184
- getPrioritizedHashAlgorithm: _getPrioritizedHashAlgorithm = getPrioritizedHashAlgorithm
185
- } = {}) {
186
- this.#set = [integrity].flat().flatMap(
187
- (integrity2) => {
188
- if (typeof integrity2 === "string") {
189
- return integrity2.split(SeparatorRegex);
190
- }
191
- return [integrity2];
192
- }
193
- ).map((integrity2) => new IntegrityMetadata(integrity2)).filter((integrityMetadata) => integrityMetadata.toString() !== "");
194
- this.#getPrioritizedHashAlgorithm = _getPrioritizedHashAlgorithm;
195
- }
196
- /**
197
- * Enables iteration over the set of integrity metadata.
198
- * @returns A generator that yields each IntegrityMetadata object.
199
- * @example
200
- * ```js
201
- * [...integrityMetadataSet]
202
- * ```
203
- */
204
- *[Symbol.iterator]() {
205
- for (const integrityMetadata of this.#set) {
206
- yield new IntegrityMetadata(integrityMetadata);
207
- }
208
- }
209
- /**
210
- * The number of integrity metadata entries in the set.
211
- */
212
- get size() {
213
- return this.#set.length;
214
- }
215
- /**
216
- * The strongest (most secure) integrity metadata from the set.
217
- * @see {@link https://www.w3.org/TR/SRI/#get-the-strongest-metadata-from-set}
218
- */
219
- get strongest() {
220
- let strongest = new IntegrityMetadataSet([]);
221
- for (const integrityMetadata of this.#set) {
222
- const [{ alg } = new IntegrityMetadata("")] = strongest;
223
- const prioritizedHashAlgorithm = this.#getPrioritizedHashAlgorithm(
224
- alg,
225
- integrityMetadata.alg
226
- );
227
- switch (prioritizedHashAlgorithm) {
228
- case "":
229
- strongest = new IntegrityMetadataSet([
230
- ...strongest,
231
- integrityMetadata
232
- ]);
233
- break;
234
- case integrityMetadata.alg:
235
- strongest = new IntegrityMetadataSet(integrityMetadata);
236
- break;
237
- }
238
- }
239
- return strongest;
240
- }
241
- /**
242
- * Returns an array of the strongest supported hash algorithms in the set.
243
- */
244
- get strongestHashAlgorithms() {
245
- const strongestHashAlgorithms = [...this.strongest].map(({ alg }) => alg).filter(Boolean);
246
- return [...new Set(strongestHashAlgorithms)];
247
- }
248
- /**
249
- * Checks if a given integrity metadata object or string matches any in the set.
250
- * @param integrity The integrity metadata to match.
251
- * @returns `true` if the integrity metadata matches, `false` otherwise.
252
- * @example
253
- * ```js
254
- * integrityMetadataSet.match("sha256-MV9b23bQeMQ7isAGTkoBZGErH853yGk0W/yUx1iU7dM=")
255
- * ```
256
- *
257
- * or
258
- *
259
- * ```js
260
- * integrityMetadataSet.match({
261
- * alg: "sha256",
262
- * val: "MV9b23bQeMQ7isAGTkoBZGErH853yGk0W/yUx1iU7dM=",
263
- * })
264
- * ```
265
- */
266
- match(integrity) {
267
- return this.#set.some(
268
- (integrityMetadata) => integrityMetadata.match(integrity)
269
- );
270
- }
271
- /**
272
- * Joins the integrity metadata in the set into a single string, separated by the specified
273
- * separator.
274
- * @param separator The separator to use (default is a space).
275
- * @returns The joined string representation of the set.
276
- */
277
- join(separator = " ") {
278
- return this.#set.map(String).join(separator);
279
- }
280
- /**
281
- * Converts the set of integrity metadata to a string representation.
282
- * @returns The string representation of the set.
283
- */
284
- toString() {
285
- return this.join();
286
- }
287
- /**
288
- * Converts the set of integrity metadata to a JSON string.
289
- * @returns The JSON string representation of the set.
290
- */
291
- toJSON() {
292
- return this.toString();
293
- }
294
- }
295
- async function createIntegrityMetadataSet(hashAlgorithms, data, options = {
296
- getPrioritizedHashAlgorithm
297
- }) {
298
- const set = await Promise.all(
299
- [hashAlgorithms].flat().map((alg) => createIntegrityMetadata(alg, data))
300
- );
301
- return new IntegrityMetadataSet(set, options);
302
- }
303
-
304
- const WARN_SUFFIX = `This will become an error after 2027. See: https://docs.originator-profile.org/en/opb/context/#the-image-datatype`;
305
- async function verifyDigestSri(content, fetcher = fetch) {
306
- const integrity = new IntegrityMetadataSet(content.digestSRI);
307
- const alg = integrity.strongestHashAlgorithms.filter(Boolean);
308
- if (alg.length === 0) return false;
309
- try {
310
- const result = await sign.createDigestSri(alg[0], content, fetcher);
311
- return "digestSRI" in result && integrity.match(result.digestSRI);
312
- } catch (error) {
313
- console.error(
314
- "Failed to access content for digestSRI verification:",
315
- error
316
- );
317
- return false;
318
- }
319
- }
320
- async function verifyImageDigestSri(value, fetcher = fetch) {
321
- if (!value) return;
322
- if (!value.digestSRI) {
323
- console.warn(`digestSRI is missing. ${WARN_SUFFIX}`);
324
- return;
325
- }
326
- const valid = await verifyDigestSri(
327
- { id: value.id, digestSRI: value.digestSRI },
328
- fetcher
329
- );
330
- if (!valid) {
331
- console.warn(`digestSRI verification failed. ${WARN_SUFFIX}`);
332
- }
333
- }
334
-
335
- class IntegrityFetchFailed extends Error {
336
- static get code() {
337
- return "ERR_INTEGRITY_FETCH_FAILED";
338
- }
339
- code = IntegrityFetchFailed.code;
340
- ok = false;
341
- /** 取得結果 */
342
- result;
343
- constructor(message, result) {
344
- super(message);
345
- this.result = result;
346
- }
347
- }
348
- class IntegrityVerificationFailed extends Error {
349
- static get code() {
350
- return "ERR_INTEGRITY_VERIFICATION_FAILED";
351
- }
352
- code = IntegrityVerificationFailed.code;
353
- ok = false;
354
- /** 取得結果 */
355
- result;
356
- constructor(message, result) {
357
- super(message);
358
- this.result = result;
359
- }
360
- }
361
-
362
- class IntegrityVerifier {
363
- constructor(contentFetcher, elementSelector) {
364
- this.contentFetcher = contentFetcher;
365
- this.elementSelector = elementSelector;
366
- }
367
- async verify(content, document2) {
368
- const integrity = new IntegrityMetadataSet(content.integrity);
369
- const alg = integrity.strongestHashAlgorithms.filter(Boolean);
370
- if (alg.length === 0) return { valid: false, failedIntegrities: [] };
371
- const elements = this.elementSelector({ ...content, document: document2 });
372
- if (elements.length === 0) return { valid: false, failedIntegrities: [] };
373
- const responses = await this.contentFetcher(elements);
374
- const meta = await Promise.all(
375
- responses.map(async (res) => {
376
- const data = await res.arrayBuffer();
377
- return await createIntegrityMetadataSet(alg, data);
378
- })
379
- );
380
- const failedIntegrities = meta.filter((m) => [...m].every((m2) => !integrity.match(m2))).map((m) => m.toString());
381
- return { valid: failedIntegrities.length === 0, failedIntegrities };
382
- }
383
- }
384
- const TargetIntegrityAlgorithm = {
385
- HtmlTargetIntegrity: {
386
- contentFetcher: sign.fetchHtmlContent,
387
- elementSelector: sign.selectByCss
388
- },
389
- TextTargetIntegrity: {
390
- contentFetcher: sign.fetchTextContent,
391
- elementSelector: sign.selectByCss
392
- },
393
- VisibleTextTargetIntegrity: {
394
- contentFetcher: sign.fetchVisibleTextContent,
395
- elementSelector: sign.selectByCss
396
- },
397
- ExternalResourceTargetIntegrity: {
398
- contentFetcher: sign.fetchExternalResource,
399
- elementSelector: sign.selectByIntegrity
400
- }
401
- };
402
- async function verifyIntegrity(content, doc = document, fetcher = fetch) {
403
- const { contentFetcher, elementSelector } = TargetIntegrityAlgorithm[content.type];
404
- const integrityVerifier = new IntegrityVerifier(
405
- (content2) => contentFetcher(content2, fetcher),
406
- elementSelector
407
- );
408
- try {
409
- return await integrityVerifier.verify(content, doc);
410
- } catch (e) {
411
- if (e instanceof sign.FetchFailed) {
412
- return new IntegrityFetchFailed("Verify integrity failed", e.error);
413
- }
414
- return new IntegrityVerificationFailed("Verify integrity failed", e);
415
- }
416
- }
417
-
418
- function verifyAllowedOrigin(origin, allowedOrigins) {
419
- if (origin === "null") {
420
- return false;
421
- }
422
- return [allowedOrigins].flat().includes(origin);
423
- }
424
-
425
- async function importURLPatternPolyfill() {
426
- if (typeof URLPattern === "undefined") {
427
- await Promise.resolve().then(function () { return require('./index-D-j8gXz_.cjs'); });
428
- }
429
- }
430
- function ReplaceEncode(url) {
431
- return url.replace(/(%[0-9a-f]{2}?)+/g, function(match) {
432
- return match.toUpperCase();
433
- });
434
- }
435
- async function verifyAllowedUrl(url, allowedUrl) {
436
- await importURLPatternPolyfill();
437
- return [allowedUrl].flat().some((value) => {
438
- if (!value) {
439
- return false;
440
- }
441
- try {
442
- const pattern = new URLPattern(ReplaceEncode(value));
443
- return pattern.test(ReplaceEncode(url));
444
- } catch (e) {
445
- console.error(`Invalid URLPattern: ${value} (url: ${url})`);
446
- }
447
- return false;
448
- });
449
- }
450
-
451
- async function checkUrlAndOrigin(result, url) {
452
- if (result.doc.allowedUrl && result.doc.allowedOrigin) {
453
- return new CaInvalid("allowedUrl and allowedOrigin are exclusive", result);
454
- }
455
- if (result.doc.allowedOrigin) {
456
- console.warn(
457
- "[OP Warning] allowedOrigin is deprecated in Content Attestation and will be removed after September 2026. Please use allowedUrl instead. See: https://docs.originator-profile.org/"
458
- );
459
- }
460
- if (result.doc.allowedUrl && !await verifyAllowedUrl(url.toString(), result.doc.allowedUrl)) {
461
- return new CaVerifyFailed(
462
- `URL not allowed. Expected:${Array.isArray(result.doc.allowedUrl) ? result.doc.allowedUrl.join(", ") : result.doc.allowedUrl} Actual:${url}`,
463
- result
464
- );
465
- }
466
- if (result.doc.allowedOrigin && !verifyAllowedOrigin(url.origin, result.doc.allowedOrigin)) {
467
- return new CaVerifyFailed(
468
- `Origin not allowed. Expected:${Array.isArray(result.doc.allowedOrigin) ? result.doc.allowedOrigin.join(", ") : result.doc.allowedOrigin} Actual:${url.origin}`,
469
- result
470
- );
471
- }
472
- return result;
473
- }
474
- function checkIntegrityResults(integrityResults, urlResult) {
475
- const fetchFailedResults = integrityResults.filter(
476
- (r) => r.verifyResult instanceof Error && r.verifyResult.code === IntegrityFetchFailed.code
477
- );
478
- if (fetchFailedResults.length > 0) {
479
- const failedIntegritiesMessage = fetchFailedResults.map((result) => {
480
- return `target[${result.index}] Expected: ${result.expectedIntegrity}`;
481
- }).join(", ");
482
- return new CaVerifyFailed(
483
- `Content Attestation Target integrity fetch failed for element(s): ${failedIntegritiesMessage}`,
484
- urlResult
485
- );
486
- }
487
- const verificationFailedResults = integrityResults.filter(
488
- (r) => r.verifyResult instanceof Error && r.verifyResult.code === IntegrityVerificationFailed.code
489
- );
490
- if (verificationFailedResults.length > 0) {
491
- const failedIntegritiesMessage = verificationFailedResults.map((result) => {
492
- return `target[${result.index}] Expected: ${result.expectedIntegrity}`;
493
- }).join(", ");
494
- return new CaVerifyFailed(
495
- `Content Attestation Target integrity verification failed for element(s): ${failedIntegritiesMessage}`,
496
- urlResult
497
- );
498
- }
499
- }
500
- function CaVerifier(ca, keys, issuer, url, verifyIntegrity$1 = verifyIntegrity, validator) {
501
- const verifyCa = securingMechanism.JwtVcVerifier(keys, issuer, validator);
502
- return async () => {
503
- const result = await verifyCa(ca);
504
- if (result instanceof securingMechanism.VcValidateFailed) {
505
- return new CaInvalid("Content Attestation validate failed", result);
506
- }
507
- if (result instanceof securingMechanism.VcVerifyFailed) {
508
- return new CaVerifyFailed("Content Attestation verify failed", result);
509
- }
510
- const urlResult = await checkUrlAndOrigin(result, url);
511
- if (urlResult instanceof Error) {
512
- return urlResult;
513
- }
514
- await verifyImageDigestSri(
515
- urlResult.doc.credentialSubject.image
516
- );
517
- if (urlResult.doc.target) {
518
- if (urlResult.doc.target.length === 0) {
519
- return new CaInvalid("Target is empty", urlResult);
520
- }
521
- const integrityResults = await Promise.all(
522
- urlResult.doc.target.map(async (t, index) => ({
523
- index,
524
- verifyResult: await verifyIntegrity$1(t),
525
- expectedIntegrity: t.integrity
526
- }))
527
- );
528
- const error = checkIntegrityResults(integrityResults, urlResult);
529
- if (error) {
530
- return error;
531
- }
532
- const failedIndices = integrityResults.filter(
533
- (result2) => !(result2.verifyResult instanceof Error) && !result2.verifyResult.valid
534
- ).map((result2) => result2.index);
535
- if (failedIndices.length > 0) {
536
- const failedIntegritiesMessage = failedIndices.map((integrityResultIndex) => {
537
- const integrityResult = integrityResults[integrityResultIndex];
538
- if (integrityResult) {
539
- const verifyResult = integrityResult.verifyResult;
540
- const calculatedIntegrities = verifyResult.failedIntegrities.join();
541
- return `target[${integrityResultIndex}] Expected: ${integrityResult.expectedIntegrity}, Calculated: ${calculatedIntegrities}`;
542
- }
543
- return void 0;
544
- }).join(", ");
545
- return new CaVerifyFailed(
546
- `Content Attestation Target integrity verification failed for element(s): ${failedIntegritiesMessage}`,
547
- urlResult
548
- );
549
- }
550
- }
551
- return urlResult;
552
- };
553
- }
554
-
555
- class CasVerifyFailed extends Error {
556
- constructor(message, result) {
557
- super(message);
558
- this.result = result;
559
- }
560
- static get code() {
561
- return "ERR_CONTENT_ATTESTATION_SET_VERIFY_FAILED";
562
- }
563
- code = CasVerifyFailed.code;
564
- }
565
-
566
- function normalizeCasItem(ca) {
567
- if (typeof ca === "object" && ca !== null && "attestation" in ca) {
568
- return ca;
569
- }
570
- return { main: false, attestation: ca };
571
- }
572
-
573
- async function verifyCas(cas, verifiedOps, url, verifyIntegrity, validator) {
574
- const decodeCa = securingMechanism.JwtVcDecoder();
575
- const resultCas = await Promise.all(
576
- cas.map(async (ca) => {
577
- const { main, attestation: source } = normalizeCasItem(ca);
578
- const decodedCa = decodeCa(source);
579
- if (decodedCa instanceof Error) {
580
- return { main, attestation: new CaInvalid("Invalid CA", decodedCa) };
581
- }
582
- const cp = verifiedOps.find(
583
- (ops) => ops.core.doc.credentialSubject.id === decodedCa.doc.issuer
584
- );
585
- if (!cp) {
586
- return {
587
- main,
588
- attestation: new CoreProfileNotFound(
589
- "Appropriate Core Profile not found",
590
- decodedCa
591
- )
592
- };
593
- }
594
- const verify = CaVerifier(
595
- source,
596
- cryptography.LocalKeys(cp.core.doc.credentialSubject.jwks),
597
- decodedCa.doc.issuer,
598
- new URL(url),
599
- verifyIntegrity,
600
- validator?.(model.ContentAttestation)
601
- );
602
- return { main, attestation: await verify() };
603
- })
604
- );
605
- if (resultCas.some((ca) => {
606
- return ca.attestation instanceof CaInvalid || ca.attestation instanceof CoreProfileNotFound || ca.attestation instanceof CaVerifyFailed;
607
- })) {
608
- return new CasVerifyFailed(
609
- "Content Attestation Set verify failed",
610
- resultCas
611
- );
612
- }
613
- return resultCas;
614
- }
615
-
616
- var REMOVE = "remove";
617
- var REPLACE = "replace";
618
- var ADD = "add";
619
- var MOVE = "move";
620
- function diffApply(obj, diff, pathConverter) {
621
- if (!obj || typeof obj != "object") {
622
- throw new Error("base object must be an object or an array");
623
- }
624
- if (!Array.isArray(diff)) {
625
- throw new Error("diff must be an array");
626
- }
627
- var diffLength = diff.length;
628
- for (var i = 0; i < diffLength; i++) {
629
- var thisDiff = diff[i];
630
- var subObject = obj;
631
- var thisOp = thisDiff.op;
632
- var thisPath = transformPath(pathConverter, thisDiff.path);
633
- var thisFromPath = thisDiff.from && transformPath(pathConverter, thisDiff.from);
634
- var toPath, toPathCopy, lastToProp, subToObject, valueToMove;
635
- if (thisFromPath) {
636
- toPath = thisPath;
637
- thisPath = thisFromPath;
638
- toPathCopy = toPath.slice();
639
- lastToProp = toPathCopy.pop();
640
- prototypeCheck(lastToProp);
641
- if (lastToProp == null) {
642
- return false;
643
- }
644
- var thisToProp;
645
- while ((thisToProp = toPathCopy.shift()) != null) {
646
- prototypeCheck(thisToProp);
647
- if (!(thisToProp in subToObject)) {
648
- subToObject[thisToProp] = {};
649
- }
650
- subToObject = subToObject[thisToProp];
651
- }
652
- }
653
- var pathCopy = thisPath.slice();
654
- var lastProp = pathCopy.pop();
655
- prototypeCheck(lastProp);
656
- if (lastProp == null) {
657
- return false;
658
- }
659
- var thisProp;
660
- while ((thisProp = pathCopy.shift()) != null) {
661
- prototypeCheck(thisProp);
662
- if (!(thisProp in subObject)) {
663
- subObject[thisProp] = {};
664
- }
665
- subObject = subObject[thisProp];
666
- }
667
- if (thisOp === REMOVE || thisOp === REPLACE || thisOp === MOVE) {
668
- var path = thisOp === MOVE ? thisDiff.from : thisDiff.path;
669
- if (!subObject.hasOwnProperty(lastProp)) {
670
- throw new Error(["expected to find property", path, "in object", obj].join(" "));
671
- }
672
- }
673
- if (thisOp === REMOVE || thisOp === MOVE) {
674
- if (thisOp === MOVE) {
675
- valueToMove = subObject[lastProp];
676
- }
677
- Array.isArray(subObject) ? subObject.splice(lastProp, 1) : delete subObject[lastProp];
678
- }
679
- if (thisOp === REPLACE || thisOp === ADD) {
680
- subObject[lastProp] = thisDiff.value;
681
- }
682
- if (thisOp === MOVE) {
683
- subObject[lastToProp] = valueToMove;
684
- }
685
- }
686
- return subObject;
687
- }
688
- function transformPath(pathConverter, thisPath) {
689
- {
690
- if (!Array.isArray(thisPath)) {
691
- throw new Error([
692
- "diff path",
693
- thisPath,
694
- "must be an array, consider supplying a path converter"
695
- ].join(" "));
696
- }
697
- }
698
- return thisPath;
699
- }
700
- function prototypeCheck(prop) {
701
- if (prop == "__proto__" || prop == "constructor" || prop == "prototype") {
702
- throw new Error("setting of prototype values not supported");
703
- }
704
- }
705
-
706
- const patch = (...args) => {
707
- const [source, diff] = args;
708
- const patched = structuredClone(source);
709
- diffApply(patched, diff);
710
- return patched;
711
- };
712
- const VerifyResultFactory = (issuedAt, expiredAt) => ({
713
- create: (vc, jwt, verificationKey, validated = false) => {
714
- const unverified = {
715
- doc: vc,
716
- issuedAt,
717
- expiredAt,
718
- algorithm: "ES256",
719
- mediaType: "application/vc+jwt",
720
- source: jwt
721
- };
722
- if (!verificationKey) return unverified;
723
- return { ...unverified, verificationKey, validated };
724
- }
725
- });
726
- const opId = {
727
- /** CP 発行者 */
728
- authority: "dns:cp-issuer.example.org",
729
- /** PA 発行者 */
730
- certifier: "dns:pa-issuer.example.org",
731
- /** CA 発行者 */
732
- originator: "dns:originator.example.org",
733
- /** 無効な第三者 */
734
- invalid: "dns:invalid.example.org"
735
- };
736
- const cp = {
737
- "@context": [
738
- "https://www.w3.org/ns/credentials/v2",
739
- "https://originator-profile.org/ns/credentials/v1"
740
- ],
741
- type: ["VerifiableCredential", "CoreProfile"],
742
- issuer: opId.authority,
743
- credentialSubject: {
744
- id: opId.originator,
745
- type: "Core",
746
- jwks: {
747
- keys: []
748
- }
749
- }
750
- };
751
- const certificate = {
752
- "@context": [
753
- "https://www.w3.org/ns/credentials/v2",
754
- "https://originator-profile.org/ns/credentials/v1",
755
- "https://originator-profile.org/ns/cip/v1",
756
- {
757
- "@language": "ja"
758
- }
759
- ],
760
- type: ["VerifiableCredential", "Certificate"],
761
- issuer: opId.certifier,
762
- credentialSubject: {
763
- id: opId.originator,
764
- type: "CertificateProperties",
765
- description: "Example Certificate",
766
- certificationSystem: {
767
- id: "urn:uuid:de5d6e80-10a5-404f-b4d3-e9f0e6926a21",
768
- type: "CertificationSystem",
769
- name: "Example Certification System",
770
- description: "Example Certification System Description"
771
- }
772
- }
773
- };
774
- const wmp = {
775
- "@context": [
776
- "https://www.w3.org/ns/credentials/v2",
777
- "https://originator-profile.org/ns/credentials/v1",
778
- "https://originator-profile.org/ns/cip/v1",
779
- {
780
- "@language": "ja"
781
- }
782
- ],
783
- type: ["VerifiableCredential", "WebMediaProfile"],
784
- issuer: opId.authority,
785
- credentialSubject: {
786
- id: opId.originator,
787
- type: "OnlineBusiness",
788
- name: "Example OP Holder",
789
- url: "https://op-originator.example.org/"
790
- }
791
- };
792
- const wsp = {
793
- "@context": [
794
- "https://www.w3.org/ns/credentials/v2",
795
- "https://originator-profile.org/ns/credentials/v1",
796
- "https://originator-profile.org/ns/cip/v1",
797
- {
798
- "@language": "ja"
799
- }
800
- ],
801
- type: ["VerifiableCredential", "WebsiteProfile"],
802
- issuer: opId.originator,
803
- credentialSubject: {
804
- id: "https://originator.example.org",
805
- type: "WebSite",
806
- name: "Example Website",
807
- description: "Example Website Description",
808
- allowedOrigin: ["https://originator.example.org"]
809
- }
810
- };
811
- const caId = "urn:uuid:78550fa7-f846-4e0f-ad5c-8d34461cb95b";
812
- const caUrl = new URL("https://www.example.org/articles/example");
813
- const article = {
814
- "@context": [
815
- "https://www.w3.org/ns/credentials/v2",
816
- "https://originator-profile.org/ns/credentials/v1",
817
- "https://originator-profile.org/ns/cip/v1",
818
- { "@language": "ja" }
819
- ],
820
- type: ["VerifiableCredential", "ContentAttestation"],
821
- issuer: opId.originator,
822
- target: [],
823
- allowedUrl: ["https://www.example.org/articles*"],
824
- credentialSubject: {
825
- id: caId,
826
- type: "Article",
827
- headline: "\u30C6\u30B9\u30C8\u8A18\u4E8B",
828
- description: "\u8A18\u4E8B\u306E\u8AAC\u660E"
829
- }
830
- };
831
-
832
- function getMappedKeys(ops) {
833
- const groupedOps = Object.groupBy(
834
- ops,
835
- (op) => op.core.doc.credentialSubject.id
836
- );
837
- const keyMap = {};
838
- for (const [opId, ops2] of Object.entries(groupedOps)) {
839
- if (!ops2) continue;
840
- const kidSet = /* @__PURE__ */ new Set();
841
- const keys = ops2.flatMap((op) => op.core.doc.credentialSubject.jwks.keys).filter(({ kid }) => !kidSet.has(kid) && kidSet.add(kid));
842
- keyMap[opId] = { keys };
843
- }
844
- return keyMap;
845
- }
846
- function getTupledKeys(ops) {
847
- const keyMap = getMappedKeys(ops);
848
- const kidSet = /* @__PURE__ */ new Set();
849
- const opId = Object.keys(keyMap);
850
- const keys = Object.values(keyMap).flatMap((jwks) => jwks.keys).filter(({ kid }) => !kidSet.has(kid) && kidSet.add(kid));
851
- return [opId.length === 1 ? opId[0] : opId, cryptography.LocalKeys({ keys })];
852
- }
853
-
854
- class OpsInvalid extends Error {
855
- constructor(message, result) {
856
- super(message);
857
- this.result = result;
858
- }
859
- static get code() {
860
- return "ERR_ORIGINATOR_PROFILE_SET_INVALID";
861
- }
862
- code = OpsInvalid.code;
863
- }
864
- class OpInvalid extends Error {
865
- constructor(message, result) {
866
- super(message);
867
- this.result = result;
868
- }
869
- static get code() {
870
- return "ERR_ORIGINATOR_PROFILE_INVALID";
871
- }
872
- code = OpInvalid.code;
873
- }
874
- class CoreProfileNotFound extends Error {
875
- constructor(message, result) {
876
- super(message);
877
- this.result = result;
878
- }
879
- static get code() {
880
- return "ERR_CORE_PROFILE_NOT_FOUND";
881
- }
882
- code = CoreProfileNotFound.code;
883
- }
884
- class OpsVerifyFailed extends Error {
885
- constructor(message, result) {
886
- super(message);
887
- this.result = result;
888
- }
889
- static get code() {
890
- return "ERR_ORIGINATOR_PROFILE_SET_VERIFY_FAILED";
891
- }
892
- code = OpsVerifyFailed.code;
893
- }
894
- class OpVerifyFailed extends Error {
895
- constructor(message, result) {
896
- super(message);
897
- this.result = result;
898
- }
899
- static get code() {
900
- return "ERR_ORIGINATOR_PROFILE_VERIFY_FAILED";
901
- }
902
- code = OpVerifyFailed.code;
903
- }
904
- class CertificateExpired extends Error {
905
- constructor(message, result) {
906
- super(message);
907
- this.result = result;
908
- }
909
- static get code() {
910
- return "ERR_CERTIFICATE_EXPIRED";
911
- }
912
- code = CertificateExpired.code;
913
- }
914
-
915
- const isEveryDecodedPa = (annotations) => annotations.every((annotation) => "doc" in annotation);
916
- const isEveryDecodedWmp = (media) => media.every((m) => "doc" in m);
917
- const validateDecodedOp = (core, annotations, media, resultOp) => {
918
- if (annotations && !isEveryDecodedPa(annotations)) {
919
- return new OpInvalid("Profile Annotation decode failed", resultOp);
920
- }
921
- if (media && !isEveryDecodedWmp(media)) {
922
- return new OpInvalid("Web Media Profile decode failed", resultOp);
923
- }
924
- if (media && media.some(
925
- (m) => core.doc.credentialSubject.id !== m.doc.credentialSubject.id
926
- )) {
927
- return new OpInvalid(
928
- "Subject mismatch between Core Profile and Web Media Profile",
929
- resultOp
930
- );
931
- }
932
- if (annotations && annotations.some(
933
- (annotation) => core.doc.credentialSubject.id !== annotation.doc.credentialSubject.id
934
- )) {
935
- return new OpInvalid(
936
- "Subject mismatch between Core Profile and Profile Annotation",
937
- resultOp
938
- );
939
- }
940
- return { type: "valid", annotations, media };
941
- };
942
- const isDecodedOps = (ops) => ops.every((op) => !(op instanceof OpInvalid));
943
- function decodeOps(ops) {
944
- const decodeCp = securingMechanism.JwtVcDecoder();
945
- const decodePa = securingMechanism.JwtVcDecoder();
946
- const decodeWmp = securingMechanism.JwtVcDecoder();
947
- const resultOps = ops.map((op) => {
948
- const core = decodeCp(op.core);
949
- const annotations = op.annotations ? op.annotations.map(decodePa) : void 0;
950
- const mediaInput = op.media;
951
- const mediaArray = mediaInput ? Array.isArray(mediaInput) ? mediaInput : [mediaInput] : void 0;
952
- const media = mediaArray ? mediaArray.map(decodeWmp) : void 0;
953
- const resultOp = { core, annotations, media };
954
- if (core instanceof Error) {
955
- return new OpInvalid("Core Profile decode failed", resultOp);
956
- }
957
- const validated = validateDecodedOp(core, annotations, media, resultOp);
958
- if (validated instanceof OpInvalid) {
959
- return validated;
960
- }
961
- return {
962
- core,
963
- annotations: validated.annotations,
964
- media: validated.media
965
- };
966
- });
967
- if (!isDecodedOps(resultOps)) {
968
- return new OpsInvalid("Invalid Originator Profile Set", resultOps);
969
- }
970
- return resultOps;
971
- }
972
-
973
- function OpVerifier(paOrWmpIssuerKeys, vc, validator) {
974
- const issuer = vc.doc.issuer;
975
- const jwks = paOrWmpIssuerKeys[issuer];
976
- if (!jwks) {
977
- return async () => new CoreProfileNotFound(`Missing Core Profile (${issuer})`, vc);
978
- }
979
- const cpKeys = cryptography.LocalKeys(jwks);
980
- return securingMechanism.JwtVcVerifier(cpKeys, issuer, validator);
981
- }
982
- function validateCertificateExpiry(verifiedVc) {
983
- const now = /* @__PURE__ */ new Date();
984
- const validFrom = verifiedVc.doc.validFrom ? new Date(verifiedVc.doc.validFrom) : null;
985
- const validUntil = verifiedVc.doc.validUntil ? new Date(verifiedVc.doc.validUntil) : null;
986
- if (validFrom && now < validFrom) {
987
- return new CertificateExpired("Certificate not yet valid", verifiedVc);
988
- }
989
- if (validUntil && now > validUntil) {
990
- return new CertificateExpired("Certificate expired", verifiedVc);
991
- }
992
- return verifiedVc;
993
- }
994
- async function verifyAnnotations(paIssuerKeys, annotations, validator) {
995
- if (!annotations) return;
996
- return await Promise.all(
997
- annotations.map(async (annotation) => {
998
- const verify = OpVerifier(
999
- paIssuerKeys,
1000
- annotation,
1001
- validator?.(zod.z.union([model.Certificate, model.JapaneseExistenceCertificate]))
1002
- );
1003
- const result = await verify(annotation.source);
1004
- if (result instanceof Error) {
1005
- return result;
1006
- }
1007
- const valid = validateCertificateExpiry(result);
1008
- if (valid instanceof CertificateExpired) {
1009
- return valid;
1010
- }
1011
- await verifyImageDigestSri(
1012
- valid.doc.credentialSubject.image
1013
- );
1014
- return valid;
1015
- })
1016
- );
1017
- }
1018
- async function verifyMedia(wmpIssuerKeys, media, validator) {
1019
- if (!media) return;
1020
- return await Promise.all(
1021
- media.map(async (m) => {
1022
- const verify = OpVerifier(
1023
- wmpIssuerKeys,
1024
- m,
1025
- validator?.(model.WebMediaProfile)
1026
- );
1027
- const result = await verify(m.source);
1028
- if (result instanceof Error) {
1029
- return result;
1030
- }
1031
- await verifyImageDigestSri(result.doc.credentialSubject.logo);
1032
- return result;
1033
- })
1034
- );
1035
- }
1036
- const isVerifiedOps = (ops) => ops.every((op) => !(op instanceof OpVerifyFailed));
1037
- function OpsVerifier(ops, keys, issuer, validator) {
1038
- const decoded = decodeOps(ops);
1039
- const verifyCp = securingMechanism.JwtVcVerifier(
1040
- keys,
1041
- issuer,
1042
- validator?.(model.CoreProfile)
1043
- );
1044
- async function verify() {
1045
- if (decoded instanceof OpsInvalid) {
1046
- return decoded;
1047
- }
1048
- const paOrWmpIssuerKeys = getMappedKeys(decoded);
1049
- const resultOps = await Promise.all(
1050
- decoded.map(async (op) => {
1051
- const core = await verifyCp(op.core.source);
1052
- const annotations = await verifyAnnotations(
1053
- paOrWmpIssuerKeys,
1054
- op.annotations,
1055
- validator
1056
- );
1057
- const media = await verifyMedia(paOrWmpIssuerKeys, op.media, validator);
1058
- const resultOp = { core, annotations, media };
1059
- if (core instanceof Error) {
1060
- return new OpVerifyFailed("Core Profile verify failed", resultOp);
1061
- }
1062
- if (annotations && annotations.some((annotation) => annotation instanceof Error)) {
1063
- return new OpVerifyFailed(
1064
- "Profile Annotation verify failed",
1065
- resultOp
1066
- );
1067
- }
1068
- if (media && media.some((m) => m instanceof Error)) {
1069
- return new OpVerifyFailed(
1070
- "Web Media Profile verify failed",
1071
- resultOp
1072
- );
1073
- }
1074
- return resultOp;
1075
- })
1076
- );
1077
- if (!isVerifiedOps(resultOps)) {
1078
- return new OpsVerifyFailed(
1079
- "Originator Profile Set verify failed",
1080
- resultOps
1081
- );
1082
- }
1083
- return resultOps;
1084
- }
1085
- return verify;
1086
- }
1087
-
1088
- class SiteProfileInvalid extends Error {
1089
- constructor(message, result) {
1090
- super(message);
1091
- this.result = result;
1092
- }
1093
- static get code() {
1094
- return "ERR_SITE_PROFILE_INVALID";
1095
- }
1096
- code = SiteProfileInvalid.code;
1097
- }
1098
- class SiteProfileVerifyFailed extends Error {
1099
- constructor(message, result) {
1100
- super(message);
1101
- this.result = result;
1102
- }
1103
- static get code() {
1104
- return "ERR_SITE_PROFILE_VERIFY_FAILED";
1105
- }
1106
- code = SiteProfileVerifyFailed.code;
1107
- }
1108
-
1109
- const decodeWebsiteProfiles = (sp, opsVerified) => {
1110
- const wspSources = sp.sites || (sp.credential ? [sp.credential] : []);
1111
- if (wspSources.length === 0) {
1112
- return new SiteProfileInvalid("No Website Profile found", {
1113
- originators: opsVerified,
1114
- sites: []
1115
- });
1116
- }
1117
- const decodeWsp = securingMechanism.JwtVcDecoder();
1118
- const decodedWsps = wspSources.map(decodeWsp);
1119
- const decodeErrors = decodedWsps.filter((wsp) => wsp instanceof Error);
1120
- if (decodeErrors.length > 0) {
1121
- return new SiteProfileInvalid("Website Profile invalid", {
1122
- originators: opsVerified,
1123
- sites: decodeErrors
1124
- });
1125
- }
1126
- return {
1127
- decodedWsps,
1128
- wspSources
1129
- };
1130
- };
1131
- function SpVerifier(sp, keys, issuer, origin, verifyOrigin = true, validator) {
1132
- async function verify() {
1133
- const verifyOps = OpsVerifier(sp.originators, keys, issuer, validator);
1134
- const opsVerified = await verifyOps();
1135
- if (opsVerified instanceof OpsInvalid) {
1136
- return new SiteProfileInvalid("Originator Profile Set invalid", {
1137
- originators: opsVerified,
1138
- sites: []
1139
- });
1140
- }
1141
- if (opsVerified instanceof OpsVerifyFailed) {
1142
- return new SiteProfileVerifyFailed(
1143
- "Originator Profile Set verify failed",
1144
- { originators: opsVerified, sites: [] }
1145
- );
1146
- }
1147
- const decoded = decodeWebsiteProfiles(sp, opsVerified);
1148
- if (decoded instanceof SiteProfileInvalid) {
1149
- return decoded;
1150
- }
1151
- const { decodedWsps, wspSources } = decoded;
1152
- const verifiedWsps = await Promise.all(
1153
- decodedWsps.map(async (decodedWsp, index) => {
1154
- if (decodedWsp instanceof Error) {
1155
- return decodedWsp;
1156
- }
1157
- const wspIssuer = decodedWsp.doc.issuer;
1158
- const cp = opsVerified.find(
1159
- (op) => op.core.doc.credentialSubject.id === wspIssuer
1160
- );
1161
- if (!cp) {
1162
- return new CoreProfileNotFound(
1163
- `Missing Core Profile (${wspIssuer})`,
1164
- decodedWsp
1165
- );
1166
- }
1167
- const verifyWsp = securingMechanism.JwtVcVerifier(
1168
- cryptography.LocalKeys(cp.core.doc.credentialSubject.jwks),
1169
- cp.core.doc.credentialSubject.id,
1170
- validator?.(model.WebsiteProfile)
1171
- );
1172
- const verified = await verifyWsp(wspSources[index]);
1173
- if (verified instanceof Error) {
1174
- return verified;
1175
- }
1176
- if (verifyOrigin) {
1177
- const allowedOrigin = "allowedOrigin" in verified.doc.credentialSubject ? verified.doc.credentialSubject.allowedOrigin : verified.doc.credentialSubject.url;
1178
- if (!verifyAllowedOrigin(origin, allowedOrigin)) {
1179
- return new Error("Origin not allowed");
1180
- }
1181
- }
1182
- await verifyImageDigestSri(verified.doc.credentialSubject.image);
1183
- return verified;
1184
- })
1185
- );
1186
- const hasCoreProfileNotFound = verifiedWsps.some(
1187
- (wsp) => wsp instanceof CoreProfileNotFound
1188
- );
1189
- if (hasCoreProfileNotFound) {
1190
- return new SiteProfileInvalid("Appropriate Core Profile not found", {
1191
- originators: opsVerified,
1192
- sites: verifiedWsps
1193
- });
1194
- }
1195
- const hasError = verifiedWsps.some((wsp) => wsp instanceof Error);
1196
- if (hasError) {
1197
- return new SiteProfileVerifyFailed("Website Profile verify failed", {
1198
- originators: opsVerified,
1199
- sites: verifiedWsps
1200
- });
1201
- }
1202
- return {
1203
- originators: opsVerified,
1204
- sites: verifiedWsps
1205
- };
1206
- }
1207
- return verify;
1208
- }
1209
-
1210
- exports.CaInvalid = CaInvalid;
1211
- exports.CaVerifier = CaVerifier;
1212
- exports.CaVerifyFailed = CaVerifyFailed;
1213
- exports.CasVerifyFailed = CasVerifyFailed;
1214
- exports.CertificateExpired = CertificateExpired;
1215
- exports.CoreProfileNotFound = CoreProfileNotFound;
1216
- exports.IntegrityFetchFailed = IntegrityFetchFailed;
1217
- exports.IntegrityVerificationFailed = IntegrityVerificationFailed;
1218
- exports.OpInvalid = OpInvalid;
1219
- exports.OpVerifyFailed = OpVerifyFailed;
1220
- exports.OpsInvalid = OpsInvalid;
1221
- exports.OpsVerifier = OpsVerifier;
1222
- exports.OpsVerifyFailed = OpsVerifyFailed;
1223
- exports.SiteProfileInvalid = SiteProfileInvalid;
1224
- exports.SiteProfileVerifyFailed = SiteProfileVerifyFailed;
1225
- exports.SpVerifier = SpVerifier;
1226
- exports.TargetIntegrityAlgorithm = TargetIntegrityAlgorithm;
1227
- exports.VerifyResultFactory = VerifyResultFactory;
1228
- exports.article = article;
1229
- exports.caId = caId;
1230
- exports.caUrl = caUrl;
1231
- exports.certificate = certificate;
1232
- exports.cp = cp;
1233
- exports.decodeOps = decodeOps;
1234
- exports.getMappedKeys = getMappedKeys;
1235
- exports.getTupledKeys = getTupledKeys;
1236
- exports.normalizeCasItem = normalizeCasItem;
1237
- exports.opId = opId;
1238
- exports.patch = patch;
1239
- exports.verifyAllowedOrigin = verifyAllowedOrigin;
1240
- exports.verifyCas = verifyCas;
1241
- exports.verifyDigestSri = verifyDigestSri;
1242
- exports.verifyImageDigestSri = verifyImageDigestSri;
1243
- exports.verifyIntegrity = verifyIntegrity;
1244
- exports.wmp = wmp;
1245
- exports.wsp = wsp;