@originator-profile/verify 0.4.0 → 0.5.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 +177 -92
- package/dist/index.d.cts +25 -8
- package/dist/index.d.mts +25 -8
- package/dist/index.mjs +177 -93
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -26,34 +26,6 @@ class CaVerifyFailed extends Error {
|
|
|
26
26
|
code = CaVerifyFailed.code;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
function verifyAllowedOrigin(origin, allowedOrigins) {
|
|
30
|
-
if (origin === "null") {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
return [allowedOrigins].flat().includes(origin);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async function importURLPatternPolyfill() {
|
|
37
|
-
if (typeof URLPattern === "undefined") {
|
|
38
|
-
await Promise.resolve().then(function () { return require('./index-D-j8gXz_.cjs'); });
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
function ReplaceEncode(url) {
|
|
42
|
-
return url.replace(/(%[0-9a-f]{2}?)+/g, function(match) {
|
|
43
|
-
return match.toUpperCase();
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
async function verifyAllowedUrl(url, allowedUrl) {
|
|
47
|
-
await importURLPatternPolyfill();
|
|
48
|
-
return [allowedUrl].flat().some((value) => {
|
|
49
|
-
if (!value) {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
const pattern = new URLPattern(ReplaceEncode(value));
|
|
53
|
-
return pattern.test(ReplaceEncode(url));
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
29
|
const supportedHashAlgorithms = {
|
|
58
30
|
/** SHA-256 hash algorithm */
|
|
59
31
|
sha256: "SHA-256",
|
|
@@ -385,6 +357,34 @@ async function verifyIntegrity(content, doc = document, fetcher = fetch) {
|
|
|
385
357
|
return await integrityVerifier.verify(content, doc);
|
|
386
358
|
}
|
|
387
359
|
|
|
360
|
+
function verifyAllowedOrigin(origin, allowedOrigins) {
|
|
361
|
+
if (origin === "null") {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
return [allowedOrigins].flat().includes(origin);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
async function importURLPatternPolyfill() {
|
|
368
|
+
if (typeof URLPattern === "undefined") {
|
|
369
|
+
await Promise.resolve().then(function () { return require('./index-D-j8gXz_.cjs'); });
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
function ReplaceEncode(url) {
|
|
373
|
+
return url.replace(/(%[0-9a-f]{2}?)+/g, function(match) {
|
|
374
|
+
return match.toUpperCase();
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
async function verifyAllowedUrl(url, allowedUrl) {
|
|
378
|
+
await importURLPatternPolyfill();
|
|
379
|
+
return [allowedUrl].flat().some((value) => {
|
|
380
|
+
if (!value) {
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
const pattern = new URLPattern(ReplaceEncode(value));
|
|
384
|
+
return pattern.test(ReplaceEncode(url));
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
|
|
388
388
|
async function checkUrlAndOrigin(result, url) {
|
|
389
389
|
if (result.doc.allowedUrl && result.doc.allowedOrigin) {
|
|
390
390
|
return new CaInvalid("allowedUrl and allowedOrigin are exclusive", result);
|
|
@@ -887,8 +887,44 @@ class OpVerifyFailed extends Error {
|
|
|
887
887
|
}
|
|
888
888
|
code = OpVerifyFailed.code;
|
|
889
889
|
}
|
|
890
|
+
class CertificateExpired extends Error {
|
|
891
|
+
constructor(message, result) {
|
|
892
|
+
super(message);
|
|
893
|
+
this.result = result;
|
|
894
|
+
}
|
|
895
|
+
static get code() {
|
|
896
|
+
return "ERR_CERTIFICATE_EXPIRED";
|
|
897
|
+
}
|
|
898
|
+
code = CertificateExpired.code;
|
|
899
|
+
}
|
|
890
900
|
|
|
891
901
|
const isEveryDecodedPa = (annotations) => annotations.every((annotation) => "doc" in annotation);
|
|
902
|
+
const isEveryDecodedWmp = (media) => media.every((m) => "doc" in m);
|
|
903
|
+
const validateDecodedOp = (core, annotations, media, resultOp) => {
|
|
904
|
+
if (annotations && !isEveryDecodedPa(annotations)) {
|
|
905
|
+
return new OpInvalid("Profile Annotation decode failed", resultOp);
|
|
906
|
+
}
|
|
907
|
+
if (media && !isEveryDecodedWmp(media)) {
|
|
908
|
+
return new OpInvalid("Web Media Profile decode failed", resultOp);
|
|
909
|
+
}
|
|
910
|
+
if (media && media.some(
|
|
911
|
+
(m) => core.doc.credentialSubject.id !== m.doc.credentialSubject.id
|
|
912
|
+
)) {
|
|
913
|
+
return new OpInvalid(
|
|
914
|
+
"Subject mismatch between Core Profile and Web Media Profile",
|
|
915
|
+
resultOp
|
|
916
|
+
);
|
|
917
|
+
}
|
|
918
|
+
if (annotations && annotations.some(
|
|
919
|
+
(annotation) => core.doc.credentialSubject.id !== annotation.doc.credentialSubject.id
|
|
920
|
+
)) {
|
|
921
|
+
return new OpInvalid(
|
|
922
|
+
"Subject mismatch between Core Profile and Profile Annotation",
|
|
923
|
+
resultOp
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
return { type: "valid", annotations, media };
|
|
927
|
+
};
|
|
892
928
|
const isDecodedOps = (ops) => ops.every((op) => !(op instanceof OpInvalid));
|
|
893
929
|
function decodeOps(ops) {
|
|
894
930
|
const decodeCp = securingMechanism.JwtVcDecoder();
|
|
@@ -897,32 +933,22 @@ function decodeOps(ops) {
|
|
|
897
933
|
const resultOps = ops.map((op) => {
|
|
898
934
|
const core = decodeCp(op.core);
|
|
899
935
|
const annotations = op.annotations ? op.annotations.map(decodePa) : void 0;
|
|
900
|
-
const
|
|
936
|
+
const mediaInput = op.media;
|
|
937
|
+
const mediaArray = mediaInput ? Array.isArray(mediaInput) ? mediaInput : [mediaInput] : void 0;
|
|
938
|
+
const media = mediaArray ? mediaArray.map(decodeWmp) : void 0;
|
|
901
939
|
const resultOp = { core, annotations, media };
|
|
902
940
|
if (core instanceof Error) {
|
|
903
941
|
return new OpInvalid("Core Profile decode failed", resultOp);
|
|
904
942
|
}
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
if (media instanceof Error) {
|
|
909
|
-
return new OpInvalid("Web Media Profile decode failed", resultOp);
|
|
910
|
-
}
|
|
911
|
-
if (media && core.doc.credentialSubject.id !== media.doc.credentialSubject.id) {
|
|
912
|
-
return new OpInvalid(
|
|
913
|
-
"Subject mismatch between Core Profile and Web Media Profile",
|
|
914
|
-
resultOp
|
|
915
|
-
);
|
|
943
|
+
const validated = validateDecodedOp(core, annotations, media, resultOp);
|
|
944
|
+
if (validated instanceof OpInvalid) {
|
|
945
|
+
return validated;
|
|
916
946
|
}
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
resultOp
|
|
923
|
-
);
|
|
924
|
-
}
|
|
925
|
-
return resultOp;
|
|
947
|
+
return {
|
|
948
|
+
core,
|
|
949
|
+
annotations: validated.annotations,
|
|
950
|
+
media: validated.media
|
|
951
|
+
};
|
|
926
952
|
});
|
|
927
953
|
if (!isDecodedOps(resultOps)) {
|
|
928
954
|
return new OpsInvalid("Invalid Originator Profile Set", resultOps);
|
|
@@ -939,10 +965,22 @@ function OpVerifier(paOrWmpIssuerKeys, vc, validator) {
|
|
|
939
965
|
const cpKeys = cryptography.LocalKeys(jwks);
|
|
940
966
|
return securingMechanism.JwtVcVerifier(cpKeys, issuer, validator);
|
|
941
967
|
}
|
|
968
|
+
function validateCertificateExpiry(verifiedVc) {
|
|
969
|
+
const now = /* @__PURE__ */ new Date();
|
|
970
|
+
const validFrom = verifiedVc.doc.validFrom ? new Date(verifiedVc.doc.validFrom) : null;
|
|
971
|
+
const validUntil = verifiedVc.doc.validUntil ? new Date(verifiedVc.doc.validUntil) : null;
|
|
972
|
+
if (validFrom && now < validFrom) {
|
|
973
|
+
return new CertificateExpired("Certificate not yet valid", verifiedVc);
|
|
974
|
+
}
|
|
975
|
+
if (validUntil && now > validUntil) {
|
|
976
|
+
return new CertificateExpired("Certificate expired", verifiedVc);
|
|
977
|
+
}
|
|
978
|
+
return verifiedVc;
|
|
979
|
+
}
|
|
942
980
|
async function verifyAnnotations(paIssuerKeys, annotations, validator) {
|
|
943
981
|
if (!annotations) return;
|
|
944
982
|
return await Promise.all(
|
|
945
|
-
annotations.map((annotation) => {
|
|
983
|
+
annotations.map(async (annotation) => {
|
|
946
984
|
const verify = OpVerifier(
|
|
947
985
|
paIssuerKeys,
|
|
948
986
|
annotation,
|
|
@@ -950,18 +988,26 @@ async function verifyAnnotations(paIssuerKeys, annotations, validator) {
|
|
|
950
988
|
oneOf: [model.Certificate, model.JapaneseExistenceCertificate]
|
|
951
989
|
})
|
|
952
990
|
);
|
|
953
|
-
|
|
991
|
+
const result = await verify(annotation.source);
|
|
992
|
+
if (result instanceof Error) {
|
|
993
|
+
return result;
|
|
994
|
+
}
|
|
995
|
+
return validateCertificateExpiry(result);
|
|
954
996
|
})
|
|
955
997
|
);
|
|
956
998
|
}
|
|
957
999
|
async function verifyMedia(wmpIssuerKeys, media, validator) {
|
|
958
1000
|
if (!media) return;
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1001
|
+
return await Promise.all(
|
|
1002
|
+
media.map((m) => {
|
|
1003
|
+
const verify = OpVerifier(
|
|
1004
|
+
wmpIssuerKeys,
|
|
1005
|
+
m,
|
|
1006
|
+
validator?.(model.WebMediaProfile)
|
|
1007
|
+
);
|
|
1008
|
+
return verify(m.source);
|
|
1009
|
+
})
|
|
963
1010
|
);
|
|
964
|
-
return await verify(media.source);
|
|
965
1011
|
}
|
|
966
1012
|
const isVerifiedOps = (ops) => ops.every((op) => !(op instanceof OpVerifyFailed));
|
|
967
1013
|
function OpsVerifier(ops, keys, issuer, validator) {
|
|
@@ -995,7 +1041,7 @@ function OpsVerifier(ops, keys, issuer, validator) {
|
|
|
995
1041
|
resultOp
|
|
996
1042
|
);
|
|
997
1043
|
}
|
|
998
|
-
if (media instanceof Error) {
|
|
1044
|
+
if (media && media.some((m) => m instanceof Error)) {
|
|
999
1045
|
return new OpVerifyFailed(
|
|
1000
1046
|
"Web Media Profile verify failed",
|
|
1001
1047
|
resultOp
|
|
@@ -1036,64 +1082,102 @@ class SiteProfileVerifyFailed extends Error {
|
|
|
1036
1082
|
code = SiteProfileVerifyFailed.code;
|
|
1037
1083
|
}
|
|
1038
1084
|
|
|
1085
|
+
const decodeWebsiteProfiles = (sp, opsVerified) => {
|
|
1086
|
+
const wspSources = sp.sites || (sp.credential ? [sp.credential] : []);
|
|
1087
|
+
if (wspSources.length === 0) {
|
|
1088
|
+
return new SiteProfileInvalid("No Website Profile found", {
|
|
1089
|
+
originators: opsVerified,
|
|
1090
|
+
sites: []
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
const decodeWsp = securingMechanism.JwtVcDecoder();
|
|
1094
|
+
const decodedWsps = wspSources.map(decodeWsp);
|
|
1095
|
+
const decodeErrors = decodedWsps.filter((wsp) => wsp instanceof Error);
|
|
1096
|
+
if (decodeErrors.length > 0) {
|
|
1097
|
+
return new SiteProfileInvalid("Website Profile invalid", {
|
|
1098
|
+
originators: opsVerified,
|
|
1099
|
+
sites: decodeErrors
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1102
|
+
return {
|
|
1103
|
+
decodedWsps,
|
|
1104
|
+
wspSources
|
|
1105
|
+
};
|
|
1106
|
+
};
|
|
1039
1107
|
function SpVerifier(sp, keys, issuer, origin, verifyOrigin = true, validator) {
|
|
1040
1108
|
async function verify() {
|
|
1041
1109
|
const verifyOps = OpsVerifier(sp.originators, keys, issuer, validator);
|
|
1042
1110
|
const opsVerified = await verifyOps();
|
|
1043
1111
|
if (opsVerified instanceof OpsInvalid) {
|
|
1044
1112
|
return new SiteProfileInvalid("Originator Profile Set invalid", {
|
|
1045
|
-
originators: opsVerified
|
|
1113
|
+
originators: opsVerified,
|
|
1114
|
+
sites: []
|
|
1046
1115
|
});
|
|
1047
1116
|
}
|
|
1048
1117
|
if (opsVerified instanceof OpsVerifyFailed) {
|
|
1049
1118
|
return new SiteProfileVerifyFailed(
|
|
1050
1119
|
"Originator Profile Set verify failed",
|
|
1051
|
-
{ originators: opsVerified }
|
|
1120
|
+
{ originators: opsVerified, sites: [] }
|
|
1052
1121
|
);
|
|
1053
1122
|
}
|
|
1054
|
-
const
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
return new SiteProfileInvalid("Website Profile invalid", {
|
|
1058
|
-
originators: opsVerified,
|
|
1059
|
-
credential: decodedWsp
|
|
1060
|
-
});
|
|
1123
|
+
const decoded = decodeWebsiteProfiles(sp, opsVerified);
|
|
1124
|
+
if (decoded instanceof SiteProfileInvalid) {
|
|
1125
|
+
return decoded;
|
|
1061
1126
|
}
|
|
1062
|
-
const
|
|
1063
|
-
const
|
|
1064
|
-
(
|
|
1127
|
+
const { decodedWsps, wspSources } = decoded;
|
|
1128
|
+
const verifiedWsps = await Promise.all(
|
|
1129
|
+
decodedWsps.map(async (decodedWsp, index) => {
|
|
1130
|
+
if (decodedWsp instanceof Error) {
|
|
1131
|
+
return decodedWsp;
|
|
1132
|
+
}
|
|
1133
|
+
const wspIssuer = decodedWsp.doc.issuer;
|
|
1134
|
+
const cp = opsVerified.find(
|
|
1135
|
+
(op) => op.core.doc.credentialSubject.id === wspIssuer
|
|
1136
|
+
);
|
|
1137
|
+
if (!cp) {
|
|
1138
|
+
return new CoreProfileNotFound(
|
|
1139
|
+
`Missing Core Profile (${wspIssuer})`,
|
|
1140
|
+
decodedWsp
|
|
1141
|
+
);
|
|
1142
|
+
}
|
|
1143
|
+
const verifyWsp = securingMechanism.JwtVcVerifier(
|
|
1144
|
+
cryptography.LocalKeys(cp.core.doc.credentialSubject.jwks),
|
|
1145
|
+
cp.core.doc.credentialSubject.id,
|
|
1146
|
+
validator?.(model.WebsiteProfile)
|
|
1147
|
+
);
|
|
1148
|
+
const verified = await verifyWsp(wspSources[index]);
|
|
1149
|
+
if (verified instanceof Error) {
|
|
1150
|
+
return verified;
|
|
1151
|
+
}
|
|
1152
|
+
if (verifyOrigin) {
|
|
1153
|
+
const allowedOrigin = "allowedOrigin" in decodedWsp.doc.credentialSubject ? decodedWsp.doc.credentialSubject.allowedOrigin : decodedWsp.doc.credentialSubject.url;
|
|
1154
|
+
if (!verifyAllowedOrigin(origin, allowedOrigin)) {
|
|
1155
|
+
return new Error("Origin not allowed");
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
return verified;
|
|
1159
|
+
})
|
|
1160
|
+
);
|
|
1161
|
+
const hasCoreProfileNotFound = verifiedWsps.some(
|
|
1162
|
+
(wsp) => wsp instanceof CoreProfileNotFound
|
|
1065
1163
|
);
|
|
1066
|
-
if (
|
|
1164
|
+
if (hasCoreProfileNotFound) {
|
|
1067
1165
|
return new SiteProfileInvalid("Appropriate Core Profile not found", {
|
|
1068
1166
|
originators: opsVerified,
|
|
1069
|
-
|
|
1070
|
-
`Missing Core Profile (${wspIssuer})`,
|
|
1071
|
-
decodedWsp
|
|
1072
|
-
)
|
|
1167
|
+
sites: verifiedWsps
|
|
1073
1168
|
});
|
|
1074
1169
|
}
|
|
1075
|
-
const
|
|
1076
|
-
|
|
1077
|
-
cp.core.doc.credentialSubject.id,
|
|
1078
|
-
validator?.(model.WebsiteProfile)
|
|
1079
|
-
);
|
|
1080
|
-
const credential = await verifyWsp(sp.credential);
|
|
1081
|
-
if (credential instanceof Error) {
|
|
1170
|
+
const hasError = verifiedWsps.some((wsp) => wsp instanceof Error);
|
|
1171
|
+
if (hasError) {
|
|
1082
1172
|
return new SiteProfileVerifyFailed("Website Profile verify failed", {
|
|
1083
1173
|
originators: opsVerified,
|
|
1084
|
-
|
|
1174
|
+
sites: verifiedWsps
|
|
1085
1175
|
});
|
|
1086
1176
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
originators: opsVerified,
|
|
1092
|
-
credential
|
|
1093
|
-
});
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
return { originators: opsVerified, credential };
|
|
1177
|
+
return {
|
|
1178
|
+
originators: opsVerified,
|
|
1179
|
+
sites: verifiedWsps
|
|
1180
|
+
};
|
|
1097
1181
|
}
|
|
1098
1182
|
return verify;
|
|
1099
1183
|
}
|
|
@@ -1161,6 +1245,7 @@ exports.CaInvalid = CaInvalid;
|
|
|
1161
1245
|
exports.CaVerifier = CaVerifier;
|
|
1162
1246
|
exports.CaVerifyFailed = CaVerifyFailed;
|
|
1163
1247
|
exports.CasVerifyFailed = CasVerifyFailed;
|
|
1248
|
+
exports.CertificateExpired = CertificateExpired;
|
|
1164
1249
|
exports.CertificationSystemValidationFailed = CertificationSystemValidationFailed;
|
|
1165
1250
|
exports.CertificationSystemValidator = CertificationSystemValidator;
|
|
1166
1251
|
exports.CoreProfileNotFound = CoreProfileNotFound;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { JwtVcDecodingResult, JwtVcVerificationResult, UnverifiedJwtVc, VerifiedJwtVc, VcValidator } from '@originator-profile/securing-mechanism';
|
|
2
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';
|
|
2
|
+
import { JwtVcDecodingResult, JwtVcVerificationResult, UnverifiedJwtVc, VerifiedJwtVc, VcValidator } from '@originator-profile/securing-mechanism';
|
|
3
3
|
import { Keys } from '@originator-profile/cryptography';
|
|
4
4
|
import { DigestSriContent, ContentFetcher, ElementSelector } from '@originator-profile/sign';
|
|
5
5
|
import { ErrorObject } from 'ajv';
|
|
@@ -415,19 +415,36 @@ declare class OpVerifyFailed extends Error {
|
|
|
415
415
|
readonly code: string;
|
|
416
416
|
constructor(message: string, result: OpVerificationFailure);
|
|
417
417
|
}
|
|
418
|
+
/**
|
|
419
|
+
* 証明書の有効期限エラー
|
|
420
|
+
*
|
|
421
|
+
* 証明書の有効期限チェックに失敗しました。次の原因で使用されます。
|
|
422
|
+
*
|
|
423
|
+
* - 証明書の有効期限が開始していない (validFrom より前)
|
|
424
|
+
* - 証明書の有効期限が切れている (validUntil より後)
|
|
425
|
+
*
|
|
426
|
+
* なお、validFrom と validUntil はオプショナルフィールドのため、
|
|
427
|
+
* 片方のみが指定されている場合もあります。
|
|
428
|
+
**/
|
|
429
|
+
declare class CertificateExpired<T extends OpVc> extends Error {
|
|
430
|
+
result: VerifiedJwtVc<T>;
|
|
431
|
+
static get code(): string;
|
|
432
|
+
readonly code: string;
|
|
433
|
+
constructor(message: string, result: VerifiedJwtVc<T>);
|
|
434
|
+
}
|
|
418
435
|
|
|
419
436
|
type Certificate = Certificate$1 | JapaneseExistenceCertificate;
|
|
420
437
|
/** Originator Profile 復号失敗 */
|
|
421
438
|
type OpDecodingFailure = {
|
|
422
439
|
core: JwtVcDecodingResult<CoreProfile>;
|
|
423
440
|
annotations?: JwtVcDecodingResult<Certificate>[];
|
|
424
|
-
media?: JwtVcDecodingResult<WebMediaProfile
|
|
441
|
+
media?: JwtVcDecodingResult<WebMediaProfile>[];
|
|
425
442
|
};
|
|
426
443
|
/** 復号済み Originator Profile */
|
|
427
444
|
type DecodedOp = {
|
|
428
445
|
core: UnverifiedJwtVc<CoreProfile>;
|
|
429
446
|
annotations?: UnverifiedJwtVc<Certificate>[];
|
|
430
|
-
media
|
|
447
|
+
media?: UnverifiedJwtVc<WebMediaProfile>[];
|
|
431
448
|
};
|
|
432
449
|
/** Originator Profile 復号結果 */
|
|
433
450
|
type OpDecodingResult = DecodedOp | OpInvalid;
|
|
@@ -441,13 +458,13 @@ type OpsDecodingResult = DecodedOps | OpsInvalid;
|
|
|
441
458
|
type OpVerificationFailure = {
|
|
442
459
|
core: JwtVcVerificationResult<CoreProfile> | CoreProfileNotFound<CoreProfile>;
|
|
443
460
|
annotations?: (JwtVcVerificationResult<Certificate> | CoreProfileNotFound<Certificate>)[];
|
|
444
|
-
media?: JwtVcVerificationResult<WebMediaProfile> | CoreProfileNotFound<WebMediaProfile
|
|
461
|
+
media?: (JwtVcVerificationResult<WebMediaProfile> | CoreProfileNotFound<WebMediaProfile>)[];
|
|
445
462
|
};
|
|
446
463
|
/** 検証済み Originator Profile */
|
|
447
464
|
type VerifiedOp = {
|
|
448
465
|
core: VerifiedJwtVc<CoreProfile>;
|
|
449
466
|
annotations?: VerifiedJwtVc<Certificate>[];
|
|
450
|
-
media?: VerifiedJwtVc<WebMediaProfile
|
|
467
|
+
media?: VerifiedJwtVc<WebMediaProfile>[];
|
|
451
468
|
};
|
|
452
469
|
/** Originator Profile 検証結果 */
|
|
453
470
|
type OpVerificationResult = VerifiedOp | OpVerifyFailed;
|
|
@@ -511,11 +528,11 @@ declare class SiteProfileVerifyFailed extends Error {
|
|
|
511
528
|
/** Site Profile 検証失敗 */
|
|
512
529
|
type SpVerificationFailure = {
|
|
513
530
|
originators: OpsVerificationResult;
|
|
514
|
-
|
|
531
|
+
sites: (JwtVcVerificationResult<WebsiteProfile> | JwtVcDecodingResult<WebsiteProfile> | CoreProfileNotFound<WebsiteProfile>)[];
|
|
515
532
|
};
|
|
516
533
|
type VerifiedSp = {
|
|
517
534
|
originators: VerifiedOps;
|
|
518
|
-
|
|
535
|
+
sites: VerifiedJwtVc<WebsiteProfile>[];
|
|
519
536
|
};
|
|
520
537
|
type SpVerificationResult = VerifiedSp | SiteProfileInvalid | SiteProfileVerifyFailed;
|
|
521
538
|
|
|
@@ -549,4 +566,4 @@ declare function validateCertificationSystem(payload: unknown): CertificationSys
|
|
|
549
566
|
*/
|
|
550
567
|
declare function verifyAllowedOrigin(origin: URL["origin"], allowedOrigins: AllowedOrigin): boolean;
|
|
551
568
|
|
|
552
|
-
export { type AdProfilePair, type CaDecodingFailure, type CaDecodingResult, CaInvalid, type CaVerificationFailure, type CaVerificationResult, CaVerifier, CaVerifyFailed, type CasItem, type CasVerificationFailure, type CasVerificationResult, CasVerifyFailed, type Certificate, 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 };
|
|
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 };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { JwtVcDecodingResult, JwtVcVerificationResult, UnverifiedJwtVc, VerifiedJwtVc, VcValidator } from '@originator-profile/securing-mechanism';
|
|
2
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';
|
|
2
|
+
import { JwtVcDecodingResult, JwtVcVerificationResult, UnverifiedJwtVc, VerifiedJwtVc, VcValidator } from '@originator-profile/securing-mechanism';
|
|
3
3
|
import { Keys } from '@originator-profile/cryptography';
|
|
4
4
|
import { DigestSriContent, ContentFetcher, ElementSelector } from '@originator-profile/sign';
|
|
5
5
|
import { ErrorObject } from 'ajv';
|
|
@@ -415,19 +415,36 @@ declare class OpVerifyFailed extends Error {
|
|
|
415
415
|
readonly code: string;
|
|
416
416
|
constructor(message: string, result: OpVerificationFailure);
|
|
417
417
|
}
|
|
418
|
+
/**
|
|
419
|
+
* 証明書の有効期限エラー
|
|
420
|
+
*
|
|
421
|
+
* 証明書の有効期限チェックに失敗しました。次の原因で使用されます。
|
|
422
|
+
*
|
|
423
|
+
* - 証明書の有効期限が開始していない (validFrom より前)
|
|
424
|
+
* - 証明書の有効期限が切れている (validUntil より後)
|
|
425
|
+
*
|
|
426
|
+
* なお、validFrom と validUntil はオプショナルフィールドのため、
|
|
427
|
+
* 片方のみが指定されている場合もあります。
|
|
428
|
+
**/
|
|
429
|
+
declare class CertificateExpired<T extends OpVc> extends Error {
|
|
430
|
+
result: VerifiedJwtVc<T>;
|
|
431
|
+
static get code(): string;
|
|
432
|
+
readonly code: string;
|
|
433
|
+
constructor(message: string, result: VerifiedJwtVc<T>);
|
|
434
|
+
}
|
|
418
435
|
|
|
419
436
|
type Certificate = Certificate$1 | JapaneseExistenceCertificate;
|
|
420
437
|
/** Originator Profile 復号失敗 */
|
|
421
438
|
type OpDecodingFailure = {
|
|
422
439
|
core: JwtVcDecodingResult<CoreProfile>;
|
|
423
440
|
annotations?: JwtVcDecodingResult<Certificate>[];
|
|
424
|
-
media?: JwtVcDecodingResult<WebMediaProfile
|
|
441
|
+
media?: JwtVcDecodingResult<WebMediaProfile>[];
|
|
425
442
|
};
|
|
426
443
|
/** 復号済み Originator Profile */
|
|
427
444
|
type DecodedOp = {
|
|
428
445
|
core: UnverifiedJwtVc<CoreProfile>;
|
|
429
446
|
annotations?: UnverifiedJwtVc<Certificate>[];
|
|
430
|
-
media
|
|
447
|
+
media?: UnverifiedJwtVc<WebMediaProfile>[];
|
|
431
448
|
};
|
|
432
449
|
/** Originator Profile 復号結果 */
|
|
433
450
|
type OpDecodingResult = DecodedOp | OpInvalid;
|
|
@@ -441,13 +458,13 @@ type OpsDecodingResult = DecodedOps | OpsInvalid;
|
|
|
441
458
|
type OpVerificationFailure = {
|
|
442
459
|
core: JwtVcVerificationResult<CoreProfile> | CoreProfileNotFound<CoreProfile>;
|
|
443
460
|
annotations?: (JwtVcVerificationResult<Certificate> | CoreProfileNotFound<Certificate>)[];
|
|
444
|
-
media?: JwtVcVerificationResult<WebMediaProfile> | CoreProfileNotFound<WebMediaProfile
|
|
461
|
+
media?: (JwtVcVerificationResult<WebMediaProfile> | CoreProfileNotFound<WebMediaProfile>)[];
|
|
445
462
|
};
|
|
446
463
|
/** 検証済み Originator Profile */
|
|
447
464
|
type VerifiedOp = {
|
|
448
465
|
core: VerifiedJwtVc<CoreProfile>;
|
|
449
466
|
annotations?: VerifiedJwtVc<Certificate>[];
|
|
450
|
-
media?: VerifiedJwtVc<WebMediaProfile
|
|
467
|
+
media?: VerifiedJwtVc<WebMediaProfile>[];
|
|
451
468
|
};
|
|
452
469
|
/** Originator Profile 検証結果 */
|
|
453
470
|
type OpVerificationResult = VerifiedOp | OpVerifyFailed;
|
|
@@ -511,11 +528,11 @@ declare class SiteProfileVerifyFailed extends Error {
|
|
|
511
528
|
/** Site Profile 検証失敗 */
|
|
512
529
|
type SpVerificationFailure = {
|
|
513
530
|
originators: OpsVerificationResult;
|
|
514
|
-
|
|
531
|
+
sites: (JwtVcVerificationResult<WebsiteProfile> | JwtVcDecodingResult<WebsiteProfile> | CoreProfileNotFound<WebsiteProfile>)[];
|
|
515
532
|
};
|
|
516
533
|
type VerifiedSp = {
|
|
517
534
|
originators: VerifiedOps;
|
|
518
|
-
|
|
535
|
+
sites: VerifiedJwtVc<WebsiteProfile>[];
|
|
519
536
|
};
|
|
520
537
|
type SpVerificationResult = VerifiedSp | SiteProfileInvalid | SiteProfileVerifyFailed;
|
|
521
538
|
|
|
@@ -549,4 +566,4 @@ declare function validateCertificationSystem(payload: unknown): CertificationSys
|
|
|
549
566
|
*/
|
|
550
567
|
declare function verifyAllowedOrigin(origin: URL["origin"], allowedOrigins: AllowedOrigin): boolean;
|
|
551
568
|
|
|
552
|
-
export { type AdProfilePair, type CaDecodingFailure, type CaDecodingResult, CaInvalid, type CaVerificationFailure, type CaVerificationResult, CaVerifier, CaVerifyFailed, type CasItem, type CasVerificationFailure, type CasVerificationResult, CasVerifyFailed, type Certificate, 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 };
|
|
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 };
|
package/dist/index.mjs
CHANGED
|
@@ -24,34 +24,6 @@ class CaVerifyFailed extends Error {
|
|
|
24
24
|
code = CaVerifyFailed.code;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
function verifyAllowedOrigin(origin, allowedOrigins) {
|
|
28
|
-
if (origin === "null") {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
return [allowedOrigins].flat().includes(origin);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async function importURLPatternPolyfill() {
|
|
35
|
-
if (typeof URLPattern === "undefined") {
|
|
36
|
-
await import('./index-CQxI_8IG.mjs');
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
function ReplaceEncode(url) {
|
|
40
|
-
return url.replace(/(%[0-9a-f]{2}?)+/g, function(match) {
|
|
41
|
-
return match.toUpperCase();
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
async function verifyAllowedUrl(url, allowedUrl) {
|
|
45
|
-
await importURLPatternPolyfill();
|
|
46
|
-
return [allowedUrl].flat().some((value) => {
|
|
47
|
-
if (!value) {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
const pattern = new URLPattern(ReplaceEncode(value));
|
|
51
|
-
return pattern.test(ReplaceEncode(url));
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
27
|
const supportedHashAlgorithms = {
|
|
56
28
|
/** SHA-256 hash algorithm */
|
|
57
29
|
sha256: "SHA-256",
|
|
@@ -383,6 +355,34 @@ async function verifyIntegrity(content, doc = document, fetcher = fetch) {
|
|
|
383
355
|
return await integrityVerifier.verify(content, doc);
|
|
384
356
|
}
|
|
385
357
|
|
|
358
|
+
function verifyAllowedOrigin(origin, allowedOrigins) {
|
|
359
|
+
if (origin === "null") {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
return [allowedOrigins].flat().includes(origin);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
async function importURLPatternPolyfill() {
|
|
366
|
+
if (typeof URLPattern === "undefined") {
|
|
367
|
+
await import('./index-CQxI_8IG.mjs');
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
function ReplaceEncode(url) {
|
|
371
|
+
return url.replace(/(%[0-9a-f]{2}?)+/g, function(match) {
|
|
372
|
+
return match.toUpperCase();
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
async function verifyAllowedUrl(url, allowedUrl) {
|
|
376
|
+
await importURLPatternPolyfill();
|
|
377
|
+
return [allowedUrl].flat().some((value) => {
|
|
378
|
+
if (!value) {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
const pattern = new URLPattern(ReplaceEncode(value));
|
|
382
|
+
return pattern.test(ReplaceEncode(url));
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
386
|
async function checkUrlAndOrigin(result, url) {
|
|
387
387
|
if (result.doc.allowedUrl && result.doc.allowedOrigin) {
|
|
388
388
|
return new CaInvalid("allowedUrl and allowedOrigin are exclusive", result);
|
|
@@ -885,8 +885,44 @@ class OpVerifyFailed extends Error {
|
|
|
885
885
|
}
|
|
886
886
|
code = OpVerifyFailed.code;
|
|
887
887
|
}
|
|
888
|
+
class CertificateExpired extends Error {
|
|
889
|
+
constructor(message, result) {
|
|
890
|
+
super(message);
|
|
891
|
+
this.result = result;
|
|
892
|
+
}
|
|
893
|
+
static get code() {
|
|
894
|
+
return "ERR_CERTIFICATE_EXPIRED";
|
|
895
|
+
}
|
|
896
|
+
code = CertificateExpired.code;
|
|
897
|
+
}
|
|
888
898
|
|
|
889
899
|
const isEveryDecodedPa = (annotations) => annotations.every((annotation) => "doc" in annotation);
|
|
900
|
+
const isEveryDecodedWmp = (media) => media.every((m) => "doc" in m);
|
|
901
|
+
const validateDecodedOp = (core, annotations, media, resultOp) => {
|
|
902
|
+
if (annotations && !isEveryDecodedPa(annotations)) {
|
|
903
|
+
return new OpInvalid("Profile Annotation decode failed", resultOp);
|
|
904
|
+
}
|
|
905
|
+
if (media && !isEveryDecodedWmp(media)) {
|
|
906
|
+
return new OpInvalid("Web Media Profile decode failed", resultOp);
|
|
907
|
+
}
|
|
908
|
+
if (media && media.some(
|
|
909
|
+
(m) => core.doc.credentialSubject.id !== m.doc.credentialSubject.id
|
|
910
|
+
)) {
|
|
911
|
+
return new OpInvalid(
|
|
912
|
+
"Subject mismatch between Core Profile and Web Media Profile",
|
|
913
|
+
resultOp
|
|
914
|
+
);
|
|
915
|
+
}
|
|
916
|
+
if (annotations && annotations.some(
|
|
917
|
+
(annotation) => core.doc.credentialSubject.id !== annotation.doc.credentialSubject.id
|
|
918
|
+
)) {
|
|
919
|
+
return new OpInvalid(
|
|
920
|
+
"Subject mismatch between Core Profile and Profile Annotation",
|
|
921
|
+
resultOp
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
return { type: "valid", annotations, media };
|
|
925
|
+
};
|
|
890
926
|
const isDecodedOps = (ops) => ops.every((op) => !(op instanceof OpInvalid));
|
|
891
927
|
function decodeOps(ops) {
|
|
892
928
|
const decodeCp = JwtVcDecoder();
|
|
@@ -895,32 +931,22 @@ function decodeOps(ops) {
|
|
|
895
931
|
const resultOps = ops.map((op) => {
|
|
896
932
|
const core = decodeCp(op.core);
|
|
897
933
|
const annotations = op.annotations ? op.annotations.map(decodePa) : void 0;
|
|
898
|
-
const
|
|
934
|
+
const mediaInput = op.media;
|
|
935
|
+
const mediaArray = mediaInput ? Array.isArray(mediaInput) ? mediaInput : [mediaInput] : void 0;
|
|
936
|
+
const media = mediaArray ? mediaArray.map(decodeWmp) : void 0;
|
|
899
937
|
const resultOp = { core, annotations, media };
|
|
900
938
|
if (core instanceof Error) {
|
|
901
939
|
return new OpInvalid("Core Profile decode failed", resultOp);
|
|
902
940
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
if (media instanceof Error) {
|
|
907
|
-
return new OpInvalid("Web Media Profile decode failed", resultOp);
|
|
908
|
-
}
|
|
909
|
-
if (media && core.doc.credentialSubject.id !== media.doc.credentialSubject.id) {
|
|
910
|
-
return new OpInvalid(
|
|
911
|
-
"Subject mismatch between Core Profile and Web Media Profile",
|
|
912
|
-
resultOp
|
|
913
|
-
);
|
|
941
|
+
const validated = validateDecodedOp(core, annotations, media, resultOp);
|
|
942
|
+
if (validated instanceof OpInvalid) {
|
|
943
|
+
return validated;
|
|
914
944
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
resultOp
|
|
921
|
-
);
|
|
922
|
-
}
|
|
923
|
-
return resultOp;
|
|
945
|
+
return {
|
|
946
|
+
core,
|
|
947
|
+
annotations: validated.annotations,
|
|
948
|
+
media: validated.media
|
|
949
|
+
};
|
|
924
950
|
});
|
|
925
951
|
if (!isDecodedOps(resultOps)) {
|
|
926
952
|
return new OpsInvalid("Invalid Originator Profile Set", resultOps);
|
|
@@ -937,10 +963,22 @@ function OpVerifier(paOrWmpIssuerKeys, vc, validator) {
|
|
|
937
963
|
const cpKeys = LocalKeys(jwks);
|
|
938
964
|
return JwtVcVerifier(cpKeys, issuer, validator);
|
|
939
965
|
}
|
|
966
|
+
function validateCertificateExpiry(verifiedVc) {
|
|
967
|
+
const now = /* @__PURE__ */ new Date();
|
|
968
|
+
const validFrom = verifiedVc.doc.validFrom ? new Date(verifiedVc.doc.validFrom) : null;
|
|
969
|
+
const validUntil = verifiedVc.doc.validUntil ? new Date(verifiedVc.doc.validUntil) : null;
|
|
970
|
+
if (validFrom && now < validFrom) {
|
|
971
|
+
return new CertificateExpired("Certificate not yet valid", verifiedVc);
|
|
972
|
+
}
|
|
973
|
+
if (validUntil && now > validUntil) {
|
|
974
|
+
return new CertificateExpired("Certificate expired", verifiedVc);
|
|
975
|
+
}
|
|
976
|
+
return verifiedVc;
|
|
977
|
+
}
|
|
940
978
|
async function verifyAnnotations(paIssuerKeys, annotations, validator) {
|
|
941
979
|
if (!annotations) return;
|
|
942
980
|
return await Promise.all(
|
|
943
|
-
annotations.map((annotation) => {
|
|
981
|
+
annotations.map(async (annotation) => {
|
|
944
982
|
const verify = OpVerifier(
|
|
945
983
|
paIssuerKeys,
|
|
946
984
|
annotation,
|
|
@@ -948,18 +986,26 @@ async function verifyAnnotations(paIssuerKeys, annotations, validator) {
|
|
|
948
986
|
oneOf: [Certificate, JapaneseExistenceCertificate]
|
|
949
987
|
})
|
|
950
988
|
);
|
|
951
|
-
|
|
989
|
+
const result = await verify(annotation.source);
|
|
990
|
+
if (result instanceof Error) {
|
|
991
|
+
return result;
|
|
992
|
+
}
|
|
993
|
+
return validateCertificateExpiry(result);
|
|
952
994
|
})
|
|
953
995
|
);
|
|
954
996
|
}
|
|
955
997
|
async function verifyMedia(wmpIssuerKeys, media, validator) {
|
|
956
998
|
if (!media) return;
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
999
|
+
return await Promise.all(
|
|
1000
|
+
media.map((m) => {
|
|
1001
|
+
const verify = OpVerifier(
|
|
1002
|
+
wmpIssuerKeys,
|
|
1003
|
+
m,
|
|
1004
|
+
validator?.(WebMediaProfile)
|
|
1005
|
+
);
|
|
1006
|
+
return verify(m.source);
|
|
1007
|
+
})
|
|
961
1008
|
);
|
|
962
|
-
return await verify(media.source);
|
|
963
1009
|
}
|
|
964
1010
|
const isVerifiedOps = (ops) => ops.every((op) => !(op instanceof OpVerifyFailed));
|
|
965
1011
|
function OpsVerifier(ops, keys, issuer, validator) {
|
|
@@ -993,7 +1039,7 @@ function OpsVerifier(ops, keys, issuer, validator) {
|
|
|
993
1039
|
resultOp
|
|
994
1040
|
);
|
|
995
1041
|
}
|
|
996
|
-
if (media instanceof Error) {
|
|
1042
|
+
if (media && media.some((m) => m instanceof Error)) {
|
|
997
1043
|
return new OpVerifyFailed(
|
|
998
1044
|
"Web Media Profile verify failed",
|
|
999
1045
|
resultOp
|
|
@@ -1034,64 +1080,102 @@ class SiteProfileVerifyFailed extends Error {
|
|
|
1034
1080
|
code = SiteProfileVerifyFailed.code;
|
|
1035
1081
|
}
|
|
1036
1082
|
|
|
1083
|
+
const decodeWebsiteProfiles = (sp, opsVerified) => {
|
|
1084
|
+
const wspSources = sp.sites || (sp.credential ? [sp.credential] : []);
|
|
1085
|
+
if (wspSources.length === 0) {
|
|
1086
|
+
return new SiteProfileInvalid("No Website Profile found", {
|
|
1087
|
+
originators: opsVerified,
|
|
1088
|
+
sites: []
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
const decodeWsp = JwtVcDecoder();
|
|
1092
|
+
const decodedWsps = wspSources.map(decodeWsp);
|
|
1093
|
+
const decodeErrors = decodedWsps.filter((wsp) => wsp instanceof Error);
|
|
1094
|
+
if (decodeErrors.length > 0) {
|
|
1095
|
+
return new SiteProfileInvalid("Website Profile invalid", {
|
|
1096
|
+
originators: opsVerified,
|
|
1097
|
+
sites: decodeErrors
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
return {
|
|
1101
|
+
decodedWsps,
|
|
1102
|
+
wspSources
|
|
1103
|
+
};
|
|
1104
|
+
};
|
|
1037
1105
|
function SpVerifier(sp, keys, issuer, origin, verifyOrigin = true, validator) {
|
|
1038
1106
|
async function verify() {
|
|
1039
1107
|
const verifyOps = OpsVerifier(sp.originators, keys, issuer, validator);
|
|
1040
1108
|
const opsVerified = await verifyOps();
|
|
1041
1109
|
if (opsVerified instanceof OpsInvalid) {
|
|
1042
1110
|
return new SiteProfileInvalid("Originator Profile Set invalid", {
|
|
1043
|
-
originators: opsVerified
|
|
1111
|
+
originators: opsVerified,
|
|
1112
|
+
sites: []
|
|
1044
1113
|
});
|
|
1045
1114
|
}
|
|
1046
1115
|
if (opsVerified instanceof OpsVerifyFailed) {
|
|
1047
1116
|
return new SiteProfileVerifyFailed(
|
|
1048
1117
|
"Originator Profile Set verify failed",
|
|
1049
|
-
{ originators: opsVerified }
|
|
1118
|
+
{ originators: opsVerified, sites: [] }
|
|
1050
1119
|
);
|
|
1051
1120
|
}
|
|
1052
|
-
const
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
return new SiteProfileInvalid("Website Profile invalid", {
|
|
1056
|
-
originators: opsVerified,
|
|
1057
|
-
credential: decodedWsp
|
|
1058
|
-
});
|
|
1121
|
+
const decoded = decodeWebsiteProfiles(sp, opsVerified);
|
|
1122
|
+
if (decoded instanceof SiteProfileInvalid) {
|
|
1123
|
+
return decoded;
|
|
1059
1124
|
}
|
|
1060
|
-
const
|
|
1061
|
-
const
|
|
1062
|
-
(
|
|
1125
|
+
const { decodedWsps, wspSources } = decoded;
|
|
1126
|
+
const verifiedWsps = await Promise.all(
|
|
1127
|
+
decodedWsps.map(async (decodedWsp, index) => {
|
|
1128
|
+
if (decodedWsp instanceof Error) {
|
|
1129
|
+
return decodedWsp;
|
|
1130
|
+
}
|
|
1131
|
+
const wspIssuer = decodedWsp.doc.issuer;
|
|
1132
|
+
const cp = opsVerified.find(
|
|
1133
|
+
(op) => op.core.doc.credentialSubject.id === wspIssuer
|
|
1134
|
+
);
|
|
1135
|
+
if (!cp) {
|
|
1136
|
+
return new CoreProfileNotFound(
|
|
1137
|
+
`Missing Core Profile (${wspIssuer})`,
|
|
1138
|
+
decodedWsp
|
|
1139
|
+
);
|
|
1140
|
+
}
|
|
1141
|
+
const verifyWsp = JwtVcVerifier(
|
|
1142
|
+
LocalKeys(cp.core.doc.credentialSubject.jwks),
|
|
1143
|
+
cp.core.doc.credentialSubject.id,
|
|
1144
|
+
validator?.(WebsiteProfile)
|
|
1145
|
+
);
|
|
1146
|
+
const verified = await verifyWsp(wspSources[index]);
|
|
1147
|
+
if (verified instanceof Error) {
|
|
1148
|
+
return verified;
|
|
1149
|
+
}
|
|
1150
|
+
if (verifyOrigin) {
|
|
1151
|
+
const allowedOrigin = "allowedOrigin" in decodedWsp.doc.credentialSubject ? decodedWsp.doc.credentialSubject.allowedOrigin : decodedWsp.doc.credentialSubject.url;
|
|
1152
|
+
if (!verifyAllowedOrigin(origin, allowedOrigin)) {
|
|
1153
|
+
return new Error("Origin not allowed");
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
return verified;
|
|
1157
|
+
})
|
|
1158
|
+
);
|
|
1159
|
+
const hasCoreProfileNotFound = verifiedWsps.some(
|
|
1160
|
+
(wsp) => wsp instanceof CoreProfileNotFound
|
|
1063
1161
|
);
|
|
1064
|
-
if (
|
|
1162
|
+
if (hasCoreProfileNotFound) {
|
|
1065
1163
|
return new SiteProfileInvalid("Appropriate Core Profile not found", {
|
|
1066
1164
|
originators: opsVerified,
|
|
1067
|
-
|
|
1068
|
-
`Missing Core Profile (${wspIssuer})`,
|
|
1069
|
-
decodedWsp
|
|
1070
|
-
)
|
|
1165
|
+
sites: verifiedWsps
|
|
1071
1166
|
});
|
|
1072
1167
|
}
|
|
1073
|
-
const
|
|
1074
|
-
|
|
1075
|
-
cp.core.doc.credentialSubject.id,
|
|
1076
|
-
validator?.(WebsiteProfile)
|
|
1077
|
-
);
|
|
1078
|
-
const credential = await verifyWsp(sp.credential);
|
|
1079
|
-
if (credential instanceof Error) {
|
|
1168
|
+
const hasError = verifiedWsps.some((wsp) => wsp instanceof Error);
|
|
1169
|
+
if (hasError) {
|
|
1080
1170
|
return new SiteProfileVerifyFailed("Website Profile verify failed", {
|
|
1081
1171
|
originators: opsVerified,
|
|
1082
|
-
|
|
1172
|
+
sites: verifiedWsps
|
|
1083
1173
|
});
|
|
1084
1174
|
}
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
originators: opsVerified,
|
|
1090
|
-
credential
|
|
1091
|
-
});
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
return { originators: opsVerified, credential };
|
|
1175
|
+
return {
|
|
1176
|
+
originators: opsVerified,
|
|
1177
|
+
sites: verifiedWsps
|
|
1178
|
+
};
|
|
1095
1179
|
}
|
|
1096
1180
|
return verify;
|
|
1097
1181
|
}
|
|
@@ -1155,4 +1239,4 @@ function validateCertificationSystem(payload) {
|
|
|
1155
1239
|
return payload;
|
|
1156
1240
|
}
|
|
1157
1241
|
|
|
1158
|
-
export { CaInvalid, CaVerifier, CaVerifyFailed, CasVerifyFailed, 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 };
|
|
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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@originator-profile/verify",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-beta.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://docs.originator-profile.org",
|
|
6
6
|
"repository": {
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"ajv-formats": "^3.0.1",
|
|
35
35
|
"jose": "^6.0.10",
|
|
36
36
|
"jsonld": "^9.0.0",
|
|
37
|
-
"@originator-profile/
|
|
38
|
-
"@originator-profile/
|
|
39
|
-
"@originator-profile/
|
|
40
|
-
"@originator-profile/
|
|
41
|
-
"@originator-profile/sign": "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"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@playwright/test": "^1.57.0",
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
"vite": "^7.0.0",
|
|
55
55
|
"vitest": "^4.0.0",
|
|
56
56
|
"websri": "^1.0.1",
|
|
57
|
-
"@originator-profile/tsconfig": "0.
|
|
58
|
-
"eslint-config-originator-profile": "0.
|
|
57
|
+
"@originator-profile/tsconfig": "0.5.0-beta.1",
|
|
58
|
+
"eslint-config-originator-profile": "0.5.0-beta.1"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
61
61
|
"build": "pkgroll --clean-dist --target=node20",
|