@originator-profile/verify 0.5.1 → 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.d.mts → index.d.ts} +3 -2
- package/dist/{index.mjs → index.js} +85 -27
- package/package.json +24 -30
- package/dist/index-D-j8gXz_.cjs +0 -772
- package/dist/index.cjs +0 -1245
- package/dist/index.d.cts +0 -471
- /package/dist/{index-CQxI_8IG.mjs → index-CQxI_8IG.js} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ContentAttestation, Image, Target, ContentAttestationSet, OpVc, Jwk, ArticleCA, Certificate as Certificate$1, CoreProfile, WebMediaProfile, WebsiteProfile, JapaneseExistenceCertificate, OriginatorProfileSet, Jwks, SiteProfile, AllowedOrigin } from '@originator-profile/model';
|
|
1
|
+
import { ContentAttestation, Image, Target, ContentAttestationSet, OpVc, Jwk, ArticleCA, Certificate as Certificate$1, CoreProfile, WebMediaProfile, WebsiteProfile, JapaneseExistenceCertificate, ProfileAnnotation, JapaneseExistencePA, ProfileAnnotationIssuerRegistration, OriginatorProfileSet, Jwks, SiteProfile, AllowedOrigin } from '@originator-profile/model';
|
|
2
2
|
import { JwtVcDecodingResult, UnverifiedJwtVc, JwtVcVerificationResult, VerifiedJwtVc, VcValidator } from '@originator-profile/securing-mechanism';
|
|
3
3
|
import { Keys } from '@originator-profile/cryptography';
|
|
4
4
|
import { DigestSriResult, ContentFetcher, ElementSelector } from '@originator-profile/sign';
|
|
@@ -344,7 +344,8 @@ declare class CertificateExpired<T extends OpVc> extends Error {
|
|
|
344
344
|
constructor(message: string, result: VerifiedJwtVc<T>);
|
|
345
345
|
}
|
|
346
346
|
|
|
347
|
-
|
|
347
|
+
/** @deprecated Profile Annotation とその派生として整理する可能性あるため "Certificate" の利用は非推奨 */
|
|
348
|
+
type Certificate = Certificate$1 | JapaneseExistenceCertificate | ProfileAnnotation | JapaneseExistencePA | ProfileAnnotationIssuerRegistration;
|
|
348
349
|
/** Originator Profile 復号失敗 */
|
|
349
350
|
type OpDecodingFailure = {
|
|
350
351
|
core: JwtVcDecodingResult<CoreProfile>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { JwtVcVerifier, VcValidateFailed, VcVerifyFailed, JwtVcDecoder } from '@originator-profile/securing-mechanism';
|
|
2
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,
|
|
4
|
+
import { ContentAttestation, JapaneseExistencePA, ProfileAnnotationIssuerRegistration, ProfileAnnotation, JapaneseExistenceCertificate, Certificate, WebMediaProfile, CoreProfile, WebsiteProfile } from '@originator-profile/model';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
|
|
7
7
|
class CaInvalid extends Error {
|
|
@@ -422,7 +422,7 @@ function verifyAllowedOrigin(origin, allowedOrigins) {
|
|
|
422
422
|
|
|
423
423
|
async function importURLPatternPolyfill() {
|
|
424
424
|
if (typeof URLPattern === "undefined") {
|
|
425
|
-
await import('./index-CQxI_8IG.
|
|
425
|
+
await import('./index-CQxI_8IG.js');
|
|
426
426
|
}
|
|
427
427
|
}
|
|
428
428
|
function ReplaceEncode(url) {
|
|
@@ -912,29 +912,48 @@ class CertificateExpired extends Error {
|
|
|
912
912
|
|
|
913
913
|
const isEveryDecodedPa = (annotations) => annotations.every((annotation) => "doc" in annotation);
|
|
914
914
|
const isEveryDecodedWmp = (media) => media.every((m) => "doc" in m);
|
|
915
|
-
const
|
|
915
|
+
const failedPaths = (items, opIndex, prefix, isFailed) => items.map(
|
|
916
|
+
(item, index) => isFailed(item) ? `OP[${opIndex}].${prefix}[${index}]` : null
|
|
917
|
+
).filter((path) => path !== null);
|
|
918
|
+
const validateDecodedOp = (core, annotations, media, resultOp, opIndex) => {
|
|
916
919
|
if (annotations && !isEveryDecodedPa(annotations)) {
|
|
917
|
-
|
|
920
|
+
const paths = failedPaths(annotations, opIndex, "PA", (a) => !("doc" in a));
|
|
921
|
+
return new OpInvalid(
|
|
922
|
+
`Profile Annotation decode failed (${paths.join(", ")})`,
|
|
923
|
+
resultOp
|
|
924
|
+
);
|
|
918
925
|
}
|
|
919
926
|
if (media && !isEveryDecodedWmp(media)) {
|
|
920
|
-
|
|
927
|
+
const paths = failedPaths(media, opIndex, "WMP", (m) => !("doc" in m));
|
|
928
|
+
return new OpInvalid(
|
|
929
|
+
`Web Media Profile decode failed (${paths.join(", ")})`,
|
|
930
|
+
resultOp
|
|
931
|
+
);
|
|
921
932
|
}
|
|
933
|
+
const subjectMismatchErrors = [];
|
|
922
934
|
if (media && media.some(
|
|
923
935
|
(m) => core.doc.credentialSubject.id !== m.doc.credentialSubject.id
|
|
924
936
|
)) {
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
937
|
+
const details = media.map(
|
|
938
|
+
(m, index) => core.doc.credentialSubject.id !== m.doc.credentialSubject.id ? `OP[${opIndex}].WMP[${index}] issuer: ${m.doc.issuer}, subject: ${m.doc.credentialSubject.id}` : null
|
|
939
|
+
).filter((d) => d !== null);
|
|
940
|
+
subjectMismatchErrors.push(
|
|
941
|
+
`Subject mismatch between Core Profile and Web Media Profile (${details.join(", ")})`
|
|
928
942
|
);
|
|
929
943
|
}
|
|
930
944
|
if (annotations && annotations.some(
|
|
931
945
|
(annotation) => core.doc.credentialSubject.id !== annotation.doc.credentialSubject.id
|
|
932
946
|
)) {
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
947
|
+
const details = annotations.map(
|
|
948
|
+
(a, index) => core.doc.credentialSubject.id !== a.doc.credentialSubject.id ? `OP[${opIndex}].PA[${index}] issuer: ${a.doc.issuer}, subject: ${a.doc.credentialSubject.id}` : null
|
|
949
|
+
).filter((d) => d !== null);
|
|
950
|
+
subjectMismatchErrors.push(
|
|
951
|
+
`Subject mismatch between Core Profile and Profile Annotation (${details.join(", ")})`
|
|
936
952
|
);
|
|
937
953
|
}
|
|
954
|
+
if (subjectMismatchErrors.length > 0) {
|
|
955
|
+
return new OpInvalid(subjectMismatchErrors.join("\n"), resultOp);
|
|
956
|
+
}
|
|
938
957
|
return { type: "valid", annotations, media };
|
|
939
958
|
};
|
|
940
959
|
const isDecodedOps = (ops) => ops.every((op) => !(op instanceof OpInvalid));
|
|
@@ -942,7 +961,7 @@ function decodeOps(ops) {
|
|
|
942
961
|
const decodeCp = JwtVcDecoder();
|
|
943
962
|
const decodePa = JwtVcDecoder();
|
|
944
963
|
const decodeWmp = JwtVcDecoder();
|
|
945
|
-
const resultOps = ops.map((op) => {
|
|
964
|
+
const resultOps = ops.map((op, opIndex) => {
|
|
946
965
|
const core = decodeCp(op.core);
|
|
947
966
|
const annotations = op.annotations ? op.annotations.map(decodePa) : void 0;
|
|
948
967
|
const mediaInput = op.media;
|
|
@@ -950,9 +969,18 @@ function decodeOps(ops) {
|
|
|
950
969
|
const media = mediaArray ? mediaArray.map(decodeWmp) : void 0;
|
|
951
970
|
const resultOp = { core, annotations, media };
|
|
952
971
|
if (core instanceof Error) {
|
|
953
|
-
return new OpInvalid(
|
|
972
|
+
return new OpInvalid(
|
|
973
|
+
`Core Profile decode failed (OP[${opIndex}])`,
|
|
974
|
+
resultOp
|
|
975
|
+
);
|
|
954
976
|
}
|
|
955
|
-
const validated = validateDecodedOp(
|
|
977
|
+
const validated = validateDecodedOp(
|
|
978
|
+
core,
|
|
979
|
+
annotations,
|
|
980
|
+
media,
|
|
981
|
+
resultOp,
|
|
982
|
+
opIndex
|
|
983
|
+
);
|
|
956
984
|
if (validated instanceof OpInvalid) {
|
|
957
985
|
return validated;
|
|
958
986
|
}
|
|
@@ -963,7 +991,9 @@ function decodeOps(ops) {
|
|
|
963
991
|
};
|
|
964
992
|
});
|
|
965
993
|
if (!isDecodedOps(resultOps)) {
|
|
966
|
-
|
|
994
|
+
const invalidIndexes = resultOps.map((op, index) => op instanceof OpInvalid ? index : null).filter((i) => i !== null);
|
|
995
|
+
const msg = invalidIndexes.length > 0 ? `Invalid Originator Profile Set (${invalidIndexes.map((i) => `OP[${i}]`).join(", ")})` : "Invalid Originator Profile Set";
|
|
996
|
+
return new OpsInvalid(msg, resultOps);
|
|
967
997
|
}
|
|
968
998
|
return resultOps;
|
|
969
999
|
}
|
|
@@ -977,6 +1007,7 @@ function OpVerifier(paOrWmpIssuerKeys, vc, validator) {
|
|
|
977
1007
|
const cpKeys = LocalKeys(jwks);
|
|
978
1008
|
return JwtVcVerifier(cpKeys, issuer, validator);
|
|
979
1009
|
}
|
|
1010
|
+
|
|
980
1011
|
function validateCertificateExpiry(verifiedVc) {
|
|
981
1012
|
const now = /* @__PURE__ */ new Date();
|
|
982
1013
|
const validFrom = verifiedVc.doc.validFrom ? new Date(verifiedVc.doc.validFrom) : null;
|
|
@@ -996,7 +1027,16 @@ async function verifyAnnotations(paIssuerKeys, annotations, validator) {
|
|
|
996
1027
|
const verify = OpVerifier(
|
|
997
1028
|
paIssuerKeys,
|
|
998
1029
|
annotation,
|
|
999
|
-
validator?.(
|
|
1030
|
+
validator?.(
|
|
1031
|
+
// TODO: Profile Annotation とその派生のスキーマとして整理
|
|
1032
|
+
z.union([
|
|
1033
|
+
JapaneseExistencePA,
|
|
1034
|
+
ProfileAnnotationIssuerRegistration,
|
|
1035
|
+
ProfileAnnotation,
|
|
1036
|
+
JapaneseExistenceCertificate,
|
|
1037
|
+
Certificate
|
|
1038
|
+
])
|
|
1039
|
+
)
|
|
1000
1040
|
);
|
|
1001
1041
|
const result = await verify(annotation.source);
|
|
1002
1042
|
if (result instanceof Error) {
|
|
@@ -1006,13 +1046,12 @@ async function verifyAnnotations(paIssuerKeys, annotations, validator) {
|
|
|
1006
1046
|
if (valid instanceof CertificateExpired) {
|
|
1007
1047
|
return valid;
|
|
1008
1048
|
}
|
|
1009
|
-
await verifyImageDigestSri(
|
|
1010
|
-
valid.doc.credentialSubject.image
|
|
1011
|
-
);
|
|
1049
|
+
await verifyImageDigestSri(valid.doc.credentialSubject.image);
|
|
1012
1050
|
return valid;
|
|
1013
1051
|
})
|
|
1014
1052
|
);
|
|
1015
1053
|
}
|
|
1054
|
+
|
|
1016
1055
|
async function verifyMedia(wmpIssuerKeys, media, validator) {
|
|
1017
1056
|
if (!media) return;
|
|
1018
1057
|
return await Promise.all(
|
|
@@ -1031,6 +1070,16 @@ async function verifyMedia(wmpIssuerKeys, media, validator) {
|
|
|
1031
1070
|
})
|
|
1032
1071
|
);
|
|
1033
1072
|
}
|
|
1073
|
+
|
|
1074
|
+
function generateErrorDetails(items, opIndex, prefix, sources) {
|
|
1075
|
+
if (!items) return [];
|
|
1076
|
+
return items.map((item, index) => {
|
|
1077
|
+
if (!(item instanceof Error)) return null;
|
|
1078
|
+
const src = sources?.[index];
|
|
1079
|
+
const info = src ? ` issuer: ${src.doc.issuer}, subject: ${src.doc.credentialSubject.id}` : "";
|
|
1080
|
+
return `OP[${opIndex}].${prefix}[${index}]${info}`;
|
|
1081
|
+
}).filter((d) => d !== null);
|
|
1082
|
+
}
|
|
1034
1083
|
const isVerifiedOps = (ops) => ops.every((op) => !(op instanceof OpVerifyFailed));
|
|
1035
1084
|
function OpsVerifier(ops, keys, issuer, validator) {
|
|
1036
1085
|
const decoded = decodeOps(ops);
|
|
@@ -1045,7 +1094,7 @@ function OpsVerifier(ops, keys, issuer, validator) {
|
|
|
1045
1094
|
}
|
|
1046
1095
|
const paOrWmpIssuerKeys = getMappedKeys(decoded);
|
|
1047
1096
|
const resultOps = await Promise.all(
|
|
1048
|
-
decoded.map(async (op) => {
|
|
1097
|
+
decoded.map(async (op, opIndex) => {
|
|
1049
1098
|
const core = await verifyCp(op.core.source);
|
|
1050
1099
|
const annotations = await verifyAnnotations(
|
|
1051
1100
|
paOrWmpIssuerKeys,
|
|
@@ -1055,17 +1104,27 @@ function OpsVerifier(ops, keys, issuer, validator) {
|
|
|
1055
1104
|
const media = await verifyMedia(paOrWmpIssuerKeys, op.media, validator);
|
|
1056
1105
|
const resultOp = { core, annotations, media };
|
|
1057
1106
|
if (core instanceof Error) {
|
|
1058
|
-
return new OpVerifyFailed(
|
|
1107
|
+
return new OpVerifyFailed(
|
|
1108
|
+
`Core Profile verify failed (OP[${opIndex}])`,
|
|
1109
|
+
resultOp
|
|
1110
|
+
);
|
|
1059
1111
|
}
|
|
1060
1112
|
if (annotations && annotations.some((annotation) => annotation instanceof Error)) {
|
|
1113
|
+
const details = generateErrorDetails(
|
|
1114
|
+
annotations,
|
|
1115
|
+
opIndex,
|
|
1116
|
+
"PA",
|
|
1117
|
+
op.annotations
|
|
1118
|
+
);
|
|
1061
1119
|
return new OpVerifyFailed(
|
|
1062
|
-
|
|
1120
|
+
`Profile Annotation verify failed (${details.join(", ")})`,
|
|
1063
1121
|
resultOp
|
|
1064
1122
|
);
|
|
1065
1123
|
}
|
|
1066
1124
|
if (media && media.some((m) => m instanceof Error)) {
|
|
1125
|
+
const details = generateErrorDetails(media, opIndex, "WMP", op.media);
|
|
1067
1126
|
return new OpVerifyFailed(
|
|
1068
|
-
|
|
1127
|
+
`Web Media Profile verify failed (${details.join(", ")})`,
|
|
1069
1128
|
resultOp
|
|
1070
1129
|
);
|
|
1071
1130
|
}
|
|
@@ -1073,10 +1132,9 @@ function OpsVerifier(ops, keys, issuer, validator) {
|
|
|
1073
1132
|
})
|
|
1074
1133
|
);
|
|
1075
1134
|
if (!isVerifiedOps(resultOps)) {
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
);
|
|
1135
|
+
const verifyFailedIndexes = resultOps.map((op, index) => op instanceof OpVerifyFailed ? index : null).filter((i) => i !== null);
|
|
1136
|
+
const msg = verifyFailedIndexes.length > 0 ? `Originator Profile Set verify failed (${verifyFailedIndexes.map((i) => `OP[${i}]`).join(", ")})` : "Originator Profile Set verify failed";
|
|
1137
|
+
return new OpsVerifyFailed(msg, resultOps);
|
|
1080
1138
|
}
|
|
1081
1139
|
return resultOps;
|
|
1082
1140
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@originator-profile/verify",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-beta.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://docs.originator-profile.org",
|
|
6
6
|
"repository": {
|
|
@@ -13,14 +13,8 @@
|
|
|
13
13
|
},
|
|
14
14
|
"type": "module",
|
|
15
15
|
"exports": {
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
"default": "./dist/index.cjs"
|
|
19
|
-
},
|
|
20
|
-
"import": {
|
|
21
|
-
"types": "./dist/index.d.mts",
|
|
22
|
-
"default": "./dist/index.mjs"
|
|
23
|
-
}
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"default": "./dist/index.js"
|
|
24
18
|
},
|
|
25
19
|
"files": [
|
|
26
20
|
"dist",
|
|
@@ -33,31 +27,31 @@
|
|
|
33
27
|
"jose": "^6.2.2",
|
|
34
28
|
"jsonld": "^9.0.0",
|
|
35
29
|
"zod": "^4.3.6",
|
|
36
|
-
"@originator-profile/core": "0.
|
|
37
|
-
"@originator-profile/
|
|
38
|
-
"@originator-profile/
|
|
39
|
-
"@originator-profile/
|
|
40
|
-
"@originator-profile/sign": "0.
|
|
30
|
+
"@originator-profile/core": "0.6.0-beta.1",
|
|
31
|
+
"@originator-profile/model": "0.6.0-beta.1",
|
|
32
|
+
"@originator-profile/cryptography": "0.6.0-beta.1",
|
|
33
|
+
"@originator-profile/securing-mechanism": "0.6.0-beta.1",
|
|
34
|
+
"@originator-profile/sign": "0.6.0-beta.1"
|
|
41
35
|
},
|
|
42
36
|
"devDependencies": {
|
|
43
|
-
"@playwright/test": "
|
|
44
|
-
"date-fns": "
|
|
45
|
-
"eslint": "
|
|
46
|
-
"happy-dom": "
|
|
47
|
-
"just-diff-apply": "
|
|
48
|
-
"just-typeof": "
|
|
49
|
-
"pkgroll": "
|
|
50
|
-
"playwright": "
|
|
51
|
-
"typescript": "
|
|
52
|
-
"urlpattern-polyfill": "
|
|
53
|
-
"vite": "
|
|
54
|
-
"vitest": "
|
|
55
|
-
"websri": "
|
|
56
|
-
"
|
|
57
|
-
"
|
|
37
|
+
"@playwright/test": "1.59.1",
|
|
38
|
+
"date-fns": "4.1.0",
|
|
39
|
+
"eslint": "10.2.0",
|
|
40
|
+
"happy-dom": "20.8.9",
|
|
41
|
+
"just-diff-apply": "5.5.0",
|
|
42
|
+
"just-typeof": "3.2.0",
|
|
43
|
+
"pkgroll": "2.27.0",
|
|
44
|
+
"playwright": "1.59.1",
|
|
45
|
+
"typescript": "6.0.2",
|
|
46
|
+
"urlpattern-polyfill": "10.1.0",
|
|
47
|
+
"vite": "8.0.8",
|
|
48
|
+
"vitest": "4.1.4",
|
|
49
|
+
"websri": "1.0.1",
|
|
50
|
+
"@originator-profile/tsconfig": "0.6.0-beta.1",
|
|
51
|
+
"eslint-config-originator-profile": "0.6.0-beta.1"
|
|
58
52
|
},
|
|
59
53
|
"scripts": {
|
|
60
|
-
"build": "pkgroll --clean-dist
|
|
54
|
+
"build": "pkgroll --clean-dist",
|
|
61
55
|
"test": "vitest run",
|
|
62
56
|
"e2e": "playwright test",
|
|
63
57
|
"e2e:update": "playwright test --update-snapshots",
|