@originator-profile/verify 0.5.0-beta.1 → 0.5.0-beta.2

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 CHANGED
@@ -4,6 +4,7 @@ var securingMechanism = require('@originator-profile/securing-mechanism');
4
4
  var sign = require('@originator-profile/sign');
5
5
  var cryptography = require('@originator-profile/cryptography');
6
6
  var model = require('@originator-profile/model');
7
+ var zod = require('zod');
7
8
 
8
9
  class CaInvalid extends Error {
9
10
  constructor(message, result) {
@@ -300,12 +301,62 @@ async function createIntegrityMetadataSet(hashAlgorithms, data, options = {
300
301
  return new IntegrityMetadataSet(set, options);
301
302
  }
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`;
303
305
  async function verifyDigestSri(content, fetcher = fetch) {
304
306
  const integrity = new IntegrityMetadataSet(content.digestSRI);
305
307
  const alg = integrity.strongestHashAlgorithms.filter(Boolean);
306
308
  if (alg.length === 0) return false;
307
- const { digestSRI } = await sign.createDigestSri(alg[0], content, fetcher);
308
- return integrity.match(digestSRI);
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
+ }
309
360
  }
310
361
 
311
362
  class IntegrityVerifier {
@@ -354,7 +405,14 @@ async function verifyIntegrity(content, doc = document, fetcher = fetch) {
354
405
  (content2) => contentFetcher(content2, fetcher),
355
406
  elementSelector
356
407
  );
357
- return await integrityVerifier.verify(content, doc);
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
+ }
358
416
  }
359
417
 
360
418
  function verifyAllowedOrigin(origin, allowedOrigins) {
@@ -380,8 +438,13 @@ async function verifyAllowedUrl(url, allowedUrl) {
380
438
  if (!value) {
381
439
  return false;
382
440
  }
383
- const pattern = new URLPattern(ReplaceEncode(value));
384
- return pattern.test(ReplaceEncode(url));
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;
385
448
  });
386
449
  }
387
450
 
@@ -408,6 +471,32 @@ async function checkUrlAndOrigin(result, url) {
408
471
  }
409
472
  return result;
410
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
+ }
411
500
  function CaVerifier(ca, keys, issuer, url, verifyIntegrity$1 = verifyIntegrity, validator) {
412
501
  const verifyCa = securingMechanism.JwtVcVerifier(keys, issuer, validator);
413
502
  return async () => {
@@ -422,6 +511,9 @@ function CaVerifier(ca, keys, issuer, url, verifyIntegrity$1 = verifyIntegrity,
422
511
  if (urlResult instanceof Error) {
423
512
  return urlResult;
424
513
  }
514
+ await verifyImageDigestSri(
515
+ urlResult.doc.credentialSubject.image
516
+ );
425
517
  if (urlResult.doc.target) {
426
518
  if (urlResult.doc.target.length === 0) {
427
519
  return new CaInvalid("Target is empty", urlResult);
@@ -433,12 +525,19 @@ function CaVerifier(ca, keys, issuer, url, verifyIntegrity$1 = verifyIntegrity,
433
525
  expectedIntegrity: t.integrity
434
526
  }))
435
527
  );
436
- const failedIndices = integrityResults.filter((result2) => !result2.verifyResult.valid).map((result2) => result2.index);
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);
437
535
  if (failedIndices.length > 0) {
438
536
  const failedIntegritiesMessage = failedIndices.map((integrityResultIndex) => {
439
537
  const integrityResult = integrityResults[integrityResultIndex];
440
538
  if (integrityResult) {
441
- const calculatedIntegrities = integrityResult.verifyResult.failedIntegrities.join();
539
+ const verifyResult = integrityResult.verifyResult;
540
+ const calculatedIntegrities = verifyResult.failedIntegrities.join();
442
541
  return `target[${integrityResultIndex}] Expected: ${integrityResult.expectedIntegrity}, Calculated: ${calculatedIntegrities}`;
443
542
  }
444
543
  return void 0;
@@ -514,91 +613,6 @@ async function verifyCas(cas, verifiedOps, url, verifyIntegrity, validator) {
514
613
  return resultCas;
515
614
  }
516
615
 
517
- class ProfileGenericError extends Error {
518
- static get code() {
519
- return "ERR_PROFILE_GENERIC";
520
- }
521
- code = ProfileGenericError.code;
522
- }
523
- class ProfileClaimsValidationFailed extends ProfileGenericError {
524
- static get code() {
525
- return "ERR_PROFILE_CLAIMS_VALIDATION_FAILED";
526
- }
527
- code = ProfileClaimsValidationFailed.code;
528
- /** 復号結果 */
529
- result;
530
- constructor(message, result) {
531
- super(message);
532
- this.result = result;
533
- }
534
- }
535
- class ProfileTokenVerifyFailed extends ProfileGenericError {
536
- static get code() {
537
- return "ERR_PROFILE_TOKEN_VERIFY_FAILED";
538
- }
539
- code = ProfileTokenVerifyFailed.code;
540
- /** 検証結果 */
541
- result;
542
- constructor(message, result) {
543
- super(message);
544
- this.result = result;
545
- }
546
- }
547
- class ProfileBodyExtractFailed extends ProfileGenericError {
548
- static get code() {
549
- return "ERR_PROFILE_BODY_EXTRACT_FAILED";
550
- }
551
- code = ProfileBodyExtractFailed.code;
552
- }
553
- class ProfileBodyVerifyFailed extends ProfileGenericError {
554
- static get code() {
555
- return "ERR_PROFILE_BODY_VERIFY_FAILED";
556
- }
557
- code = ProfileBodyVerifyFailed.code;
558
- /** 検証結果 */
559
- result;
560
- constructor(message, result) {
561
- super(message);
562
- this.result = result;
563
- }
564
- }
565
- class ProfilesResolveFailed extends ProfileGenericError {
566
- static get code() {
567
- return "ERR_PROFILES_RESOLVE_FAILED";
568
- }
569
- code = ProfilesResolveFailed.code;
570
- /** 検証結果 */
571
- result;
572
- constructor(message, result) {
573
- super(message);
574
- this.result = result;
575
- }
576
- }
577
- class ProfilesVerifyFailed extends ProfileGenericError {
578
- static get code() {
579
- return "ERR_PROFILES_VERIFY_FAILED";
580
- }
581
- code = ProfilesVerifyFailed.code;
582
- /** 検証結果 */
583
- result;
584
- constructor(message, result) {
585
- super(message);
586
- this.result = result;
587
- }
588
- }
589
- class CertificationSystemValidationFailed extends ProfileGenericError {
590
- static get code() {
591
- return "ERR_CERTIFICATION_SYSTEM_VALIDATION_FAILED";
592
- }
593
- code = CertificationSystemValidationFailed.code;
594
- /** 検証結果 */
595
- result;
596
- constructor(message, result) {
597
- super(message);
598
- this.result = result;
599
- }
600
- }
601
-
602
616
  var REMOVE = "remove";
603
617
  var REPLACE = "replace";
604
618
  var ADD = "add";
@@ -984,28 +998,38 @@ async function verifyAnnotations(paIssuerKeys, annotations, validator) {
984
998
  const verify = OpVerifier(
985
999
  paIssuerKeys,
986
1000
  annotation,
987
- validator?.({
988
- oneOf: [model.Certificate, model.JapaneseExistenceCertificate]
989
- })
1001
+ validator?.(zod.z.union([model.Certificate, model.JapaneseExistenceCertificate]))
990
1002
  );
991
1003
  const result = await verify(annotation.source);
992
1004
  if (result instanceof Error) {
993
1005
  return result;
994
1006
  }
995
- return validateCertificateExpiry(result);
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;
996
1015
  })
997
1016
  );
998
1017
  }
999
1018
  async function verifyMedia(wmpIssuerKeys, media, validator) {
1000
1019
  if (!media) return;
1001
1020
  return await Promise.all(
1002
- media.map((m) => {
1021
+ media.map(async (m) => {
1003
1022
  const verify = OpVerifier(
1004
1023
  wmpIssuerKeys,
1005
1024
  m,
1006
1025
  validator?.(model.WebMediaProfile)
1007
1026
  );
1008
- return verify(m.source);
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;
1009
1033
  })
1010
1034
  );
1011
1035
  }
@@ -1150,11 +1174,12 @@ function SpVerifier(sp, keys, issuer, origin, verifyOrigin = true, validator) {
1150
1174
  return verified;
1151
1175
  }
1152
1176
  if (verifyOrigin) {
1153
- const allowedOrigin = "allowedOrigin" in decodedWsp.doc.credentialSubject ? decodedWsp.doc.credentialSubject.allowedOrigin : decodedWsp.doc.credentialSubject.url;
1177
+ const allowedOrigin = "allowedOrigin" in verified.doc.credentialSubject ? verified.doc.credentialSubject.allowedOrigin : verified.doc.credentialSubject.url;
1154
1178
  if (!verifyAllowedOrigin(origin, allowedOrigin)) {
1155
1179
  return new Error("Origin not allowed");
1156
1180
  }
1157
1181
  }
1182
+ await verifyImageDigestSri(verified.doc.credentialSubject.image);
1158
1183
  return verified;
1159
1184
  })
1160
1185
  );
@@ -1182,85 +1207,19 @@ function SpVerifier(sp, keys, issuer, origin, verifyOrigin = true, validator) {
1182
1207
  return verify;
1183
1208
  }
1184
1209
 
1185
- var objectTypeof = typeOf;
1186
- function typeOf(obj) {
1187
- if (obj === null) {
1188
- return "null";
1189
- }
1190
- if (obj !== Object(obj)) {
1191
- return typeof obj;
1192
- }
1193
- var result = {}.toString.call(obj).slice(8, -1).toLowerCase();
1194
- return result.indexOf("function") > -1 ? "function" : result;
1195
- }
1196
-
1197
- function CertificationSystemValidator() {
1198
- return function validate(payload) {
1199
- if (objectTypeof(payload) !== "object") {
1200
- return new CertificationSystemValidationFailed("should be an object", {
1201
- payload
1202
- });
1203
- }
1204
- const keys = Object.keys(payload);
1205
- const entries = Object.entries(payload);
1206
- if (!model.CertificationSystem.required.every((k) => keys.includes(k))) {
1207
- return new CertificationSystemValidationFailed(
1208
- "should be contain required properties",
1209
- { payload }
1210
- );
1211
- }
1212
- for (const entry of entries) {
1213
- const [key, value] = entry;
1214
- const propertySchema = model.CertificationSystem.properties[key];
1215
- if (objectTypeof(propertySchema) !== "object") {
1216
- return new CertificationSystemValidationFailed(
1217
- "should not contain additional properties",
1218
- { payload }
1219
- );
1220
- }
1221
- if ("const" in propertySchema && value !== propertySchema.const)
1222
- return new CertificationSystemValidationFailed(
1223
- `should be contain value of '${value}' in '${key}' property`,
1224
- { payload }
1225
- );
1226
- if ("type" in propertySchema && typeof value !== propertySchema.type)
1227
- return new CertificationSystemValidationFailed(
1228
- `should be contain ${propertySchema.type} value in '${key}' property`,
1229
- { payload }
1230
- );
1231
- }
1232
- return true;
1233
- };
1234
- }
1235
- function validateCertificationSystem(payload) {
1236
- const validator = CertificationSystemValidator();
1237
- const result = validator(payload);
1238
- if (result !== true) {
1239
- return result;
1240
- }
1241
- return payload;
1242
- }
1243
-
1244
1210
  exports.CaInvalid = CaInvalid;
1245
1211
  exports.CaVerifier = CaVerifier;
1246
1212
  exports.CaVerifyFailed = CaVerifyFailed;
1247
1213
  exports.CasVerifyFailed = CasVerifyFailed;
1248
1214
  exports.CertificateExpired = CertificateExpired;
1249
- exports.CertificationSystemValidationFailed = CertificationSystemValidationFailed;
1250
- exports.CertificationSystemValidator = CertificationSystemValidator;
1251
1215
  exports.CoreProfileNotFound = CoreProfileNotFound;
1216
+ exports.IntegrityFetchFailed = IntegrityFetchFailed;
1217
+ exports.IntegrityVerificationFailed = IntegrityVerificationFailed;
1252
1218
  exports.OpInvalid = OpInvalid;
1253
1219
  exports.OpVerifyFailed = OpVerifyFailed;
1254
1220
  exports.OpsInvalid = OpsInvalid;
1255
1221
  exports.OpsVerifier = OpsVerifier;
1256
1222
  exports.OpsVerifyFailed = OpsVerifyFailed;
1257
- exports.ProfileBodyExtractFailed = ProfileBodyExtractFailed;
1258
- exports.ProfileBodyVerifyFailed = ProfileBodyVerifyFailed;
1259
- exports.ProfileClaimsValidationFailed = ProfileClaimsValidationFailed;
1260
- exports.ProfileGenericError = ProfileGenericError;
1261
- exports.ProfileTokenVerifyFailed = ProfileTokenVerifyFailed;
1262
- exports.ProfilesResolveFailed = ProfilesResolveFailed;
1263
- exports.ProfilesVerifyFailed = ProfilesVerifyFailed;
1264
1223
  exports.SiteProfileInvalid = SiteProfileInvalid;
1265
1224
  exports.SiteProfileVerifyFailed = SiteProfileVerifyFailed;
1266
1225
  exports.SpVerifier = SpVerifier;
@@ -1277,10 +1236,10 @@ exports.getTupledKeys = getTupledKeys;
1277
1236
  exports.normalizeCasItem = normalizeCasItem;
1278
1237
  exports.opId = opId;
1279
1238
  exports.patch = patch;
1280
- exports.validateCertificationSystem = validateCertificationSystem;
1281
1239
  exports.verifyAllowedOrigin = verifyAllowedOrigin;
1282
1240
  exports.verifyCas = verifyCas;
1283
1241
  exports.verifyDigestSri = verifyDigestSri;
1242
+ exports.verifyImageDigestSri = verifyImageDigestSri;
1284
1243
  exports.verifyIntegrity = verifyIntegrity;
1285
1244
  exports.wmp = wmp;
1286
1245
  exports.wsp = wsp;
package/dist/index.d.cts CHANGED
@@ -1,10 +1,7 @@
1
- import { ContentAttestation, Target, ContentAttestationSet, JwtOpPayload, JwtDpPayload, Op, Dp, OpVc, Jwk, CoreProfile, Certificate as Certificate$1, WebMediaProfile, WebsiteProfile, ArticleCA, JapaneseExistenceCertificate, OriginatorProfileSet, Jwks, SiteProfile, CertificationSystem, AllowedOrigin } from '@originator-profile/model';
1
+ import { ContentAttestation, Image, Target, ContentAttestationSet, OpVc, Jwk, CoreProfile, Certificate as Certificate$1, WebMediaProfile, WebsiteProfile, ArticleCA, JapaneseExistenceCertificate, OriginatorProfileSet, Jwks, SiteProfile, AllowedOrigin } from '@originator-profile/model';
2
2
  import { JwtVcDecodingResult, JwtVcVerificationResult, UnverifiedJwtVc, VerifiedJwtVc, VcValidator } from '@originator-profile/securing-mechanism';
3
3
  import { Keys } from '@originator-profile/cryptography';
4
- import { DigestSriContent, ContentFetcher, ElementSelector } from '@originator-profile/sign';
5
- import { ErrorObject } from 'ajv';
6
- import { JWTVerifyResult, ResolvedKey, JWTPayload } from 'jose';
7
- import { JOSEError } from 'jose/errors';
4
+ import { DigestSriResult, ContentFetcher, ElementSelector } from '@originator-profile/sign';
8
5
 
9
6
  /** Content Attestation 復号失敗 */
10
7
  type CaDecodingFailure = JwtVcDecodingResult<ContentAttestation>;
@@ -47,7 +44,7 @@ declare class CaVerifyFailed extends Error {
47
44
  * @see {@link https://www.w3.org/TR/SRI/#the-integrity-attribute}
48
45
  * @example
49
46
  * ```ts
50
- * const content: DigestSriContent = {
47
+ * const content = {
51
48
  * id: "<URL>",
52
49
  * digestSRI: "sha256-...",
53
50
  * };
@@ -55,12 +52,36 @@ declare class CaVerifyFailed extends Error {
55
52
  * await verifyDigestSri(content); // true or false
56
53
  * ```
57
54
  */
58
- declare function verifyDigestSri(content: DigestSriContent, fetcher?: typeof fetch): Promise<boolean>;
55
+ declare function verifyDigestSri(content: DigestSriResult, fetcher?: typeof fetch): Promise<boolean>;
56
+ /**
57
+ * Image の digestSRI を検証する。
58
+ * 後方互換性の観点で、2027年までは検証失敗時に console.warn のみで処理を中断しない。
59
+ */
60
+ declare function verifyImageDigestSri(value: Image | undefined, fetcher?: typeof fetch): Promise<void>;
61
+
62
+ declare class IntegrityFetchFailed extends Error {
63
+ static get code(): "ERR_INTEGRITY_FETCH_FAILED";
64
+ readonly code: "ERR_INTEGRITY_FETCH_FAILED";
65
+ readonly ok = false;
66
+ /** 取得結果 */
67
+ result?: Error;
68
+ constructor(message: string, result: IntegrityFetchFailed["result"]);
69
+ }
70
+ declare class IntegrityVerificationFailed extends Error {
71
+ static get code(): "ERR_INTEGRITY_VERIFICATION_FAILED";
72
+ readonly code: "ERR_INTEGRITY_VERIFICATION_FAILED";
73
+ readonly ok = false;
74
+ /** 取得結果 */
75
+ result?: unknown;
76
+ constructor(message: string, result: IntegrityVerificationFailed["result"]);
77
+ }
59
78
 
60
79
  type IntegrityVerifyResult = {
61
80
  valid: boolean;
62
81
  failedIntegrities: ReadonlyArray<string>;
63
82
  };
83
+ type FetchIntegrityResult = IntegrityVerifyResult | IntegrityFetchFailed | IntegrityVerificationFailed;
84
+
64
85
  /** Target Integrity のコンテンツ取得・要素位置特定アルゴリズム */
65
86
  declare const TargetIntegrityAlgorithm: {
66
87
  HtmlTargetIntegrity: {
@@ -94,7 +115,7 @@ declare const TargetIntegrityAlgorithm: {
94
115
  * await verifyIntegrity(content); // true or false
95
116
  * ```
96
117
  */
97
- declare function verifyIntegrity(content: Target, doc?: Document, fetcher?: typeof fetch): Promise<IntegrityVerifyResult>;
118
+ declare function verifyIntegrity(content: Target, doc?: Document, fetcher?: typeof fetch): Promise<FetchIntegrityResult>;
98
119
  type VerifyIntegrity = typeof verifyIntegrity;
99
120
 
100
121
  /**
@@ -171,116 +192,6 @@ declare function normalizeCasItem<Ca>(ca: Ca | CasItem<Ca>): CasItem<Ca>;
171
192
  */
172
193
  declare function verifyCas<T extends ContentAttestation = ContentAttestation>(cas: ContentAttestationSet, verifiedOps: VerifiedOps, url: string, verifyIntegrity: VerifyIntegrity, validator?: typeof VcValidator): Promise<CasVerificationResult<T>>;
173
194
 
174
- interface ProfilePair {
175
- op: {
176
- iss: string;
177
- sub: string;
178
- profile: string;
179
- };
180
- dp: {
181
- sub: string;
182
- profile: string;
183
- };
184
- }
185
- interface WebsiteProfilePair {
186
- "@context": string;
187
- website: ProfilePair;
188
- }
189
- interface AdProfilePair {
190
- "@context": string;
191
- ad: ProfilePair;
192
- }
193
- /** Profile の Token の復号結果 */
194
- type DecodeResult = {
195
- op: true;
196
- payload: JwtOpPayload;
197
- jwt: string;
198
- } | {
199
- dp: true;
200
- payload: JwtDpPayload;
201
- jwt: string;
202
- } | ProfileClaimsValidationFailed;
203
- /** Profile の Token の検証結果 */
204
- type VerifyTokenResult = (JWTVerifyResult & ResolvedKey & ({
205
- op: Op;
206
- jwt: string;
207
- } | {
208
- dp: Dp;
209
- jwt: string;
210
- })) | ProfileClaimsValidationFailed | ProfileTokenVerifyFailed;
211
- /** Profile Set */
212
- type Profiles = {
213
- profile: string[];
214
- ad?: ProfilePair[];
215
- };
216
- /** Profile の検証結果 */
217
- type VerifyResult = VerifyTokenResult | ProfilesResolveFailed | ProfilesVerifyFailed;
218
- /** Profile Set の検証結果 */
219
- type VerifyResults = VerifyResult[];
220
-
221
- declare class ProfileGenericError extends Error {
222
- static get code(): string;
223
- readonly code: string;
224
- }
225
- declare class ProfileClaimsValidationFailed extends ProfileGenericError {
226
- static get code(): "ERR_PROFILE_CLAIMS_VALIDATION_FAILED";
227
- readonly code: "ERR_PROFILE_CLAIMS_VALIDATION_FAILED";
228
- /** 復号結果 */
229
- result: {
230
- error?: JOSEError;
231
- errors?: ErrorObject[];
232
- payload?: JWTPayload;
233
- jwt: string;
234
- };
235
- constructor(message: string, result: ProfileClaimsValidationFailed["result"]);
236
- }
237
- declare class ProfileTokenVerifyFailed extends ProfileGenericError {
238
- static get code(): "ERR_PROFILE_TOKEN_VERIFY_FAILED";
239
- readonly code: "ERR_PROFILE_TOKEN_VERIFY_FAILED";
240
- /** 検証結果 */
241
- result: Exclude<DecodeResult, ProfileGenericError> & {
242
- error?: JOSEError;
243
- };
244
- constructor(message: string, result: ProfileTokenVerifyFailed["result"]);
245
- }
246
- declare class ProfileBodyExtractFailed extends ProfileGenericError {
247
- static get code(): "ERR_PROFILE_BODY_EXTRACT_FAILED";
248
- readonly code: "ERR_PROFILE_BODY_EXTRACT_FAILED";
249
- }
250
- declare class ProfileBodyVerifyFailed extends ProfileGenericError {
251
- static get code(): "ERR_PROFILE_BODY_VERIFY_FAILED";
252
- readonly code: "ERR_PROFILE_BODY_VERIFY_FAILED";
253
- /** 検証結果 */
254
- result: {
255
- error?: JOSEError;
256
- body: string;
257
- };
258
- constructor(message: string, result: ProfileBodyVerifyFailed["result"]);
259
- }
260
- declare class ProfilesResolveFailed extends ProfileGenericError {
261
- static get code(): "ERR_PROFILES_RESOLVE_FAILED";
262
- readonly code: "ERR_PROFILES_RESOLVE_FAILED";
263
- /** 検証結果 */
264
- result: Exclude<DecodeResult, ProfileGenericError>;
265
- constructor(message: string, result: ProfilesResolveFailed["result"]);
266
- }
267
- declare class ProfilesVerifyFailed extends ProfileGenericError {
268
- static get code(): "ERR_PROFILES_VERIFY_FAILED";
269
- readonly code: "ERR_PROFILES_VERIFY_FAILED";
270
- /** 検証結果 */
271
- result: Exclude<DecodeResult | VerifyTokenResult, ProfileGenericError>;
272
- constructor(message: string, result: ProfilesVerifyFailed["result"]);
273
- }
274
- declare class CertificationSystemValidationFailed extends ProfileGenericError {
275
- static get code(): "ERR_CERTIFICATION_SYSTEM_VALIDATION_FAILED";
276
- readonly code: "ERR_CERTIFICATION_SYSTEM_VALIDATION_FAILED";
277
- /** 検証結果 */
278
- result: {
279
- payload?: unknown;
280
- };
281
- constructor(message: string, result: CertificationSystemValidationFailed["result"]);
282
- }
283
-
284
195
  // Definitions by: Eddie Atkinson <https://github.com/eddie-atkinson>
285
196
 
286
197
  type Operation = "add" | "replace" | "remove" | "move";
@@ -548,16 +459,6 @@ type SpVerificationResult = VerifiedSp | SiteProfileInvalid | SiteProfileVerifyF
548
459
  */
549
460
  declare function SpVerifier(sp: SiteProfile, keys: Keys, issuer: string | string[], origin: URL["origin"], verifyOrigin?: boolean, validator?: typeof VcValidator): () => Promise<SpVerificationResult>;
550
461
 
551
- /** 認証制度ペイロードの確認のためのバリデーター */
552
- declare function CertificationSystemValidator(): (payload: unknown) => true | CertificationSystemValidationFailed;
553
- type CertificationSystemValidator = ReturnType<typeof CertificationSystemValidator>;
554
- /**
555
- * 認証制度の検証
556
- * @param payload ペイロード
557
- * @return 検証結果
558
- */
559
- declare function validateCertificationSystem(payload: unknown): CertificationSystem | CertificationSystemValidationFailed;
560
-
561
462
  /**
562
463
  * URLオリジンが対象のオリジンの中に含まれているのか検証する
563
464
  * @param origin 対象とするオリジン
@@ -566,4 +467,4 @@ declare function validateCertificationSystem(payload: unknown): CertificationSys
566
467
  */
567
468
  declare function verifyAllowedOrigin(origin: URL["origin"], allowedOrigins: AllowedOrigin): boolean;
568
469
 
569
- export { type AdProfilePair, type CaDecodingFailure, type CaDecodingResult, CaInvalid, type CaVerificationFailure, type CaVerificationResult, CaVerifier, CaVerifyFailed, type CasItem, type CasVerificationFailure, type CasVerificationResult, CasVerifyFailed, type Certificate, CertificateExpired, CertificationSystemValidationFailed, CertificationSystemValidator, CoreProfileNotFound, type DecodeResult, type DecodedCa, type DecodedOp, type DecodedOps, type IntegrityVerifyResult, type MappedKeys, type OpDecodingFailure, type OpDecodingResult, OpInvalid, type OpVerificationFailure, type OpVerificationResult, OpVerifyFailed, type OpsDecodingFailure, type OpsDecodingResult, OpsInvalid, type OpsVerificationFailure, type OpsVerificationResult, OpsVerifier, OpsVerifyFailed, ProfileBodyExtractFailed, ProfileBodyVerifyFailed, ProfileClaimsValidationFailed, ProfileGenericError, type ProfilePair, ProfileTokenVerifyFailed, type Profiles, ProfilesResolveFailed, ProfilesVerifyFailed, SiteProfileInvalid, SiteProfileVerifyFailed, type SpVerificationFailure, type SpVerificationResult, SpVerifier, TargetIntegrityAlgorithm, type TupledKeys, type VerifiedCa, type VerifiedCas, type VerifiedOp, type VerifiedOps, type VerifiedSp, type VerifyIntegrity, type VerifyResult, VerifyResultFactory, type VerifyResults, type VerifyTokenResult, type WebsiteProfilePair, article, caId, caUrl, certificate, cp, decodeOps, getMappedKeys, getTupledKeys, normalizeCasItem, opId, patch, validateCertificationSystem, verifyAllowedOrigin, verifyCas, verifyDigestSri, verifyIntegrity, wmp, wsp };
470
+ export { type CaDecodingFailure, type CaDecodingResult, CaInvalid, type CaVerificationFailure, type CaVerificationResult, CaVerifier, CaVerifyFailed, type CasItem, type CasVerificationFailure, type CasVerificationResult, CasVerifyFailed, type Certificate, CertificateExpired, CoreProfileNotFound, type DecodedCa, type DecodedOp, type DecodedOps, type FetchIntegrityResult, IntegrityFetchFailed, IntegrityVerificationFailed, type IntegrityVerifyResult, type MappedKeys, type OpDecodingFailure, type OpDecodingResult, OpInvalid, type OpVerificationFailure, type OpVerificationResult, OpVerifyFailed, type OpsDecodingFailure, type OpsDecodingResult, OpsInvalid, type OpsVerificationFailure, type OpsVerificationResult, OpsVerifier, OpsVerifyFailed, SiteProfileInvalid, SiteProfileVerifyFailed, type SpVerificationFailure, type SpVerificationResult, SpVerifier, TargetIntegrityAlgorithm, type TupledKeys, type VerifiedCa, type VerifiedCas, type VerifiedOp, type VerifiedOps, type VerifiedSp, type VerifyIntegrity, VerifyResultFactory, article, caId, caUrl, certificate, cp, decodeOps, getMappedKeys, getTupledKeys, normalizeCasItem, opId, patch, verifyAllowedOrigin, verifyCas, verifyDigestSri, verifyImageDigestSri, verifyIntegrity, wmp, wsp };
package/dist/index.d.mts CHANGED
@@ -1,10 +1,7 @@
1
- import { ContentAttestation, Target, ContentAttestationSet, JwtOpPayload, JwtDpPayload, Op, Dp, OpVc, Jwk, CoreProfile, Certificate as Certificate$1, WebMediaProfile, WebsiteProfile, ArticleCA, JapaneseExistenceCertificate, OriginatorProfileSet, Jwks, SiteProfile, CertificationSystem, AllowedOrigin } from '@originator-profile/model';
1
+ import { ContentAttestation, Image, Target, ContentAttestationSet, OpVc, Jwk, CoreProfile, Certificate as Certificate$1, WebMediaProfile, WebsiteProfile, ArticleCA, JapaneseExistenceCertificate, OriginatorProfileSet, Jwks, SiteProfile, AllowedOrigin } from '@originator-profile/model';
2
2
  import { JwtVcDecodingResult, JwtVcVerificationResult, UnverifiedJwtVc, VerifiedJwtVc, VcValidator } from '@originator-profile/securing-mechanism';
3
3
  import { Keys } from '@originator-profile/cryptography';
4
- import { DigestSriContent, ContentFetcher, ElementSelector } from '@originator-profile/sign';
5
- import { ErrorObject } from 'ajv';
6
- import { JWTVerifyResult, ResolvedKey, JWTPayload } from 'jose';
7
- import { JOSEError } from 'jose/errors';
4
+ import { DigestSriResult, ContentFetcher, ElementSelector } from '@originator-profile/sign';
8
5
 
9
6
  /** Content Attestation 復号失敗 */
10
7
  type CaDecodingFailure = JwtVcDecodingResult<ContentAttestation>;
@@ -47,7 +44,7 @@ declare class CaVerifyFailed extends Error {
47
44
  * @see {@link https://www.w3.org/TR/SRI/#the-integrity-attribute}
48
45
  * @example
49
46
  * ```ts
50
- * const content: DigestSriContent = {
47
+ * const content = {
51
48
  * id: "<URL>",
52
49
  * digestSRI: "sha256-...",
53
50
  * };
@@ -55,12 +52,36 @@ declare class CaVerifyFailed extends Error {
55
52
  * await verifyDigestSri(content); // true or false
56
53
  * ```
57
54
  */
58
- declare function verifyDigestSri(content: DigestSriContent, fetcher?: typeof fetch): Promise<boolean>;
55
+ declare function verifyDigestSri(content: DigestSriResult, fetcher?: typeof fetch): Promise<boolean>;
56
+ /**
57
+ * Image の digestSRI を検証する。
58
+ * 後方互換性の観点で、2027年までは検証失敗時に console.warn のみで処理を中断しない。
59
+ */
60
+ declare function verifyImageDigestSri(value: Image | undefined, fetcher?: typeof fetch): Promise<void>;
61
+
62
+ declare class IntegrityFetchFailed extends Error {
63
+ static get code(): "ERR_INTEGRITY_FETCH_FAILED";
64
+ readonly code: "ERR_INTEGRITY_FETCH_FAILED";
65
+ readonly ok = false;
66
+ /** 取得結果 */
67
+ result?: Error;
68
+ constructor(message: string, result: IntegrityFetchFailed["result"]);
69
+ }
70
+ declare class IntegrityVerificationFailed extends Error {
71
+ static get code(): "ERR_INTEGRITY_VERIFICATION_FAILED";
72
+ readonly code: "ERR_INTEGRITY_VERIFICATION_FAILED";
73
+ readonly ok = false;
74
+ /** 取得結果 */
75
+ result?: unknown;
76
+ constructor(message: string, result: IntegrityVerificationFailed["result"]);
77
+ }
59
78
 
60
79
  type IntegrityVerifyResult = {
61
80
  valid: boolean;
62
81
  failedIntegrities: ReadonlyArray<string>;
63
82
  };
83
+ type FetchIntegrityResult = IntegrityVerifyResult | IntegrityFetchFailed | IntegrityVerificationFailed;
84
+
64
85
  /** Target Integrity のコンテンツ取得・要素位置特定アルゴリズム */
65
86
  declare const TargetIntegrityAlgorithm: {
66
87
  HtmlTargetIntegrity: {
@@ -94,7 +115,7 @@ declare const TargetIntegrityAlgorithm: {
94
115
  * await verifyIntegrity(content); // true or false
95
116
  * ```
96
117
  */
97
- declare function verifyIntegrity(content: Target, doc?: Document, fetcher?: typeof fetch): Promise<IntegrityVerifyResult>;
118
+ declare function verifyIntegrity(content: Target, doc?: Document, fetcher?: typeof fetch): Promise<FetchIntegrityResult>;
98
119
  type VerifyIntegrity = typeof verifyIntegrity;
99
120
 
100
121
  /**
@@ -171,116 +192,6 @@ declare function normalizeCasItem<Ca>(ca: Ca | CasItem<Ca>): CasItem<Ca>;
171
192
  */
172
193
  declare function verifyCas<T extends ContentAttestation = ContentAttestation>(cas: ContentAttestationSet, verifiedOps: VerifiedOps, url: string, verifyIntegrity: VerifyIntegrity, validator?: typeof VcValidator): Promise<CasVerificationResult<T>>;
173
194
 
174
- interface ProfilePair {
175
- op: {
176
- iss: string;
177
- sub: string;
178
- profile: string;
179
- };
180
- dp: {
181
- sub: string;
182
- profile: string;
183
- };
184
- }
185
- interface WebsiteProfilePair {
186
- "@context": string;
187
- website: ProfilePair;
188
- }
189
- interface AdProfilePair {
190
- "@context": string;
191
- ad: ProfilePair;
192
- }
193
- /** Profile の Token の復号結果 */
194
- type DecodeResult = {
195
- op: true;
196
- payload: JwtOpPayload;
197
- jwt: string;
198
- } | {
199
- dp: true;
200
- payload: JwtDpPayload;
201
- jwt: string;
202
- } | ProfileClaimsValidationFailed;
203
- /** Profile の Token の検証結果 */
204
- type VerifyTokenResult = (JWTVerifyResult & ResolvedKey & ({
205
- op: Op;
206
- jwt: string;
207
- } | {
208
- dp: Dp;
209
- jwt: string;
210
- })) | ProfileClaimsValidationFailed | ProfileTokenVerifyFailed;
211
- /** Profile Set */
212
- type Profiles = {
213
- profile: string[];
214
- ad?: ProfilePair[];
215
- };
216
- /** Profile の検証結果 */
217
- type VerifyResult = VerifyTokenResult | ProfilesResolveFailed | ProfilesVerifyFailed;
218
- /** Profile Set の検証結果 */
219
- type VerifyResults = VerifyResult[];
220
-
221
- declare class ProfileGenericError extends Error {
222
- static get code(): string;
223
- readonly code: string;
224
- }
225
- declare class ProfileClaimsValidationFailed extends ProfileGenericError {
226
- static get code(): "ERR_PROFILE_CLAIMS_VALIDATION_FAILED";
227
- readonly code: "ERR_PROFILE_CLAIMS_VALIDATION_FAILED";
228
- /** 復号結果 */
229
- result: {
230
- error?: JOSEError;
231
- errors?: ErrorObject[];
232
- payload?: JWTPayload;
233
- jwt: string;
234
- };
235
- constructor(message: string, result: ProfileClaimsValidationFailed["result"]);
236
- }
237
- declare class ProfileTokenVerifyFailed extends ProfileGenericError {
238
- static get code(): "ERR_PROFILE_TOKEN_VERIFY_FAILED";
239
- readonly code: "ERR_PROFILE_TOKEN_VERIFY_FAILED";
240
- /** 検証結果 */
241
- result: Exclude<DecodeResult, ProfileGenericError> & {
242
- error?: JOSEError;
243
- };
244
- constructor(message: string, result: ProfileTokenVerifyFailed["result"]);
245
- }
246
- declare class ProfileBodyExtractFailed extends ProfileGenericError {
247
- static get code(): "ERR_PROFILE_BODY_EXTRACT_FAILED";
248
- readonly code: "ERR_PROFILE_BODY_EXTRACT_FAILED";
249
- }
250
- declare class ProfileBodyVerifyFailed extends ProfileGenericError {
251
- static get code(): "ERR_PROFILE_BODY_VERIFY_FAILED";
252
- readonly code: "ERR_PROFILE_BODY_VERIFY_FAILED";
253
- /** 検証結果 */
254
- result: {
255
- error?: JOSEError;
256
- body: string;
257
- };
258
- constructor(message: string, result: ProfileBodyVerifyFailed["result"]);
259
- }
260
- declare class ProfilesResolveFailed extends ProfileGenericError {
261
- static get code(): "ERR_PROFILES_RESOLVE_FAILED";
262
- readonly code: "ERR_PROFILES_RESOLVE_FAILED";
263
- /** 検証結果 */
264
- result: Exclude<DecodeResult, ProfileGenericError>;
265
- constructor(message: string, result: ProfilesResolveFailed["result"]);
266
- }
267
- declare class ProfilesVerifyFailed extends ProfileGenericError {
268
- static get code(): "ERR_PROFILES_VERIFY_FAILED";
269
- readonly code: "ERR_PROFILES_VERIFY_FAILED";
270
- /** 検証結果 */
271
- result: Exclude<DecodeResult | VerifyTokenResult, ProfileGenericError>;
272
- constructor(message: string, result: ProfilesVerifyFailed["result"]);
273
- }
274
- declare class CertificationSystemValidationFailed extends ProfileGenericError {
275
- static get code(): "ERR_CERTIFICATION_SYSTEM_VALIDATION_FAILED";
276
- readonly code: "ERR_CERTIFICATION_SYSTEM_VALIDATION_FAILED";
277
- /** 検証結果 */
278
- result: {
279
- payload?: unknown;
280
- };
281
- constructor(message: string, result: CertificationSystemValidationFailed["result"]);
282
- }
283
-
284
195
  // Definitions by: Eddie Atkinson <https://github.com/eddie-atkinson>
285
196
 
286
197
  type Operation = "add" | "replace" | "remove" | "move";
@@ -548,16 +459,6 @@ type SpVerificationResult = VerifiedSp | SiteProfileInvalid | SiteProfileVerifyF
548
459
  */
549
460
  declare function SpVerifier(sp: SiteProfile, keys: Keys, issuer: string | string[], origin: URL["origin"], verifyOrigin?: boolean, validator?: typeof VcValidator): () => Promise<SpVerificationResult>;
550
461
 
551
- /** 認証制度ペイロードの確認のためのバリデーター */
552
- declare function CertificationSystemValidator(): (payload: unknown) => true | CertificationSystemValidationFailed;
553
- type CertificationSystemValidator = ReturnType<typeof CertificationSystemValidator>;
554
- /**
555
- * 認証制度の検証
556
- * @param payload ペイロード
557
- * @return 検証結果
558
- */
559
- declare function validateCertificationSystem(payload: unknown): CertificationSystem | CertificationSystemValidationFailed;
560
-
561
462
  /**
562
463
  * URLオリジンが対象のオリジンの中に含まれているのか検証する
563
464
  * @param origin 対象とするオリジン
@@ -566,4 +467,4 @@ declare function validateCertificationSystem(payload: unknown): CertificationSys
566
467
  */
567
468
  declare function verifyAllowedOrigin(origin: URL["origin"], allowedOrigins: AllowedOrigin): boolean;
568
469
 
569
- export { type AdProfilePair, type CaDecodingFailure, type CaDecodingResult, CaInvalid, type CaVerificationFailure, type CaVerificationResult, CaVerifier, CaVerifyFailed, type CasItem, type CasVerificationFailure, type CasVerificationResult, CasVerifyFailed, type Certificate, CertificateExpired, CertificationSystemValidationFailed, CertificationSystemValidator, CoreProfileNotFound, type DecodeResult, type DecodedCa, type DecodedOp, type DecodedOps, type IntegrityVerifyResult, type MappedKeys, type OpDecodingFailure, type OpDecodingResult, OpInvalid, type OpVerificationFailure, type OpVerificationResult, OpVerifyFailed, type OpsDecodingFailure, type OpsDecodingResult, OpsInvalid, type OpsVerificationFailure, type OpsVerificationResult, OpsVerifier, OpsVerifyFailed, ProfileBodyExtractFailed, ProfileBodyVerifyFailed, ProfileClaimsValidationFailed, ProfileGenericError, type ProfilePair, ProfileTokenVerifyFailed, type Profiles, ProfilesResolveFailed, ProfilesVerifyFailed, SiteProfileInvalid, SiteProfileVerifyFailed, type SpVerificationFailure, type SpVerificationResult, SpVerifier, TargetIntegrityAlgorithm, type TupledKeys, type VerifiedCa, type VerifiedCas, type VerifiedOp, type VerifiedOps, type VerifiedSp, type VerifyIntegrity, type VerifyResult, VerifyResultFactory, type VerifyResults, type VerifyTokenResult, type WebsiteProfilePair, article, caId, caUrl, certificate, cp, decodeOps, getMappedKeys, getTupledKeys, normalizeCasItem, opId, patch, validateCertificationSystem, verifyAllowedOrigin, verifyCas, verifyDigestSri, verifyIntegrity, wmp, wsp };
470
+ export { type CaDecodingFailure, type CaDecodingResult, CaInvalid, type CaVerificationFailure, type CaVerificationResult, CaVerifier, CaVerifyFailed, type CasItem, type CasVerificationFailure, type CasVerificationResult, CasVerifyFailed, type Certificate, CertificateExpired, CoreProfileNotFound, type DecodedCa, type DecodedOp, type DecodedOps, type FetchIntegrityResult, IntegrityFetchFailed, IntegrityVerificationFailed, type IntegrityVerifyResult, type MappedKeys, type OpDecodingFailure, type OpDecodingResult, OpInvalid, type OpVerificationFailure, type OpVerificationResult, OpVerifyFailed, type OpsDecodingFailure, type OpsDecodingResult, OpsInvalid, type OpsVerificationFailure, type OpsVerificationResult, OpsVerifier, OpsVerifyFailed, SiteProfileInvalid, SiteProfileVerifyFailed, type SpVerificationFailure, type SpVerificationResult, SpVerifier, TargetIntegrityAlgorithm, type TupledKeys, type VerifiedCa, type VerifiedCas, type VerifiedOp, type VerifiedOps, type VerifiedSp, type VerifyIntegrity, VerifyResultFactory, article, caId, caUrl, certificate, cp, decodeOps, getMappedKeys, getTupledKeys, normalizeCasItem, opId, patch, verifyAllowedOrigin, verifyCas, verifyDigestSri, verifyImageDigestSri, verifyIntegrity, wmp, wsp };
package/dist/index.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  import { JwtVcVerifier, VcValidateFailed, VcVerifyFailed, JwtVcDecoder } from '@originator-profile/securing-mechanism';
2
- import { createDigestSri, selectByIntegrity, fetchExternalResource, selectByCss, fetchVisibleTextContent, fetchTextContent, fetchHtmlContent } from '@originator-profile/sign';
2
+ import { createDigestSri, selectByIntegrity, fetchExternalResource, selectByCss, fetchVisibleTextContent, fetchTextContent, fetchHtmlContent, FetchFailed } from '@originator-profile/sign';
3
3
  import { LocalKeys } from '@originator-profile/cryptography';
4
- import { ContentAttestation, CoreProfile, Certificate, JapaneseExistenceCertificate, WebMediaProfile, WebsiteProfile, CertificationSystem } from '@originator-profile/model';
4
+ import { ContentAttestation, CoreProfile, Certificate, JapaneseExistenceCertificate, WebMediaProfile, WebsiteProfile } from '@originator-profile/model';
5
+ import { z } from 'zod';
5
6
 
6
7
  class CaInvalid extends Error {
7
8
  constructor(message, result) {
@@ -298,12 +299,62 @@ async function createIntegrityMetadataSet(hashAlgorithms, data, options = {
298
299
  return new IntegrityMetadataSet(set, options);
299
300
  }
300
301
 
302
+ const WARN_SUFFIX = `This will become an error after 2027. See: https://docs.originator-profile.org/en/opb/context/#the-image-datatype`;
301
303
  async function verifyDigestSri(content, fetcher = fetch) {
302
304
  const integrity = new IntegrityMetadataSet(content.digestSRI);
303
305
  const alg = integrity.strongestHashAlgorithms.filter(Boolean);
304
306
  if (alg.length === 0) return false;
305
- const { digestSRI } = await createDigestSri(alg[0], content, fetcher);
306
- return integrity.match(digestSRI);
307
+ try {
308
+ const result = await createDigestSri(alg[0], content, fetcher);
309
+ return "digestSRI" in result && integrity.match(result.digestSRI);
310
+ } catch (error) {
311
+ console.error(
312
+ "Failed to access content for digestSRI verification:",
313
+ error
314
+ );
315
+ return false;
316
+ }
317
+ }
318
+ async function verifyImageDigestSri(value, fetcher = fetch) {
319
+ if (!value) return;
320
+ if (!value.digestSRI) {
321
+ console.warn(`digestSRI is missing. ${WARN_SUFFIX}`);
322
+ return;
323
+ }
324
+ const valid = await verifyDigestSri(
325
+ { id: value.id, digestSRI: value.digestSRI },
326
+ fetcher
327
+ );
328
+ if (!valid) {
329
+ console.warn(`digestSRI verification failed. ${WARN_SUFFIX}`);
330
+ }
331
+ }
332
+
333
+ class IntegrityFetchFailed extends Error {
334
+ static get code() {
335
+ return "ERR_INTEGRITY_FETCH_FAILED";
336
+ }
337
+ code = IntegrityFetchFailed.code;
338
+ ok = false;
339
+ /** 取得結果 */
340
+ result;
341
+ constructor(message, result) {
342
+ super(message);
343
+ this.result = result;
344
+ }
345
+ }
346
+ class IntegrityVerificationFailed extends Error {
347
+ static get code() {
348
+ return "ERR_INTEGRITY_VERIFICATION_FAILED";
349
+ }
350
+ code = IntegrityVerificationFailed.code;
351
+ ok = false;
352
+ /** 取得結果 */
353
+ result;
354
+ constructor(message, result) {
355
+ super(message);
356
+ this.result = result;
357
+ }
307
358
  }
308
359
 
309
360
  class IntegrityVerifier {
@@ -352,7 +403,14 @@ async function verifyIntegrity(content, doc = document, fetcher = fetch) {
352
403
  (content2) => contentFetcher(content2, fetcher),
353
404
  elementSelector
354
405
  );
355
- return await integrityVerifier.verify(content, doc);
406
+ try {
407
+ return await integrityVerifier.verify(content, doc);
408
+ } catch (e) {
409
+ if (e instanceof FetchFailed) {
410
+ return new IntegrityFetchFailed("Verify integrity failed", e.error);
411
+ }
412
+ return new IntegrityVerificationFailed("Verify integrity failed", e);
413
+ }
356
414
  }
357
415
 
358
416
  function verifyAllowedOrigin(origin, allowedOrigins) {
@@ -378,8 +436,13 @@ async function verifyAllowedUrl(url, allowedUrl) {
378
436
  if (!value) {
379
437
  return false;
380
438
  }
381
- const pattern = new URLPattern(ReplaceEncode(value));
382
- return pattern.test(ReplaceEncode(url));
439
+ try {
440
+ const pattern = new URLPattern(ReplaceEncode(value));
441
+ return pattern.test(ReplaceEncode(url));
442
+ } catch (e) {
443
+ console.error(`Invalid URLPattern: ${value} (url: ${url})`);
444
+ }
445
+ return false;
383
446
  });
384
447
  }
385
448
 
@@ -406,6 +469,32 @@ async function checkUrlAndOrigin(result, url) {
406
469
  }
407
470
  return result;
408
471
  }
472
+ function checkIntegrityResults(integrityResults, urlResult) {
473
+ const fetchFailedResults = integrityResults.filter(
474
+ (r) => r.verifyResult instanceof Error && r.verifyResult.code === IntegrityFetchFailed.code
475
+ );
476
+ if (fetchFailedResults.length > 0) {
477
+ const failedIntegritiesMessage = fetchFailedResults.map((result) => {
478
+ return `target[${result.index}] Expected: ${result.expectedIntegrity}`;
479
+ }).join(", ");
480
+ return new CaVerifyFailed(
481
+ `Content Attestation Target integrity fetch failed for element(s): ${failedIntegritiesMessage}`,
482
+ urlResult
483
+ );
484
+ }
485
+ const verificationFailedResults = integrityResults.filter(
486
+ (r) => r.verifyResult instanceof Error && r.verifyResult.code === IntegrityVerificationFailed.code
487
+ );
488
+ if (verificationFailedResults.length > 0) {
489
+ const failedIntegritiesMessage = verificationFailedResults.map((result) => {
490
+ return `target[${result.index}] Expected: ${result.expectedIntegrity}`;
491
+ }).join(", ");
492
+ return new CaVerifyFailed(
493
+ `Content Attestation Target integrity verification failed for element(s): ${failedIntegritiesMessage}`,
494
+ urlResult
495
+ );
496
+ }
497
+ }
409
498
  function CaVerifier(ca, keys, issuer, url, verifyIntegrity$1 = verifyIntegrity, validator) {
410
499
  const verifyCa = JwtVcVerifier(keys, issuer, validator);
411
500
  return async () => {
@@ -420,6 +509,9 @@ function CaVerifier(ca, keys, issuer, url, verifyIntegrity$1 = verifyIntegrity,
420
509
  if (urlResult instanceof Error) {
421
510
  return urlResult;
422
511
  }
512
+ await verifyImageDigestSri(
513
+ urlResult.doc.credentialSubject.image
514
+ );
423
515
  if (urlResult.doc.target) {
424
516
  if (urlResult.doc.target.length === 0) {
425
517
  return new CaInvalid("Target is empty", urlResult);
@@ -431,12 +523,19 @@ function CaVerifier(ca, keys, issuer, url, verifyIntegrity$1 = verifyIntegrity,
431
523
  expectedIntegrity: t.integrity
432
524
  }))
433
525
  );
434
- const failedIndices = integrityResults.filter((result2) => !result2.verifyResult.valid).map((result2) => result2.index);
526
+ const error = checkIntegrityResults(integrityResults, urlResult);
527
+ if (error) {
528
+ return error;
529
+ }
530
+ const failedIndices = integrityResults.filter(
531
+ (result2) => !(result2.verifyResult instanceof Error) && !result2.verifyResult.valid
532
+ ).map((result2) => result2.index);
435
533
  if (failedIndices.length > 0) {
436
534
  const failedIntegritiesMessage = failedIndices.map((integrityResultIndex) => {
437
535
  const integrityResult = integrityResults[integrityResultIndex];
438
536
  if (integrityResult) {
439
- const calculatedIntegrities = integrityResult.verifyResult.failedIntegrities.join();
537
+ const verifyResult = integrityResult.verifyResult;
538
+ const calculatedIntegrities = verifyResult.failedIntegrities.join();
440
539
  return `target[${integrityResultIndex}] Expected: ${integrityResult.expectedIntegrity}, Calculated: ${calculatedIntegrities}`;
441
540
  }
442
541
  return void 0;
@@ -512,91 +611,6 @@ async function verifyCas(cas, verifiedOps, url, verifyIntegrity, validator) {
512
611
  return resultCas;
513
612
  }
514
613
 
515
- class ProfileGenericError extends Error {
516
- static get code() {
517
- return "ERR_PROFILE_GENERIC";
518
- }
519
- code = ProfileGenericError.code;
520
- }
521
- class ProfileClaimsValidationFailed extends ProfileGenericError {
522
- static get code() {
523
- return "ERR_PROFILE_CLAIMS_VALIDATION_FAILED";
524
- }
525
- code = ProfileClaimsValidationFailed.code;
526
- /** 復号結果 */
527
- result;
528
- constructor(message, result) {
529
- super(message);
530
- this.result = result;
531
- }
532
- }
533
- class ProfileTokenVerifyFailed extends ProfileGenericError {
534
- static get code() {
535
- return "ERR_PROFILE_TOKEN_VERIFY_FAILED";
536
- }
537
- code = ProfileTokenVerifyFailed.code;
538
- /** 検証結果 */
539
- result;
540
- constructor(message, result) {
541
- super(message);
542
- this.result = result;
543
- }
544
- }
545
- class ProfileBodyExtractFailed extends ProfileGenericError {
546
- static get code() {
547
- return "ERR_PROFILE_BODY_EXTRACT_FAILED";
548
- }
549
- code = ProfileBodyExtractFailed.code;
550
- }
551
- class ProfileBodyVerifyFailed extends ProfileGenericError {
552
- static get code() {
553
- return "ERR_PROFILE_BODY_VERIFY_FAILED";
554
- }
555
- code = ProfileBodyVerifyFailed.code;
556
- /** 検証結果 */
557
- result;
558
- constructor(message, result) {
559
- super(message);
560
- this.result = result;
561
- }
562
- }
563
- class ProfilesResolveFailed extends ProfileGenericError {
564
- static get code() {
565
- return "ERR_PROFILES_RESOLVE_FAILED";
566
- }
567
- code = ProfilesResolveFailed.code;
568
- /** 検証結果 */
569
- result;
570
- constructor(message, result) {
571
- super(message);
572
- this.result = result;
573
- }
574
- }
575
- class ProfilesVerifyFailed extends ProfileGenericError {
576
- static get code() {
577
- return "ERR_PROFILES_VERIFY_FAILED";
578
- }
579
- code = ProfilesVerifyFailed.code;
580
- /** 検証結果 */
581
- result;
582
- constructor(message, result) {
583
- super(message);
584
- this.result = result;
585
- }
586
- }
587
- class CertificationSystemValidationFailed extends ProfileGenericError {
588
- static get code() {
589
- return "ERR_CERTIFICATION_SYSTEM_VALIDATION_FAILED";
590
- }
591
- code = CertificationSystemValidationFailed.code;
592
- /** 検証結果 */
593
- result;
594
- constructor(message, result) {
595
- super(message);
596
- this.result = result;
597
- }
598
- }
599
-
600
614
  var REMOVE = "remove";
601
615
  var REPLACE = "replace";
602
616
  var ADD = "add";
@@ -982,28 +996,38 @@ async function verifyAnnotations(paIssuerKeys, annotations, validator) {
982
996
  const verify = OpVerifier(
983
997
  paIssuerKeys,
984
998
  annotation,
985
- validator?.({
986
- oneOf: [Certificate, JapaneseExistenceCertificate]
987
- })
999
+ validator?.(z.union([Certificate, JapaneseExistenceCertificate]))
988
1000
  );
989
1001
  const result = await verify(annotation.source);
990
1002
  if (result instanceof Error) {
991
1003
  return result;
992
1004
  }
993
- return validateCertificateExpiry(result);
1005
+ const valid = validateCertificateExpiry(result);
1006
+ if (valid instanceof CertificateExpired) {
1007
+ return valid;
1008
+ }
1009
+ await verifyImageDigestSri(
1010
+ valid.doc.credentialSubject.image
1011
+ );
1012
+ return valid;
994
1013
  })
995
1014
  );
996
1015
  }
997
1016
  async function verifyMedia(wmpIssuerKeys, media, validator) {
998
1017
  if (!media) return;
999
1018
  return await Promise.all(
1000
- media.map((m) => {
1019
+ media.map(async (m) => {
1001
1020
  const verify = OpVerifier(
1002
1021
  wmpIssuerKeys,
1003
1022
  m,
1004
1023
  validator?.(WebMediaProfile)
1005
1024
  );
1006
- return verify(m.source);
1025
+ const result = await verify(m.source);
1026
+ if (result instanceof Error) {
1027
+ return result;
1028
+ }
1029
+ await verifyImageDigestSri(result.doc.credentialSubject.logo);
1030
+ return result;
1007
1031
  })
1008
1032
  );
1009
1033
  }
@@ -1148,11 +1172,12 @@ function SpVerifier(sp, keys, issuer, origin, verifyOrigin = true, validator) {
1148
1172
  return verified;
1149
1173
  }
1150
1174
  if (verifyOrigin) {
1151
- const allowedOrigin = "allowedOrigin" in decodedWsp.doc.credentialSubject ? decodedWsp.doc.credentialSubject.allowedOrigin : decodedWsp.doc.credentialSubject.url;
1175
+ const allowedOrigin = "allowedOrigin" in verified.doc.credentialSubject ? verified.doc.credentialSubject.allowedOrigin : verified.doc.credentialSubject.url;
1152
1176
  if (!verifyAllowedOrigin(origin, allowedOrigin)) {
1153
1177
  return new Error("Origin not allowed");
1154
1178
  }
1155
1179
  }
1180
+ await verifyImageDigestSri(verified.doc.credentialSubject.image);
1156
1181
  return verified;
1157
1182
  })
1158
1183
  );
@@ -1180,63 +1205,4 @@ function SpVerifier(sp, keys, issuer, origin, verifyOrigin = true, validator) {
1180
1205
  return verify;
1181
1206
  }
1182
1207
 
1183
- var objectTypeof = typeOf;
1184
- function typeOf(obj) {
1185
- if (obj === null) {
1186
- return "null";
1187
- }
1188
- if (obj !== Object(obj)) {
1189
- return typeof obj;
1190
- }
1191
- var result = {}.toString.call(obj).slice(8, -1).toLowerCase();
1192
- return result.indexOf("function") > -1 ? "function" : result;
1193
- }
1194
-
1195
- function CertificationSystemValidator() {
1196
- return function validate(payload) {
1197
- if (objectTypeof(payload) !== "object") {
1198
- return new CertificationSystemValidationFailed("should be an object", {
1199
- payload
1200
- });
1201
- }
1202
- const keys = Object.keys(payload);
1203
- const entries = Object.entries(payload);
1204
- if (!CertificationSystem.required.every((k) => keys.includes(k))) {
1205
- return new CertificationSystemValidationFailed(
1206
- "should be contain required properties",
1207
- { payload }
1208
- );
1209
- }
1210
- for (const entry of entries) {
1211
- const [key, value] = entry;
1212
- const propertySchema = CertificationSystem.properties[key];
1213
- if (objectTypeof(propertySchema) !== "object") {
1214
- return new CertificationSystemValidationFailed(
1215
- "should not contain additional properties",
1216
- { payload }
1217
- );
1218
- }
1219
- if ("const" in propertySchema && value !== propertySchema.const)
1220
- return new CertificationSystemValidationFailed(
1221
- `should be contain value of '${value}' in '${key}' property`,
1222
- { payload }
1223
- );
1224
- if ("type" in propertySchema && typeof value !== propertySchema.type)
1225
- return new CertificationSystemValidationFailed(
1226
- `should be contain ${propertySchema.type} value in '${key}' property`,
1227
- { payload }
1228
- );
1229
- }
1230
- return true;
1231
- };
1232
- }
1233
- function validateCertificationSystem(payload) {
1234
- const validator = CertificationSystemValidator();
1235
- const result = validator(payload);
1236
- if (result !== true) {
1237
- return result;
1238
- }
1239
- return payload;
1240
- }
1241
-
1242
- export { CaInvalid, CaVerifier, CaVerifyFailed, CasVerifyFailed, CertificateExpired, CertificationSystemValidationFailed, CertificationSystemValidator, CoreProfileNotFound, OpInvalid, OpVerifyFailed, OpsInvalid, OpsVerifier, OpsVerifyFailed, ProfileBodyExtractFailed, ProfileBodyVerifyFailed, ProfileClaimsValidationFailed, ProfileGenericError, ProfileTokenVerifyFailed, ProfilesResolveFailed, ProfilesVerifyFailed, SiteProfileInvalid, SiteProfileVerifyFailed, SpVerifier, TargetIntegrityAlgorithm, VerifyResultFactory, article, caId, caUrl, certificate, cp, decodeOps, getMappedKeys, getTupledKeys, normalizeCasItem, opId, patch, validateCertificationSystem, verifyAllowedOrigin, verifyCas, verifyDigestSri, verifyIntegrity, wmp, wsp };
1208
+ export { CaInvalid, CaVerifier, CaVerifyFailed, CasVerifyFailed, CertificateExpired, CoreProfileNotFound, IntegrityFetchFailed, IntegrityVerificationFailed, OpInvalid, OpVerifyFailed, OpsInvalid, OpsVerifier, OpsVerifyFailed, SiteProfileInvalid, SiteProfileVerifyFailed, SpVerifier, TargetIntegrityAlgorithm, VerifyResultFactory, article, caId, caUrl, certificate, cp, decodeOps, getMappedKeys, getTupledKeys, normalizeCasItem, opId, patch, verifyAllowedOrigin, verifyCas, verifyDigestSri, verifyImageDigestSri, verifyIntegrity, wmp, wsp };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@originator-profile/verify",
3
- "version": "0.5.0-beta.1",
3
+ "version": "0.5.0-beta.2",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://docs.originator-profile.org",
6
6
  "repository": {
@@ -30,15 +30,14 @@
30
30
  ],
31
31
  "dependencies": {
32
32
  "@types/jsonld": "^1.5.15",
33
- "ajv": "^8.17.1",
34
- "ajv-formats": "^3.0.1",
35
33
  "jose": "^6.0.10",
36
34
  "jsonld": "^9.0.0",
37
- "@originator-profile/cryptography": "0.5.0-beta.1",
38
- "@originator-profile/model": "0.5.0-beta.1",
39
- "@originator-profile/securing-mechanism": "0.5.0-beta.1",
40
- "@originator-profile/core": "0.5.0-beta.1",
41
- "@originator-profile/sign": "0.5.0-beta.1"
35
+ "zod": "^4.3.6",
36
+ "@originator-profile/model": "0.5.0-beta.2",
37
+ "@originator-profile/cryptography": "0.5.0-beta.2",
38
+ "@originator-profile/core": "0.5.0-beta.2",
39
+ "@originator-profile/sign": "0.5.0-beta.2",
40
+ "@originator-profile/securing-mechanism": "0.5.0-beta.2"
42
41
  },
43
42
  "devDependencies": {
44
43
  "@playwright/test": "^1.57.0",
@@ -54,8 +53,8 @@
54
53
  "vite": "^7.0.0",
55
54
  "vitest": "^4.0.0",
56
55
  "websri": "^1.0.1",
57
- "@originator-profile/tsconfig": "0.5.0-beta.1",
58
- "eslint-config-originator-profile": "0.5.0-beta.1"
56
+ "eslint-config-originator-profile": "0.5.0-beta.2",
57
+ "@originator-profile/tsconfig": "0.5.0-beta.2"
59
58
  },
60
59
  "scripts": {
61
60
  "build": "pkgroll --clean-dist --target=node20",