@fedify/fedify 2.4.0-dev.2077 → 2.4.0-dev.2093
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/{builder-i3jxVe9m.mjs → builder-Ld4Y9ymR.mjs} +34 -3
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{compound-proof-Cayy-ECj.mjs → compound-proof-CTx_lewQ.mjs} +191 -13
- package/dist/{deno-Djkzd-G_.mjs → deno-8t8k_6Yv.mjs} +1 -1
- package/dist/{docloader-dA0RswUV.mjs → docloader-DJKcsAiF.mjs} +2 -2
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/compound-fanout.test.mjs +3 -3
- package/dist/federation/handler-compound-proof.test.mjs +3 -3
- package/dist/federation/handler.test.mjs +5 -5
- package/dist/federation/hashlink-media.test.mjs +2 -2
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +7 -7
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.js +1 -1
- package/dist/federation/outgoing-proof.test.mjs +254 -5
- package/dist/federation/portable-gateway-keys.test.mjs +72 -11
- package/dist/federation/portable-inbox.test.mjs +513 -6
- package/dist/federation/portable.test.mjs +182 -4
- package/dist/federation/send.test.mjs +3 -3
- package/dist/federation/tasks/enqueue.test.mjs +1 -1
- package/dist/federation/tasks/tasks.test.mjs +2 -2
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +89 -1
- package/dist/{federation-CFd0Jhhv.cjs → federation-aSHO04ob.cjs} +472 -74
- package/dist/{http-CCJ97Jql.mjs → http-B2ftY0Ha.mjs} +4 -4
- package/dist/{http-Dvy_IwRa.cjs → http-DSaSAN7X.cjs} +1609 -1457
- package/dist/{http-aqh3yFdM.js → http-DyT7DP1Y.js} +1518 -1390
- package/dist/{key-IxTTC8Yf.mjs → key-Dwm4VswT.mjs} +39 -99
- package/dist/{kv-cache-BP69NV0P.cjs → kv-cache-BSJAlP4C.cjs} +1 -1
- package/dist/{kv-cache-Bwwbh-xR.mjs → kv-cache-D0yYukqk.mjs} +1 -1
- package/dist/{kv-cache-Y6SDRSX6.js → kv-cache-DmroAz3M.js} +1 -1
- package/dist/{ld-l0B9nREb.mjs → ld-BYZOoDzZ.mjs} +3 -3
- package/dist/{metrics-D1p6hv4z.mjs → metrics-B7YwKTFr.mjs} +1 -1
- package/dist/{middleware-BDjCUHMS.mjs → middleware-BNeqKSsL.mjs} +1 -1
- package/dist/{middleware-SSfryVzY.js → middleware-Blq0882d.js} +480 -82
- package/dist/{middleware-BMgzqBtr.mjs → middleware-E_0IH72m.mjs} +278 -80
- package/dist/{mod-HDSvS-ww.d.cts → mod-C8LieBzF.d.cts} +16 -3
- package/dist/{mod-C9WSpZWm.d.ts → mod-Coacostr.d.ts} +16 -3
- package/dist/mod.cjs +5 -5
- package/dist/mod.d.cts +1 -1
- package/dist/mod.d.ts +1 -1
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/{owner-DGbYmXqU.mjs → owner-Cgx2Dc7I.mjs} +5 -4
- package/dist/{owner-jH1z_YfD.js → owner-DAGSC5gX.js} +2 -2
- package/dist/{owner-BpOxL5PG.cjs → owner-szIZl4qI.cjs} +2 -2
- package/dist/{portable-key-CCwJGSsU.mjs → portable-key-Cn1WJSN1.mjs} +60 -41
- package/dist/portable-key-id-Bva5iT3W.mjs +136 -0
- package/dist/{proof-CVL7JnZd.mjs → proof-DVXC6nYz.mjs} +59 -18
- package/dist/{send-Ejy1jOz9.mjs → send-D-hOvYKy.mjs} +3 -3
- package/dist/sig/compound-proof-discovery.test.mjs +1 -1
- package/dist/sig/compound-proof-producer.test.mjs +1 -1
- package/dist/sig/compound-proof-verification.test.mjs +160 -3
- package/dist/sig/compound-proof.test.mjs +2 -2
- package/dist/sig/http.test.mjs +2 -2
- package/dist/sig/key.test.mjs +1 -1
- package/dist/sig/ld.test.mjs +2 -2
- package/dist/sig/mod.cjs +3 -3
- package/dist/sig/mod.d.cts +1 -1
- package/dist/sig/mod.d.ts +1 -1
- package/dist/sig/mod.js +3 -3
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/portable-collection.test.mjs +69 -5
- package/dist/sig/portable-key.test.mjs +176 -10
- package/dist/sig/proof.test.mjs +107 -4
- package/dist/{sig-Dpy1B1Ad.js → sig-B5Ell7pO.js} +19 -3
- package/dist/{sig-xoqy3ATq.cjs → sig-CXOKN4Br.cjs} +19 -3
- package/dist/{temporal-DNJ1cNpr.mjs → temporal-CqpKGEPk.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/utils/docloader.test.mjs +2 -2
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +7 -7
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-
|
|
6
|
-
import { r as
|
|
4
|
+
import { n as version, t as name } from "./deno-8t8k_6Yv.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-B7YwKTFr.mjs";
|
|
6
|
+
import { r as getPortableDid, s as isPortableId } from "./portable-key-id-Bva5iT3W.mjs";
|
|
7
|
+
import { r as fetchKey, s as validateCryptoKey } from "./key-Dwm4VswT.mjs";
|
|
7
8
|
import { n as preloadedOnlyDocumentLoader } from "./public-audience--klBIOk1.mjs";
|
|
8
9
|
import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-4IJqPYos.mjs";
|
|
9
|
-
import { c as getNormalizationContextLoader } from "./ld-
|
|
10
|
+
import { c as getNormalizationContextLoader } from "./ld-BYZOoDzZ.mjs";
|
|
10
11
|
import { getLogger } from "@logtape/logtape";
|
|
11
12
|
import { Activity, DataIntegrityProof, Multikey, getTypeId } from "@fedify/vocab";
|
|
12
13
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
13
|
-
import { encodeMultibase, formatIri, getDocumentLoader, getFe34Origin,
|
|
14
|
+
import { encodeMultibase, formatIri, fromCompatibleEf61Id, getDocumentLoader, getFe34Origin, parseIri } from "@fedify/vocab-runtime";
|
|
14
15
|
import { encodeHex } from "byte-encodings/hex";
|
|
15
16
|
import { isPlainJsonTree, retainSignedRepresentation } from "@fedify/vocab-runtime/internal/signed-representation";
|
|
16
17
|
import jsonld from "@fedify/vocab-runtime/jsonld";
|
|
@@ -736,8 +737,37 @@ async function expandPortableObjectRoot(jsonLd, contextLoader) {
|
|
|
736
737
|
}
|
|
737
738
|
};
|
|
738
739
|
}
|
|
740
|
+
/**
|
|
741
|
+
* Gets the DID of a portable object ID, which is either an `ap:` or
|
|
742
|
+
* `ap+ef61:` URI or an FEP-ef61 compatible identifier.
|
|
743
|
+
* @throws {TypeError} If the ID is malformed.
|
|
744
|
+
*/
|
|
745
|
+
function getObjectDid(id) {
|
|
746
|
+
try {
|
|
747
|
+
parseIri(id);
|
|
748
|
+
if (PORTABLE_OBJECT_ID_PATTERN.test(id)) return getFe34Origin(id);
|
|
749
|
+
const portableId = fromCompatibleEf61Id(id);
|
|
750
|
+
if (portableId != null) return getFe34Origin(portableId);
|
|
751
|
+
} catch (error) {
|
|
752
|
+
if (!(error instanceof TypeError)) throw error;
|
|
753
|
+
throw new InvalidPortableObjectIdError(id, { cause: error });
|
|
754
|
+
}
|
|
755
|
+
throw new InvalidPortableObjectIdError(id);
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* The error thrown when a document's ID looks portable, i.e., it is an `ap:`
|
|
759
|
+
* or `ap+ef61:` URI or looks like an FEP-ef61 compatible identifier, but is
|
|
760
|
+
* malformed.
|
|
761
|
+
* @internal
|
|
762
|
+
*/
|
|
763
|
+
var InvalidPortableObjectIdError = class extends TypeError {
|
|
764
|
+
constructor(id, options) {
|
|
765
|
+
super(`Invalid portable object ID: ${id}`, options);
|
|
766
|
+
this.name = "InvalidPortableObjectIdError";
|
|
767
|
+
}
|
|
768
|
+
};
|
|
739
769
|
async function preparePortableObjectProof(jsonLd, options) {
|
|
740
|
-
if (isJsonLdNode(jsonLd) && typeof jsonLd["@id"] === "string" && !
|
|
770
|
+
if (isJsonLdNode(jsonLd) && typeof jsonLd["@id"] === "string" && !isPortableId(jsonLd["@id"])) return {
|
|
741
771
|
prepared: false,
|
|
742
772
|
result: {
|
|
743
773
|
verified: false,
|
|
@@ -746,15 +776,15 @@ async function preparePortableObjectProof(jsonLd, options) {
|
|
|
746
776
|
};
|
|
747
777
|
const { root, proofContextLoader } = await expandPortableObjectRoot(jsonLd, options.contextLoader);
|
|
748
778
|
const id = root["@id"];
|
|
749
|
-
if (typeof id !== "string" || !
|
|
779
|
+
if (typeof id !== "string" || !isPortableId(id)) return {
|
|
750
780
|
prepared: false,
|
|
751
781
|
result: {
|
|
752
782
|
verified: false,
|
|
753
783
|
reason: { type: "notPortableObject" }
|
|
754
784
|
}
|
|
755
785
|
};
|
|
786
|
+
const objectDid = getObjectDid(id);
|
|
756
787
|
const objectId = parseIri(id);
|
|
757
|
-
getFe34Origin(objectId);
|
|
758
788
|
const objectType = classifyFep2277CoreType(root);
|
|
759
789
|
if (objectType === "verificationMethod" || objectType === "publicKey" || objectType === "link") return {
|
|
760
790
|
prepared: false,
|
|
@@ -859,7 +889,7 @@ async function preparePortableObjectProof(jsonLd, options) {
|
|
|
859
889
|
}
|
|
860
890
|
};
|
|
861
891
|
}
|
|
862
|
-
if (
|
|
892
|
+
if (getFe34Origin(verificationMethod) !== objectDid) return {
|
|
863
893
|
prepared: false,
|
|
864
894
|
result: {
|
|
865
895
|
verified: false,
|
|
@@ -918,15 +948,24 @@ async function verifyPortableObjectProofPolicy(jsonLd, key, options = {}) {
|
|
|
918
948
|
* collection without a proof is reported separately so a caller can apply a
|
|
919
949
|
* gateway trust policy. Embedded portable objects are not traversed.
|
|
920
950
|
*
|
|
951
|
+
* A portable object is a document whose ID is an `ap:` or `ap+ef61:` URI, or
|
|
952
|
+
* an [FEP-ef61] compatible identifier such as
|
|
953
|
+
* `https://gw.example/.well-known/apgateway/did:key:z6Mk…/actor`, which
|
|
954
|
+
* stands for the portable ID `ap+ef61://did:key:z6Mk…/actor`.
|
|
955
|
+
*
|
|
921
956
|
* Every proof must use a DID URL whose DID matches the portable object's
|
|
922
|
-
* authority, and every proof must
|
|
957
|
+
* authority, i.e., the DID of its canonical portable ID, and every proof must
|
|
958
|
+
* pass {@link verifyProof}. The proofs are verified over the document as
|
|
959
|
+
* given; a compatible identifier is never rewritten into a portable ID.
|
|
960
|
+
*
|
|
961
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
923
962
|
*
|
|
924
963
|
* @param jsonLd The JSON-LD document to verify.
|
|
925
964
|
* @param options Additional options. See also
|
|
926
965
|
* {@link VerifyPortableObjectProofOptions}.
|
|
927
966
|
* @returns The detailed portable proof-policy result.
|
|
928
967
|
* @throws {TypeError} If the input is not a single JSON-LD object or has a
|
|
929
|
-
* malformed portable ID.
|
|
968
|
+
* malformed portable ID or compatible identifier.
|
|
930
969
|
* @since 2.4.0
|
|
931
970
|
*/
|
|
932
971
|
async function verifyPortableObjectProof(jsonLd, options = {}) {
|
|
@@ -1026,7 +1065,7 @@ async function verifyObject(cls, jsonLd, options = {}) {
|
|
|
1026
1065
|
};
|
|
1027
1066
|
const proofDocumentLoader = async (url, loaderOptions) => {
|
|
1028
1067
|
const remoteDocument = await baseDocumentLoader(url, loaderOptions);
|
|
1029
|
-
if (
|
|
1068
|
+
if (isPortableId(url)) loadedPortableProofs++;
|
|
1030
1069
|
const reference = normalizeDocumentUrl(url);
|
|
1031
1070
|
const candidateIndex = rawProofCandidates.findIndex((candidate, index) => !hydratedCandidates.has(index) && !rawProofCandidatePool.used.has(index) && candidate.reference === reference);
|
|
1032
1071
|
if (candidateIndex >= 0) {
|
|
@@ -1076,14 +1115,16 @@ async function verifyObject(cls, jsonLd, options = {}) {
|
|
|
1076
1115
|
return object;
|
|
1077
1116
|
}
|
|
1078
1117
|
function deleteAuthenticatedAttribution(attributions, controllerId, verificationMethodId) {
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1118
|
+
if (!hasCryptographicOrigin(controllerId.href) && !isPortableId(controllerId)) {
|
|
1119
|
+
attributions.delete(controllerId.href);
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1122
|
+
const did = getPortableDid(controllerId);
|
|
1123
|
+
if (did == null || !hasCryptographicOrigin(verificationMethodId.href) || getPortableDid(verificationMethodId) !== did) return;
|
|
1124
|
+
for (const attribution of [...attributions]) if ((hasCryptographicOrigin(attribution) || isPortableId(attribution)) && getPortableDid(attribution) === did) attributions.delete(attribution);
|
|
1084
1125
|
}
|
|
1085
1126
|
function hasCryptographicOrigin(iri) {
|
|
1086
1127
|
return /^did:/i.test(iri) || /^ap(?:\+ef61)?:\/\//i.test(iri);
|
|
1087
1128
|
}
|
|
1088
1129
|
//#endregion
|
|
1089
|
-
export {
|
|
1130
|
+
export { verifyMapLocalProof as a, verifyPortableObjectProofPolicy as c, signObject as i, verifyPortableObjectProofWithRoot as l, createProof as n, verifyObject as o, hasProofLike as r, verifyPortableObjectProof as s, InvalidPortableObjectIdError as t, verifyProof as u };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { n as getDurationMs, r as getFederationMetrics } from "./metrics-
|
|
6
|
-
import { n as doubleKnock } from "./http-
|
|
4
|
+
import { n as version, t as name } from "./deno-8t8k_6Yv.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics } from "./metrics-B7YwKTFr.mjs";
|
|
6
|
+
import { n as doubleKnock } from "./http-B2ftY0Ha.mjs";
|
|
7
7
|
import { getLogger } from "@logtape/logtape";
|
|
8
8
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
9
9
|
import { FetchError, UrlError, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
@@ -3,7 +3,7 @@ import "urlpattern-polyfill";
|
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
|
|
5
5
|
import "../std__assert-DvMDRPes.mjs";
|
|
6
|
-
import { i as inspectCompoundPortableObjectApplicability, n as discoverCompoundProofDocuments } from "../compound-proof-
|
|
6
|
+
import { i as inspectCompoundPortableObjectApplicability, n as discoverCompoundProofDocuments } from "../compound-proof-CTx_lewQ.mjs";
|
|
7
7
|
import { t as map_local_create_note_default } from "../map-local-create-note-B0SeXJms.mjs";
|
|
8
8
|
import { test } from "@fedify/fixture";
|
|
9
9
|
//#region src/sig/compound-proof-discovery.test.ts
|
|
@@ -3,7 +3,7 @@ import "urlpattern-polyfill";
|
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
|
|
5
5
|
import "../std__assert-DvMDRPes.mjs";
|
|
6
|
-
import { i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, t as containsCompoundPortableObject } from "../compound-proof-
|
|
6
|
+
import { i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, t as containsCompoundPortableObject } from "../compound-proof-CTx_lewQ.mjs";
|
|
7
7
|
import { test } from "@fedify/fixture";
|
|
8
8
|
//#region src/sig/compound-proof-producer.test.ts
|
|
9
9
|
const portableId = "ap+ef61://did:key:z6MkAlice/objects/1";
|
|
@@ -4,12 +4,14 @@ globalThis.addEventListener = () => {};
|
|
|
4
4
|
import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
|
|
5
5
|
import "../std__assert-DvMDRPes.mjs";
|
|
6
6
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { a as verifyMapLocalProof, c as verifyPortableObjectProofPolicy } from "../proof-DVXC6nYz.mjs";
|
|
8
|
+
import { n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
|
|
9
|
+
import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, o as verifyCompoundProofDocuments, t as containsCompoundPortableObject } from "../compound-proof-CTx_lewQ.mjs";
|
|
9
10
|
import { t as map_local_create_note_default } from "../map-local-create-note-B0SeXJms.mjs";
|
|
10
11
|
import { t as map_local_context_conflict_default } from "../map-local-context-conflict-DOYEEJ3u.mjs";
|
|
12
|
+
import { CryptographicKey, Multikey, Person } from "@fedify/vocab";
|
|
11
13
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
12
|
-
import { encodeMultibase } from "@fedify/vocab-runtime";
|
|
14
|
+
import { encodeMultibase, exportDidKey, parseIri } from "@fedify/vocab-runtime";
|
|
13
15
|
import serialize from "json-canon";
|
|
14
16
|
//#region src/sig/compound-proof-verification.test.ts
|
|
15
17
|
const limits = {
|
|
@@ -461,5 +463,160 @@ test("verifyCompoundPortableObjectProofs() reports the policy-validated ID", asy
|
|
|
461
463
|
assertEquals(result.portableObjects.length, 1);
|
|
462
464
|
assertEquals(result.portableObjects[0].id, map_local_create_note_default.documents.innerUnsecuredDocument.id);
|
|
463
465
|
});
|
|
466
|
+
const compatibleDid = await exportDidKey(ed25519PublicKey.publicKey);
|
|
467
|
+
const compatibleVerificationMethod = `${compatibleDid}#${compatibleDid.slice(8)}`;
|
|
468
|
+
const compatibleActorId = `https://gw.example/.well-known/apgateway/${compatibleDid}/actor`;
|
|
469
|
+
const compatibleContext = ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/data-integrity/v1"];
|
|
470
|
+
async function signCompatible(document) {
|
|
471
|
+
return await secureRawDocument(document, await crypto.subtle.exportKey("jwk", ed25519PrivateKey), compatibleVerificationMethod);
|
|
472
|
+
}
|
|
473
|
+
async function compatibleActor(id = compatibleActorId, keyBase = compatibleActorId) {
|
|
474
|
+
const actorId = parseIri(id);
|
|
475
|
+
return await new Person({
|
|
476
|
+
id: actorId,
|
|
477
|
+
inbox: new URL(`${keyBase}/inbox`),
|
|
478
|
+
outbox: new URL(`${keyBase}/outbox`),
|
|
479
|
+
gateways: [new URL("https://gw.example")],
|
|
480
|
+
publicKey: new CryptographicKey({
|
|
481
|
+
id: new URL(`${keyBase}#main-key`),
|
|
482
|
+
owner: actorId,
|
|
483
|
+
publicKey: rsaPublicKey2.publicKey
|
|
484
|
+
}),
|
|
485
|
+
assertionMethods: [new Multikey({
|
|
486
|
+
id: new URL(`${keyBase}#ed25519-key`),
|
|
487
|
+
controller: actorId,
|
|
488
|
+
publicKey: ed25519PublicKey.publicKey
|
|
489
|
+
})]
|
|
490
|
+
}).toJsonLd({
|
|
491
|
+
format: "compact",
|
|
492
|
+
contextLoader: mockDocumentLoader
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
test("verifyCompoundPortableObjectProofs() treats compatible-ID maps as portable", async () => {
|
|
496
|
+
const note = {
|
|
497
|
+
"@context": [...compatibleContext],
|
|
498
|
+
id: `${compatibleActorId}/notes/1`,
|
|
499
|
+
type: "Note",
|
|
500
|
+
attributedTo: compatibleActorId,
|
|
501
|
+
content: "Hello"
|
|
502
|
+
};
|
|
503
|
+
const ordinary = {
|
|
504
|
+
"@context": [...compatibleContext],
|
|
505
|
+
id: "https://social.example/activities/1",
|
|
506
|
+
type: "Announce",
|
|
507
|
+
actor: "https://social.example/users/bob",
|
|
508
|
+
object: note
|
|
509
|
+
};
|
|
510
|
+
assertEquals(inspectCompoundPortableObjectApplicability(ordinary, limits), "present");
|
|
511
|
+
assert(containsCompoundPortableObject(ordinary));
|
|
512
|
+
const result = await verifyCompoundPortableObjectProofs(ordinary, limits, options);
|
|
513
|
+
assert(result.status === "ok");
|
|
514
|
+
assertEquals(result.verified, false);
|
|
515
|
+
assertEquals(result.portableObjects.map((o) => [o.path, o.verified]), [["/object", false]]);
|
|
516
|
+
const signed = await verifyCompoundPortableObjectProofs({
|
|
517
|
+
...ordinary,
|
|
518
|
+
object: await signCompatible(note)
|
|
519
|
+
}, limits, options);
|
|
520
|
+
assert(signed.status === "ok");
|
|
521
|
+
assert(signed.verified);
|
|
522
|
+
});
|
|
523
|
+
test("verifyCompoundPortableObjectProofs() checks compatible activity IDs", async () => {
|
|
524
|
+
const create = (did) => ({
|
|
525
|
+
"@context": [...compatibleContext],
|
|
526
|
+
id: `https://gw.example/.well-known/apgateway/${did}/activities/1`,
|
|
527
|
+
type: "Create",
|
|
528
|
+
actor: compatibleActorId,
|
|
529
|
+
object: "https://social.example/notes/1"
|
|
530
|
+
});
|
|
531
|
+
const own = await verifyCompoundPortableObjectProofs(await signCompatible(create(compatibleDid)), limits, options);
|
|
532
|
+
assert(own.status === "ok");
|
|
533
|
+
assert(own.verified);
|
|
534
|
+
const forged = await verifyCompoundPortableObjectProofs(await signCompatible(create("did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK")), limits, options);
|
|
535
|
+
assert(forged.status === "ok");
|
|
536
|
+
assertEquals(forged.verified, false);
|
|
537
|
+
const [object] = forged.portableObjects;
|
|
538
|
+
assert(!object.verified);
|
|
539
|
+
assertEquals(object.reason.type, "verificationMethodMismatch");
|
|
540
|
+
});
|
|
541
|
+
test("verifyCompoundPortableObjectProofs() exempts keys embedded in portable actors", async () => {
|
|
542
|
+
let result = await verifyCompoundPortableObjectProofs(await signCompatible(await compatibleActor()), limits, options);
|
|
543
|
+
assert(result.status === "ok");
|
|
544
|
+
assert(result.verified);
|
|
545
|
+
assertEquals(result.portableObjects.map((o) => o.path), [""]);
|
|
546
|
+
result = await verifyCompoundPortableObjectProofs(await signCompatible(await compatibleActor(`ap://${compatibleDid}/actor`)), limits, options);
|
|
547
|
+
assert(result.status === "ok");
|
|
548
|
+
assert(result.verified);
|
|
549
|
+
result = await verifyCompoundPortableObjectProofs({
|
|
550
|
+
"@context": [...compatibleContext],
|
|
551
|
+
id: "https://social.example/activities/2",
|
|
552
|
+
type: "Update",
|
|
553
|
+
actor: "https://social.example/users/bob",
|
|
554
|
+
object: await signCompatible(await compatibleActor())
|
|
555
|
+
}, limits, options);
|
|
556
|
+
assert(result.status === "ok");
|
|
557
|
+
assert(result.verified);
|
|
558
|
+
});
|
|
559
|
+
test("verifyCompoundPortableObjectProofs() exempts only keys of the parent itself", async () => {
|
|
560
|
+
const actor = await compatibleActor();
|
|
561
|
+
const otherActorId = "https://gw.example/.well-known/apgateway/did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK/actor";
|
|
562
|
+
const publicKey = actor.publicKey;
|
|
563
|
+
const cases = {
|
|
564
|
+
"a key of another actor": {
|
|
565
|
+
...actor,
|
|
566
|
+
publicKey: {
|
|
567
|
+
...publicKey,
|
|
568
|
+
id: `${otherActorId}#main-key`,
|
|
569
|
+
owner: otherActorId
|
|
570
|
+
}
|
|
571
|
+
},
|
|
572
|
+
"a key owned by another actor": {
|
|
573
|
+
...actor,
|
|
574
|
+
publicKey: {
|
|
575
|
+
...publicKey,
|
|
576
|
+
owner: otherActorId
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
"a non-key object": {
|
|
580
|
+
...actor,
|
|
581
|
+
publicKey: {
|
|
582
|
+
id: `${compatibleActorId}#note`,
|
|
583
|
+
type: "Note",
|
|
584
|
+
content: "Not a key"
|
|
585
|
+
}
|
|
586
|
+
},
|
|
587
|
+
"a key with extra content": {
|
|
588
|
+
...actor,
|
|
589
|
+
publicKey: {
|
|
590
|
+
...publicKey,
|
|
591
|
+
name: "Extra"
|
|
592
|
+
}
|
|
593
|
+
},
|
|
594
|
+
"a key under another property": {
|
|
595
|
+
...actor,
|
|
596
|
+
attachment: structuredClone(publicKey)
|
|
597
|
+
},
|
|
598
|
+
"a parent context with a keyword alias": {
|
|
599
|
+
...actor,
|
|
600
|
+
"@context": [...actor["@context"], { kind: "@type" }]
|
|
601
|
+
},
|
|
602
|
+
"a key with a scoped context": {
|
|
603
|
+
...actor,
|
|
604
|
+
publicKey: {
|
|
605
|
+
...publicKey,
|
|
606
|
+
"@context": { CryptographicKey: {
|
|
607
|
+
"@id": "https://w3id.org/security#Key",
|
|
608
|
+
"@context": {}
|
|
609
|
+
} }
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
for (const [name, document] of Object.entries(cases)) {
|
|
614
|
+
const result = await verifyCompoundPortableObjectProofs(await signCompatible(document), limits, options);
|
|
615
|
+
assert(result.status === "ok", name);
|
|
616
|
+
assertEquals(result.verified, false, name);
|
|
617
|
+
assert(result.portableObjects.find((o) => o.path === "")?.verified, name);
|
|
618
|
+
assert(result.portableObjects.some((o) => o.path !== "" && !o.verified), name);
|
|
619
|
+
}
|
|
620
|
+
});
|
|
464
621
|
//#endregion
|
|
465
622
|
export {};
|
|
@@ -6,9 +6,9 @@ import "../std__assert-DvMDRPes.mjs";
|
|
|
6
6
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
7
7
|
import { n as preloadedOnlyDocumentLoader } from "../public-audience--klBIOk1.mjs";
|
|
8
8
|
import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-4IJqPYos.mjs";
|
|
9
|
-
import {
|
|
9
|
+
import { i as signObject, u as verifyProof } from "../proof-DVXC6nYz.mjs";
|
|
10
10
|
import { n as ed25519PrivateKey, r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
|
|
11
|
-
import { o as verifyCompoundProofDocuments } from "../compound-proof-
|
|
11
|
+
import { o as verifyCompoundProofDocuments } from "../compound-proof-CTx_lewQ.mjs";
|
|
12
12
|
import { t as map_local_create_note_default } from "../map-local-create-note-B0SeXJms.mjs";
|
|
13
13
|
import { t as map_local_context_conflict_default } from "../map-local-context-conflict-DOYEEJ3u.mjs";
|
|
14
14
|
import { Create, DataIntegrityProof, Note, Question } from "@fedify/vocab";
|
package/dist/sig/http.test.mjs
CHANGED
|
@@ -11,8 +11,8 @@ import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
|
|
|
11
11
|
import "../std__assert-DvMDRPes.mjs";
|
|
12
12
|
import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
|
|
13
13
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
14
|
-
import { t as exportJwk } from "../key-
|
|
15
|
-
import { a as parseRfc9421Signature, c as timingSafeEqual, i as formatRfc9421SignatureParameters, l as verifyRequest, n as doubleKnock, o as parseRfc9421SignatureInput, r as formatRfc9421Signature, s as signRequest, t as createRfc9421SignatureBase, u as verifyRequestDetailed } from "../http-
|
|
14
|
+
import { t as exportJwk } from "../key-Dwm4VswT.mjs";
|
|
15
|
+
import { a as parseRfc9421Signature, c as timingSafeEqual, i as formatRfc9421SignatureParameters, l as verifyRequest, n as doubleKnock, o as parseRfc9421SignatureInput, r as formatRfc9421Signature, s as signRequest, t as createRfc9421SignatureBase, u as verifyRequestDetailed } from "../http-B2ftY0Ha.mjs";
|
|
16
16
|
import { i as rsaPrivateKey2, l as rsaPublicKey5, o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
|
|
17
17
|
import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
18
18
|
import { FetchError, exportSpki } from "@fedify/vocab-runtime";
|
package/dist/sig/key.test.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
|
|
|
6
6
|
import "../std__assert-DvMDRPes.mjs";
|
|
7
7
|
import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
|
|
8
8
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
9
|
-
import { a as generateCryptoKeyPair, i as fetchKeyDetailed, o as importJwk, r as fetchKey, s as validateCryptoKey, t as exportJwk } from "../key-
|
|
9
|
+
import { a as generateCryptoKeyPair, i as fetchKeyDetailed, o as importJwk, r as fetchKey, s as validateCryptoKey, t as exportJwk } from "../key-Dwm4VswT.mjs";
|
|
10
10
|
import { c as rsaPublicKey3, i as rsaPrivateKey2, o as rsaPublicKey1, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
|
|
11
11
|
import { CryptographicKey, Multikey } from "@fedify/vocab";
|
|
12
12
|
import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
package/dist/sig/ld.test.mjs
CHANGED
|
@@ -8,8 +8,8 @@ import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
|
|
|
8
8
|
import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
|
|
9
9
|
import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
|
|
10
10
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
11
|
-
import { a as generateCryptoKeyPair } from "../key-
|
|
12
|
-
import { a as compactJsonLd, f as isInvalidUrlTypeError, g as verifySignature, h as verifyJsonLd, i as attachSignature, n as UnsafeJsonLdError, o as createSignature, p as signJsonLd, s as detachSignature, u as hasSignatureLike } from "../ld-
|
|
11
|
+
import { a as generateCryptoKeyPair } from "../key-Dwm4VswT.mjs";
|
|
12
|
+
import { a as compactJsonLd, f as isInvalidUrlTypeError, g as verifySignature, h as verifyJsonLd, i as attachSignature, n as UnsafeJsonLdError, o as createSignature, p as signJsonLd, s as detachSignature, u as hasSignatureLike } from "../ld-BYZOoDzZ.mjs";
|
|
13
13
|
import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
|
|
14
14
|
import { CryptographicKey } from "@fedify/vocab";
|
|
15
15
|
import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
package/dist/sig/mod.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const require_http = require("../http-
|
|
4
|
-
const require_owner = require("../owner-
|
|
5
|
-
const require_sig = require("../sig-
|
|
3
|
+
const require_http = require("../http-DSaSAN7X.cjs");
|
|
4
|
+
const require_owner = require("../owner-szIZl4qI.cjs");
|
|
5
|
+
const require_sig = require("../sig-CXOKN4Br.cjs");
|
|
6
6
|
exports.attachSignature = require_http.attachSignature;
|
|
7
7
|
exports.createProof = require_http.createProof;
|
|
8
8
|
exports.createSignature = require_http.createSignature;
|
package/dist/sig/mod.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
2
|
import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "../http-xlG-jRdB.cjs";
|
|
3
3
|
import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "../owner-BF0L9cMt.cjs";
|
|
4
|
-
import { C as createSignature, D as verifyJsonLd, E as signJsonLd, O as verifySignature, S as attachSignature, T as hasSignatureLike, _ as verifyProof, a as CreateProofOptions, b as VerifyJsonLdOptions, c as VerifyPortableObjectProofFailureReason, d as VerifyProofOptions, f as createProof, g as verifyPortableObjectProof, h as verifyObject, i as verifyPortableObject, l as VerifyPortableObjectProofOptions, m as signObject, n as VerifyPortableObjectOptions, o as SignObjectOptions, p as hasProofLike, r as VerifyPortableObjectResult, s as VerifyObjectOptions, t as VerifyPortableObjectFailureReason, u as VerifyPortableObjectProofResult, v as CreateSignatureOptions, w as detachSignature, x as VerifySignatureOptions, y as SignJsonLdOptions } from "../mod-
|
|
4
|
+
import { C as createSignature, D as verifyJsonLd, E as signJsonLd, O as verifySignature, S as attachSignature, T as hasSignatureLike, _ as verifyProof, a as CreateProofOptions, b as VerifyJsonLdOptions, c as VerifyPortableObjectProofFailureReason, d as VerifyProofOptions, f as createProof, g as verifyPortableObjectProof, h as verifyObject, i as verifyPortableObject, l as VerifyPortableObjectProofOptions, m as signObject, n as VerifyPortableObjectOptions, o as SignObjectOptions, p as hasProofLike, r as VerifyPortableObjectResult, s as VerifyObjectOptions, t as VerifyPortableObjectFailureReason, u as VerifyPortableObjectProofResult, v as CreateSignatureOptions, w as detachSignature, x as VerifySignatureOptions, y as SignJsonLdOptions } from "../mod-C8LieBzF.cjs";
|
|
5
5
|
export { AcceptSignatureMember, AcceptSignatureParameters, CreateProofOptions, CreateSignatureOptions, DoesActorOwnKeyOptions, FetchKeyDetailedResult, FetchKeyErrorResult, FetchKeyOptions, FetchKeyResult, FulfillAcceptSignatureResult, GetKeyOwnerOptions, HttpMessageSignaturesSpec, HttpMessageSignaturesSpecDeterminer, KeyCache, Rfc9421SignRequestOptions, SignJsonLdOptions, SignObjectOptions, SignRequestOptions, VerifyJsonLdOptions, VerifyObjectOptions, VerifyPortableObjectFailureReason, VerifyPortableObjectOptions, VerifyPortableObjectProofFailureReason, VerifyPortableObjectProofOptions, VerifyPortableObjectProofResult, VerifyPortableObjectResult, VerifyProofOptions, VerifyRequestDetailedResult, VerifyRequestFailureReason, VerifyRequestOptions, VerifySignatureOptions, attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, hasProofLike, hasSignatureLike, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyPortableObject, verifyPortableObjectProof, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
|
package/dist/sig/mod.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
2
|
import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "../http-n2v6DPxu.js";
|
|
3
3
|
import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "../owner-BSzr5-I8.js";
|
|
4
|
-
import { C as createSignature, D as verifyJsonLd, E as signJsonLd, O as verifySignature, S as attachSignature, T as hasSignatureLike, _ as verifyProof, a as CreateProofOptions, b as VerifyJsonLdOptions, c as VerifyPortableObjectProofFailureReason, d as VerifyProofOptions, f as createProof, g as verifyPortableObjectProof, h as verifyObject, i as verifyPortableObject, l as VerifyPortableObjectProofOptions, m as signObject, n as VerifyPortableObjectOptions, o as SignObjectOptions, p as hasProofLike, r as VerifyPortableObjectResult, s as VerifyObjectOptions, t as VerifyPortableObjectFailureReason, u as VerifyPortableObjectProofResult, v as CreateSignatureOptions, w as detachSignature, x as VerifySignatureOptions, y as SignJsonLdOptions } from "../mod-
|
|
4
|
+
import { C as createSignature, D as verifyJsonLd, E as signJsonLd, O as verifySignature, S as attachSignature, T as hasSignatureLike, _ as verifyProof, a as CreateProofOptions, b as VerifyJsonLdOptions, c as VerifyPortableObjectProofFailureReason, d as VerifyProofOptions, f as createProof, g as verifyPortableObjectProof, h as verifyObject, i as verifyPortableObject, l as VerifyPortableObjectProofOptions, m as signObject, n as VerifyPortableObjectOptions, o as SignObjectOptions, p as hasProofLike, r as VerifyPortableObjectResult, s as VerifyObjectOptions, t as VerifyPortableObjectFailureReason, u as VerifyPortableObjectProofResult, v as CreateSignatureOptions, w as detachSignature, x as VerifySignatureOptions, y as SignJsonLdOptions } from "../mod-Coacostr.js";
|
|
5
5
|
export { AcceptSignatureMember, AcceptSignatureParameters, CreateProofOptions, CreateSignatureOptions, DoesActorOwnKeyOptions, FetchKeyDetailedResult, FetchKeyErrorResult, FetchKeyOptions, FetchKeyResult, FulfillAcceptSignatureResult, GetKeyOwnerOptions, HttpMessageSignaturesSpec, HttpMessageSignaturesSpecDeterminer, KeyCache, Rfc9421SignRequestOptions, SignJsonLdOptions, SignObjectOptions, SignRequestOptions, VerifyJsonLdOptions, VerifyObjectOptions, VerifyPortableObjectFailureReason, VerifyPortableObjectOptions, VerifyPortableObjectProofFailureReason, VerifyPortableObjectProofOptions, VerifyPortableObjectProofResult, VerifyPortableObjectResult, VerifyProofOptions, VerifyRequestDetailedResult, VerifyRequestFailureReason, VerifyRequestOptions, VerifySignatureOptions, attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, hasProofLike, hasSignatureLike, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyPortableObject, verifyPortableObjectProof, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
|
package/dist/sig/mod.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import {
|
|
4
|
-
import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-
|
|
5
|
-
import { t as verifyPortableObject } from "../sig-
|
|
3
|
+
import { C as detachSignature, E as hasSignatureLike, I as fetchKey, L as fetchKeyDetailed, M as verifySignature, P as exportJwk, R as generateCryptoKeyPair, S as createSignature, a as verifyRequestDetailed, b as attachSignature, c as createProof, ct as parseAcceptSignature, f as verifyObject, g as verifyProof, i as verifyRequest, j as verifyJsonLd, k as signJsonLd, l as hasProofLike, lt as validateAcceptSignature, ot as formatAcceptSignature, p as verifyPortableObjectProof, r as signRequest, st as fulfillAcceptSignature, u as signObject, z as importJwk } from "../http-DyT7DP1Y.js";
|
|
4
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-DAGSC5gX.js";
|
|
5
|
+
import { t as verifyPortableObject } from "../sig-B5Ell7pO.js";
|
|
6
6
|
export { attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, hasProofLike, hasSignatureLike, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyPortableObject, verifyPortableObjectProof, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
|
package/dist/sig/owner.test.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
|
|
|
6
6
|
import "../std__assert-DvMDRPes.mjs";
|
|
7
7
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
8
8
|
import { o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
|
|
9
|
-
import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-
|
|
9
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-Cgx2Dc7I.mjs";
|
|
10
10
|
import { Create, CryptographicKey, lookupObject } from "@fedify/vocab";
|
|
11
11
|
import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
12
12
|
//#region src/sig/owner.test.ts
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "../deno-
|
|
5
|
-
import {
|
|
4
|
+
import { n as version, t as name } from "../deno-8t8k_6Yv.mjs";
|
|
5
|
+
import { l as verifyPortableObjectProofWithRoot, s as verifyPortableObjectProof } from "../proof-DVXC6nYz.mjs";
|
|
6
6
|
import { n as ed25519PrivateKey, r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
|
|
7
7
|
import { getLogger } from "@logtape/logtape";
|
|
8
8
|
import { Collection, CollectionPage, Note, Object as Object$1, OrderedCollection, Person, isActor, traverseCollection } from "@fedify/vocab";
|
|
9
9
|
import { trace } from "@opentelemetry/api";
|
|
10
10
|
import { test } from "@fedify/fixture";
|
|
11
11
|
import { FetchError, canonicalizePortableUri, encodeMultibase, exportDidKey, formatIri, fromCompatibleEf61Id, getDocumentLoader, getFe34Origin, parseIri, preloadedContexts } from "@fedify/vocab-runtime";
|
|
12
|
+
import { dereferencePortableIri, getPortableGatewayCandidates } from "@fedify/vocab-runtime/internal/portable-dereference";
|
|
12
13
|
import serialize from "json-canon";
|
|
13
14
|
import { deepStrictEqual, ok, strictEqual } from "node:assert/strict";
|
|
14
|
-
import { dereferencePortableIri, getPortableGatewayCandidates } from "@fedify/vocab-runtime/internal/portable-dereference";
|
|
15
15
|
//#region src/sig/portable-collection.ts
|
|
16
16
|
const logger = getLogger([
|
|
17
17
|
"fedify",
|
|
@@ -54,6 +54,8 @@ function getContextState(context) {
|
|
|
54
54
|
}
|
|
55
55
|
function canonicalize(id) {
|
|
56
56
|
try {
|
|
57
|
+
const portable = fromCompatibleEf61Id(id);
|
|
58
|
+
if (portable != null) return canonicalizePortableUri(formatIri(portable));
|
|
57
59
|
return canonicalizePortableUri(typeof id === "string" ? id : formatIri(id));
|
|
58
60
|
} catch (error) {
|
|
59
61
|
if (error instanceof TypeError) return null;
|
|
@@ -234,7 +236,20 @@ async function fetchOwner(candidate, options) {
|
|
|
234
236
|
const contextLoader = options.contextLoader ?? getDocumentLoader();
|
|
235
237
|
const tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
|
|
236
238
|
const tracer = tracerProvider.getTracer(name, version);
|
|
237
|
-
|
|
239
|
+
let inferredGateways;
|
|
240
|
+
try {
|
|
241
|
+
const portable = fromCompatibleEf61Id(candidate);
|
|
242
|
+
if (portable != null) {
|
|
243
|
+
inferredGateways = [new URL(candidate.origin)];
|
|
244
|
+
candidate = portable;
|
|
245
|
+
}
|
|
246
|
+
} catch (error) {
|
|
247
|
+
if (!(error instanceof TypeError)) throw error;
|
|
248
|
+
logger.debug("The owner {owner} of a portable collection is a malformed compatible identifier.", { owner: candidate.href });
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
const gateways = options.gateways ?? (inferredGateways != null || getPortableGatewayCandidates(candidate).length > 0 ? void 0 : options.gatewayHints);
|
|
252
|
+
if (options.gateways != null) inferredGateways = void 0;
|
|
238
253
|
const span = tracer.startSpan("activitypub.lookup_object");
|
|
239
254
|
try {
|
|
240
255
|
const object = await dereferencePortableIri(candidate, {
|
|
@@ -242,6 +257,7 @@ async function fetchOwner(candidate, options) {
|
|
|
242
257
|
contextLoader,
|
|
243
258
|
tracerProvider,
|
|
244
259
|
gateways,
|
|
260
|
+
...inferredGateways == null ? {} : { inferredGateways },
|
|
245
261
|
verifyPortableObject: (document, verifierOptions) => verifyPortableObjectProof(document, {
|
|
246
262
|
...options,
|
|
247
263
|
...verifierOptions
|
|
@@ -569,13 +585,61 @@ test("verifyPortableObject() uses the actual fetch source", async () => {
|
|
|
569
585
|
referrer,
|
|
570
586
|
documentUrl: new URL(`https://user@gw1.example/.well-known/apgateway/${did}/actor/outbox`)
|
|
571
587
|
}), "unknownCollectionSource");
|
|
572
|
-
|
|
588
|
+
const result = await verify(outbox({ id: gatewayUrl(evil, outboxId) }), {
|
|
589
|
+
documentLoader,
|
|
590
|
+
gateways,
|
|
591
|
+
referrer,
|
|
592
|
+
documentUrl: new URL(gatewayUrl(gw1, outboxId))
|
|
593
|
+
});
|
|
594
|
+
ok(result.verified);
|
|
595
|
+
strictEqual(result.method, "gateway");
|
|
596
|
+
if (result.method !== "gateway") return;
|
|
597
|
+
deepStrictEqual(result.gateway, new URL(gw1));
|
|
598
|
+
assertFailure(await verify(outbox({ id: `${evil}/outbox` }), {
|
|
573
599
|
documentLoader,
|
|
574
600
|
gateways,
|
|
575
601
|
referrer,
|
|
576
602
|
documentUrl: new URL(gatewayUrl(gw1, outboxId))
|
|
577
603
|
}), "notPortableObject");
|
|
578
604
|
});
|
|
605
|
+
test("verifyPortableObject() trusts unsecured collections of compatible-ID actors", async () => {
|
|
606
|
+
const compatibleActorId = gatewayUrl(gw1, actorId);
|
|
607
|
+
const compatibleOutboxId = gatewayUrl(gw1, outboxId);
|
|
608
|
+
const signed = await sign(actor({
|
|
609
|
+
id: compatibleActorId,
|
|
610
|
+
inbox: gatewayUrl(gw1, `ap://${did}/actor/inbox`),
|
|
611
|
+
outbox: compatibleOutboxId,
|
|
612
|
+
followers: gatewayUrl(gw1, `ap://${did}/actor/followers`)
|
|
613
|
+
}));
|
|
614
|
+
const collection = outbox({
|
|
615
|
+
id: compatibleOutboxId,
|
|
616
|
+
attributedTo: compatibleActorId
|
|
617
|
+
});
|
|
618
|
+
const documentLoader = createLoader({ [compatibleActorId]: signed });
|
|
619
|
+
const result = await verify(collection, {
|
|
620
|
+
documentLoader,
|
|
621
|
+
documentUrl: new URL(compatibleOutboxId)
|
|
622
|
+
});
|
|
623
|
+
ok(result.verified, JSON.stringify(result));
|
|
624
|
+
strictEqual(result.method, "gateway");
|
|
625
|
+
if (result.method !== "gateway") return;
|
|
626
|
+
deepStrictEqual(result.gateway, new URL(gw1));
|
|
627
|
+
deepStrictEqual(documentLoader.fetched, [compatibleActorId]);
|
|
628
|
+
const noGateways = createLoader({ [compatibleActorId]: signed });
|
|
629
|
+
assertFailure(await verify(collection, {
|
|
630
|
+
documentLoader: noGateways,
|
|
631
|
+
documentUrl: new URL(compatibleOutboxId),
|
|
632
|
+
gateways: []
|
|
633
|
+
}), "collectionOwnerUnavailable");
|
|
634
|
+
deepStrictEqual(noGateways.fetched.filter((url) => url === compatibleActorId), []);
|
|
635
|
+
assertFailure(await verify(collection, {
|
|
636
|
+
documentLoader: createLoader({ [compatibleActorId]: actor({
|
|
637
|
+
id: compatibleActorId,
|
|
638
|
+
outbox: compatibleOutboxId
|
|
639
|
+
}) }),
|
|
640
|
+
documentUrl: new URL(compatibleOutboxId)
|
|
641
|
+
}), "collectionOwnerUnavailable");
|
|
642
|
+
});
|
|
579
643
|
test("verifyPortableObject() requires an unambiguous owner", async () => {
|
|
580
644
|
const base = {
|
|
581
645
|
documentLoader: createLoader({ [gatewayUrl(gw1, actorId)]: signedActor }),
|