@fedify/fedify 2.2.0-pr.709.20 → 2.2.0-pr.710.24
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-6NAlCn-K.mjs → builder-CKJTVRhn.mjs} +3 -3
- package/dist/compat/public-audience.test.d.mts +2 -0
- package/dist/compat/public-audience.test.mjs +162 -0
- package/dist/compat/transformers.test.mjs +2 -2
- package/dist/{deno-CWoVKoBl.mjs → deno-cvysscWX.mjs} +1 -1
- package/dist/{docloader-z8BYCZvY.mjs → docloader-BuEazLeK.mjs} +2 -2
- package/dist/federation/builder.test.mjs +2 -2
- package/dist/federation/collection.test.mjs +1 -1
- package/dist/federation/handler.test.mjs +4 -4
- package/dist/federation/idempotency.test.mjs +3 -3
- package/dist/federation/inbox.test.mjs +1 -1
- package/dist/federation/keycache.test.mjs +2 -2
- package/dist/federation/kv.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +17 -7
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.js +1 -1
- package/dist/federation/negotiation.test.mjs +1 -1
- package/dist/federation/retry.test.mjs +1 -1
- package/dist/federation/send.test.mjs +3 -3
- package/dist/federation/webfinger.test.mjs +2 -2
- package/dist/{http-cyerYP3k.js → http-B0Tu7TW-.js} +1 -1
- package/dist/{http-B0CGWLm2.cjs → http-BJ7XtRRp.cjs} +1 -1
- package/dist/{http-Cl7YijGX.mjs → http-Dy22pK-t.mjs} +2 -2
- package/dist/{key-DgOxeSHC.mjs → key-DXBoO6CC.mjs} +1 -1
- package/dist/{kv-cache-BhCk5dX_.js → kv-cache-Bxbq9e39.js} +1 -1
- package/dist/{kv-cache-BzAyTibN.cjs → kv-cache-x4KOTSSC.cjs} +1 -1
- package/dist/{ld-BqJAwT8x.mjs → ld-BW_1mHgq.mjs} +2 -2
- package/dist/{middleware-DeRKEGtq.mjs → middleware-BdpMBegR.mjs} +1 -1
- package/dist/{middleware-Dlfri269.mjs → middleware-Bu0zxHoX.mjs} +17 -15
- package/dist/{middleware-CmlDuNnT.js → middleware-COjNuA6A.js} +4 -3
- package/dist/{middleware-CPDkGhht.cjs → middleware-CRFf7Wb6.cjs} +1 -1
- package/dist/{middleware-Dr7gPlVB.cjs → middleware-QpqLtpW9.cjs} +5 -4
- package/dist/mod.cjs +4 -4
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/client.test.mjs +1 -1
- package/dist/nodeinfo/handler.test.mjs +2 -2
- package/dist/nodeinfo/types.test.mjs +1 -1
- package/dist/otel/exporter.test.mjs +1 -1
- package/dist/{owner-CBLQ-vDw.mjs → owner-CBdNJRwZ.mjs} +2 -2
- package/dist/{proof-DZpF7E4g.mjs → proof-7MA0dp2c.mjs} +36 -31
- package/dist/{proof-CchoRjI8.cjs → proof-B__J6A1_.cjs} +221 -38
- package/dist/{proof-sJxm6hBB.js → proof-Bfx0NdYz.js} +218 -41
- package/dist/public-audience-5WWE-JTr.mjs +181 -0
- package/dist/{send-Ckd6J9RF.mjs → send-9BckNAN-.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 +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/proof.test.mjs +60 -2
- package/dist/utils/docloader.test.mjs +2 -2
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +16 -7
- package/skills/fedify/SKILL.md +462 -0
- /package/dist/{activity-listener-Ck3JZ_hR.mjs → activity-listener-CFzUqoCS.mjs} +0 -0
- /package/dist/{client-DEpOVgY1.mjs → client-DVu6Fmom.mjs} +0 -0
- /package/dist/{collection-BD6-SZ6O.mjs → collection-BQRKGS7L.mjs} +0 -0
- /package/dist/{keycache-CCSwkQcY.mjs → keycache-C2t1kvP5.mjs} +0 -0
- /package/dist/{kv-tL2TOE9X.mjs → kv-C-TG81Sv.mjs} +0 -0
- /package/dist/{negotiation-DnsfFF8I.mjs → negotiation-xb0QR3u_.mjs} +0 -0
- /package/dist/{retry-B_E3V_Dx.mjs → retry-CJL0poaU.mjs} +0 -0
- /package/dist/{types-DCP0WLdt.mjs → types-CGUnLkU3.mjs} +0 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
|
-
import { _ as version, d as validateCryptoKey, g as name, s as fetchKey } from "./http-
|
|
3
|
+
import { _ as version, d as validateCryptoKey, g as name, s as fetchKey } from "./http-B0Tu7TW-.js";
|
|
4
4
|
import { getLogger } from "@logtape/logtape";
|
|
5
|
-
import { Activity, CryptographicKey, DataIntegrityProof, Multikey, Object as Object$1, getTypeId, isActor } from "@fedify/vocab";
|
|
5
|
+
import { Activity, CryptographicKey, DataIntegrityProof, Multikey, Object as Object$1, PUBLIC_COLLECTION, getTypeId, isActor } from "@fedify/vocab";
|
|
6
6
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
7
7
|
import { encodeHex } from "byte-encodings/hex";
|
|
8
|
-
import { getDocumentLoader } from "@fedify/vocab-runtime";
|
|
8
|
+
import { getDocumentLoader, preloadedContexts } from "@fedify/vocab-runtime";
|
|
9
9
|
import { decodeBase64, encodeBase64 } from "byte-encodings/base64";
|
|
10
10
|
import jsonld from "@fedify/vocab-runtime/jsonld";
|
|
11
11
|
import serialize from "json-canon";
|
|
12
12
|
//#region src/sig/ld.ts
|
|
13
|
-
const logger$
|
|
13
|
+
const logger$2 = getLogger([
|
|
14
14
|
"fedify",
|
|
15
15
|
"sig",
|
|
16
16
|
"ld"
|
|
@@ -158,7 +158,7 @@ async function verifySignature(jsonLd, options = {}) {
|
|
|
158
158
|
try {
|
|
159
159
|
signature = decodeBase64(sig.signatureValue);
|
|
160
160
|
} catch (error) {
|
|
161
|
-
logger$
|
|
161
|
+
logger$2.debug("Failed to verify; invalid base64 signatureValue: {signatureValue}", {
|
|
162
162
|
...sig,
|
|
163
163
|
error
|
|
164
164
|
});
|
|
@@ -177,7 +177,7 @@ async function verifySignature(jsonLd, options = {}) {
|
|
|
177
177
|
try {
|
|
178
178
|
sigOptsHash = await hashJsonLd(sigOpts, options.contextLoader);
|
|
179
179
|
} catch (error) {
|
|
180
|
-
logger$
|
|
180
|
+
logger$2.warn("Failed to verify; failed to hash the signature options: {signatureOptions}\n{error}", {
|
|
181
181
|
signatureOptions: sigOpts,
|
|
182
182
|
error
|
|
183
183
|
});
|
|
@@ -189,7 +189,7 @@ async function verifySignature(jsonLd, options = {}) {
|
|
|
189
189
|
try {
|
|
190
190
|
docHash = await hashJsonLd(document, options.contextLoader);
|
|
191
191
|
} catch (error) {
|
|
192
|
-
logger$
|
|
192
|
+
logger$2.warn("Failed to verify; failed to hash the document: {document}\n{error}", {
|
|
193
193
|
document,
|
|
194
194
|
error
|
|
195
195
|
});
|
|
@@ -200,7 +200,7 @@ async function verifySignature(jsonLd, options = {}) {
|
|
|
200
200
|
const messageBytes = encoder.encode(message);
|
|
201
201
|
if (await crypto.subtle.verify("RSASSA-PKCS1-v1_5", key.publicKey, signature.slice(), messageBytes)) return key;
|
|
202
202
|
if (cached) {
|
|
203
|
-
logger$
|
|
203
|
+
logger$2.debug("Failed to verify with the cached key {keyId}; signature {signatureValue} is invalid. Retrying with the freshly fetched key...", {
|
|
204
204
|
keyId: sig.creator,
|
|
205
205
|
...sig
|
|
206
206
|
});
|
|
@@ -214,7 +214,7 @@ async function verifySignature(jsonLd, options = {}) {
|
|
|
214
214
|
if (key == null) return null;
|
|
215
215
|
return await crypto.subtle.verify("RSASSA-PKCS1-v1_5", key.publicKey, signature.slice(), messageBytes) ? key : null;
|
|
216
216
|
}
|
|
217
|
-
logger$
|
|
217
|
+
logger$2.debug("Failed to verify with the fetched key {keyId}; signature {signatureValue} is invalid. Check if the key is correct or if the signed message is correct. The message to sign is:\n{message}", {
|
|
218
218
|
keyId: sig.creator,
|
|
219
219
|
...sig,
|
|
220
220
|
message
|
|
@@ -246,12 +246,12 @@ async function verifyJsonLd(jsonLd, options = {}) {
|
|
|
246
246
|
const key = await verifySignature(jsonLd, options);
|
|
247
247
|
if (key == null) return false;
|
|
248
248
|
if (key.ownerId == null) {
|
|
249
|
-
logger$
|
|
249
|
+
logger$2.debug("Key {keyId} has no owner.", { keyId: key.id?.href });
|
|
250
250
|
return false;
|
|
251
251
|
}
|
|
252
252
|
attributions.delete(key.ownerId.href);
|
|
253
253
|
if (attributions.size > 0) {
|
|
254
|
-
logger$
|
|
254
|
+
logger$2.debug("Some attributions are not authenticated by the Linked Data Signatures: {attributions}.", { attributions: [...attributions] });
|
|
255
255
|
return false;
|
|
256
256
|
}
|
|
257
257
|
return true;
|
|
@@ -386,6 +386,179 @@ async function getKeyOwner(keyId, options) {
|
|
|
386
386
|
return null;
|
|
387
387
|
}
|
|
388
388
|
//#endregion
|
|
389
|
+
//#region src/compat/public-audience.ts
|
|
390
|
+
const logger$1 = getLogger([
|
|
391
|
+
"fedify",
|
|
392
|
+
"compat",
|
|
393
|
+
"public-audience"
|
|
394
|
+
]);
|
|
395
|
+
const PUBLIC_ADDRESSING_FIELDS = new Set([
|
|
396
|
+
"to",
|
|
397
|
+
"cc",
|
|
398
|
+
"bto",
|
|
399
|
+
"bcc",
|
|
400
|
+
"audience"
|
|
401
|
+
]);
|
|
402
|
+
const preloadedOnlyDocumentLoader = (url) => {
|
|
403
|
+
if (url in preloadedContexts) return Promise.resolve({
|
|
404
|
+
contextUrl: null,
|
|
405
|
+
documentUrl: url,
|
|
406
|
+
document: preloadedContexts[url]
|
|
407
|
+
});
|
|
408
|
+
return Promise.reject(/* @__PURE__ */ new Error("Refusing to fetch a non-preloaded JSON-LD context: " + url));
|
|
409
|
+
};
|
|
410
|
+
const AS_CONTEXT_URL = "https://www.w3.org/ns/activitystreams";
|
|
411
|
+
const MAX_TRAVERSAL_DEPTH = 64;
|
|
412
|
+
const KNOWN_SAFE_CONTEXT_URLS = new Set(Object.keys(preloadedContexts));
|
|
413
|
+
function hasPublicCurieInAddressing(value, parentKey, depth = 0) {
|
|
414
|
+
if (typeof value === "string") return parentKey != null && PUBLIC_ADDRESSING_FIELDS.has(parentKey) && (value === "as:Public" || value === "Public");
|
|
415
|
+
if (depth >= MAX_TRAVERSAL_DEPTH) return false;
|
|
416
|
+
if (Array.isArray(value)) return value.some((item) => hasPublicCurieInAddressing(item, parentKey, depth + 1));
|
|
417
|
+
if (typeof value !== "object" || value == null) return false;
|
|
418
|
+
const record = value;
|
|
419
|
+
for (const key of Object.keys(record)) {
|
|
420
|
+
if (key === "@context") continue;
|
|
421
|
+
if (hasPublicCurieInAddressing(record[key], key, depth + 1)) return true;
|
|
422
|
+
}
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
function rewritePublicAudience(value, parentKey, depth = 0) {
|
|
426
|
+
if (typeof value === "string" && parentKey != null && PUBLIC_ADDRESSING_FIELDS.has(parentKey) && (value === "as:Public" || value === "Public")) return PUBLIC_COLLECTION.href;
|
|
427
|
+
if (depth >= MAX_TRAVERSAL_DEPTH) return value;
|
|
428
|
+
if (Array.isArray(value)) {
|
|
429
|
+
let changed = false;
|
|
430
|
+
const mapped = value.map((item) => {
|
|
431
|
+
const rewritten = rewritePublicAudience(item, parentKey, depth + 1);
|
|
432
|
+
if (rewritten !== item) changed = true;
|
|
433
|
+
return rewritten;
|
|
434
|
+
});
|
|
435
|
+
return changed ? mapped : value;
|
|
436
|
+
}
|
|
437
|
+
if (typeof value !== "object" || value == null) return value;
|
|
438
|
+
const record = value;
|
|
439
|
+
let changed = false;
|
|
440
|
+
const normalized = {};
|
|
441
|
+
for (const key of Object.keys(record)) {
|
|
442
|
+
const rewritten = key === "@context" ? record[key] : rewritePublicAudience(record[key], key, depth + 1);
|
|
443
|
+
if (rewritten !== record[key]) changed = true;
|
|
444
|
+
normalized[key] = rewritten;
|
|
445
|
+
}
|
|
446
|
+
return changed ? normalized : value;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Reports whether `value` carries an `@context` property anywhere inside
|
|
450
|
+
* its subtree (not counting the value itself). A nested `@context` can
|
|
451
|
+
* introduce a local term-definition scope that redefines `as:` or `Public`
|
|
452
|
+
* even when the top-level `@context` is safe, so the fast path must defer
|
|
453
|
+
* to the URDNA2015 equivalence check whenever one is present.
|
|
454
|
+
*/
|
|
455
|
+
function hasNestedContext(value, depth = 0) {
|
|
456
|
+
if (depth >= MAX_TRAVERSAL_DEPTH) return true;
|
|
457
|
+
if (Array.isArray(value)) return value.some((item) => hasNestedContext(item, depth + 1));
|
|
458
|
+
if (typeof value !== "object" || value == null) return false;
|
|
459
|
+
const record = value;
|
|
460
|
+
for (const key of Object.keys(record)) {
|
|
461
|
+
if (key === "@context") return true;
|
|
462
|
+
if (hasNestedContext(record[key], depth + 1)) return true;
|
|
463
|
+
}
|
|
464
|
+
return false;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Checks whether the `@context` of a JSON-LD document is guaranteed not
|
|
468
|
+
* to redefine the `as:` prefix or the bare `Public` term. Only documents
|
|
469
|
+
* whose `@context` is a string, or an array of strings, drawn from Fedify's
|
|
470
|
+
* preloaded context set AND including the ActivityStreams URL qualify,
|
|
471
|
+
* AND no nested subtree carries its own `@context` that might redefine
|
|
472
|
+
* those terms within a local scope. When all of that holds the rewrite
|
|
473
|
+
* is provably semantics-preserving and the URDNA2015 equivalence check
|
|
474
|
+
* can be skipped. Any other shape (unknown external URLs, inline
|
|
475
|
+
* objects at the top level, nested `@context` blocks) is treated as
|
|
476
|
+
* potentially unsafe.
|
|
477
|
+
*/
|
|
478
|
+
function hasKnownSafeContext(jsonLd) {
|
|
479
|
+
if (typeof jsonLd !== "object" || jsonLd == null) return false;
|
|
480
|
+
const record = jsonLd;
|
|
481
|
+
if (!Object.hasOwn(record, "@context")) return false;
|
|
482
|
+
const ctx = record["@context"];
|
|
483
|
+
const entries = typeof ctx === "string" ? [ctx] : Array.isArray(ctx) ? ctx : null;
|
|
484
|
+
if (entries == null || entries.length === 0) return false;
|
|
485
|
+
let hasAs = false;
|
|
486
|
+
for (const entry of entries) {
|
|
487
|
+
if (typeof entry !== "string") return false;
|
|
488
|
+
if (!KNOWN_SAFE_CONTEXT_URLS.has(entry)) return false;
|
|
489
|
+
if (entry === AS_CONTEXT_URL) hasAs = true;
|
|
490
|
+
}
|
|
491
|
+
if (!hasAs) return false;
|
|
492
|
+
for (const key of Object.keys(record)) {
|
|
493
|
+
if (key === "@context") continue;
|
|
494
|
+
if (hasNestedContext(record[key])) return false;
|
|
495
|
+
}
|
|
496
|
+
return true;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Rewrites the compact `as:Public` / `Public` CURIE appearing in activity
|
|
500
|
+
* addressing fields (`to`, `cc`, `bto`, `bcc`, `audience`) to the fully
|
|
501
|
+
* expanded `https://www.w3.org/ns/activitystreams#Public` URI.
|
|
502
|
+
*
|
|
503
|
+
* Several ActivityPub implementations, Lemmy among them, match these
|
|
504
|
+
* fields as plain URLs without running JSON-LD expansion, and silently
|
|
505
|
+
* drop activities whose public addressing appears in CURIE form. This
|
|
506
|
+
* helper works around that gap.
|
|
507
|
+
*
|
|
508
|
+
* For documents whose `@context` is drawn entirely from Fedify's
|
|
509
|
+
* preloaded context set and includes the ActivityStreams URL, the
|
|
510
|
+
* rewrite is applied directly: the content of every preloaded non-AS
|
|
511
|
+
* context is known not to redefine the `as:` prefix or the bare `Public`
|
|
512
|
+
* term, so the semantics are preserved by construction. Any other
|
|
513
|
+
* shape (an inline object, an unknown external URL, and so on) is
|
|
514
|
+
* treated as potentially unsafe and gated on a JSON-LD equivalence
|
|
515
|
+
* check; both forms are canonicalized with URDNA2015 and the resulting
|
|
516
|
+
* N-Quads are compared. When they differ, the original document is
|
|
517
|
+
* returned unchanged. Canonicalization failures also fall back to the
|
|
518
|
+
* original document.
|
|
519
|
+
*
|
|
520
|
+
* When no `contextLoader` is supplied the helper falls back to an
|
|
521
|
+
* internal loader that resolves only the URLs in Fedify's
|
|
522
|
+
* preloaded-contexts set and rejects every other URL without issuing a
|
|
523
|
+
* network request. That behaviour is deliberately narrower than
|
|
524
|
+
* `@fedify/vocab-runtime`'s `getDocumentLoader()`, which after its
|
|
525
|
+
* `validatePublicUrl` check will happily fetch non-preloaded URLs: the
|
|
526
|
+
* helper is reached from verification paths (`verifyProof()` /
|
|
527
|
+
* `verifyObject()`) that operate on inbound, potentially adversarial
|
|
528
|
+
* JSON-LD, and a default loader that fetches attacker-supplied
|
|
529
|
+
* `@context` URLs on the caller's behalf would be an SSRF vector.
|
|
530
|
+
* Canonicalization failures against the restricted loader fall back to
|
|
531
|
+
* the original document, same as any other canonicalization error.
|
|
532
|
+
* Callers that genuinely need the remote-fetch loader (for example
|
|
533
|
+
* applications that sign local JSON-LD against a custom vocabulary)
|
|
534
|
+
* should pass a `contextLoader` explicitly.
|
|
535
|
+
*
|
|
536
|
+
* Must be called before any signing step that canonicalizes the
|
|
537
|
+
* compact form byte-for-byte (for example, Object Integrity Proofs
|
|
538
|
+
* using the `eddsa-jcs-2022` cryptosuite), so the signed payload
|
|
539
|
+
* matches what is sent on the wire.
|
|
540
|
+
*/
|
|
541
|
+
async function normalizePublicAudience(jsonLd, contextLoader) {
|
|
542
|
+
if (!hasPublicCurieInAddressing(jsonLd)) return jsonLd;
|
|
543
|
+
const normalized = rewritePublicAudience(jsonLd);
|
|
544
|
+
if (hasKnownSafeContext(jsonLd)) return normalized;
|
|
545
|
+
const loader = contextLoader ?? preloadedOnlyDocumentLoader;
|
|
546
|
+
try {
|
|
547
|
+
const [before, after] = await Promise.all([jsonld.canonize(jsonLd, {
|
|
548
|
+
format: "application/n-quads",
|
|
549
|
+
documentLoader: loader
|
|
550
|
+
}), jsonld.canonize(normalized, {
|
|
551
|
+
format: "application/n-quads",
|
|
552
|
+
documentLoader: loader
|
|
553
|
+
})]);
|
|
554
|
+
if (before === after) return normalized;
|
|
555
|
+
logger$1.warn("Expanding the public audience CURIE to its full URI would change the canonical form of the activity; sending the activity as is. This usually means the active JSON-LD context redefines the `as:` prefix or the bare `Public` term.");
|
|
556
|
+
} catch (error) {
|
|
557
|
+
logger$1.debug("Failed to verify public audience normalization equivalence via JSON-LD canonicalization; sending the activity as is.\n{error}", { error });
|
|
558
|
+
}
|
|
559
|
+
return jsonLd;
|
|
560
|
+
}
|
|
561
|
+
//#endregion
|
|
389
562
|
//#region src/sig/proof.ts
|
|
390
563
|
const logger = getLogger([
|
|
391
564
|
"fedify",
|
|
@@ -434,11 +607,12 @@ function hasProofLike(jsonLd) {
|
|
|
434
607
|
async function createProof(object, privateKey, keyId, { contextLoader, context, created } = {}) {
|
|
435
608
|
validateCryptoKey(privateKey, "private");
|
|
436
609
|
if (privateKey.algorithm.name !== "Ed25519") throw new TypeError("Unsupported algorithm: " + privateKey.algorithm.name);
|
|
437
|
-
|
|
610
|
+
let compactMsg = await object.clone({ proofs: [] }).toJsonLd({
|
|
438
611
|
format: "compact",
|
|
439
612
|
contextLoader,
|
|
440
613
|
context
|
|
441
614
|
});
|
|
615
|
+
compactMsg = await normalizePublicAudience(compactMsg, contextLoader);
|
|
442
616
|
const msgCanon = serialize(compactMsg);
|
|
443
617
|
const encoder = new TextEncoder();
|
|
444
618
|
const msgBytes = encoder.encode(msgCanon);
|
|
@@ -533,27 +707,25 @@ async function verifyProof(jsonLd, proof, options = {}) {
|
|
|
533
707
|
});
|
|
534
708
|
}
|
|
535
709
|
async function verifyProofInternal(jsonLd, proof, options) {
|
|
536
|
-
if (typeof jsonLd !== "object" || proof.cryptosuite !== "eddsa-jcs-2022" || proof.verificationMethodId == null || proof.proofPurpose !== "assertionMethod" || proof.proofValue == null || proof.created == null) return null;
|
|
710
|
+
if (typeof jsonLd !== "object" || jsonLd == null || Array.isArray(jsonLd) || proof.cryptosuite !== "eddsa-jcs-2022" || proof.verificationMethodId == null || proof.proofPurpose !== "assertionMethod" || proof.proofValue == null || proof.created == null) return null;
|
|
537
711
|
const publicKeyPromise = fetchKey(proof.verificationMethodId, Multikey, options);
|
|
538
|
-
const
|
|
712
|
+
const proofConfig = {
|
|
539
713
|
"@context": jsonLd["@context"],
|
|
540
714
|
type: "DataIntegrityProof",
|
|
541
715
|
cryptosuite: proof.cryptosuite,
|
|
542
716
|
verificationMethod: proof.verificationMethodId.href,
|
|
543
717
|
proofPurpose: proof.proofPurpose,
|
|
544
718
|
created: proof.created.toString()
|
|
545
|
-
}
|
|
719
|
+
};
|
|
546
720
|
const encoder = new TextEncoder();
|
|
547
|
-
const proofBytes = encoder.encode(
|
|
721
|
+
const proofBytes = encoder.encode(serialize(proofConfig));
|
|
548
722
|
const proofDigest = await crypto.subtle.digest("SHA-256", proofBytes);
|
|
549
723
|
const msg = { ...jsonLd };
|
|
550
724
|
if ("proof" in msg) delete msg.proof;
|
|
551
|
-
|
|
552
|
-
const
|
|
553
|
-
const
|
|
554
|
-
|
|
555
|
-
digest.set(new Uint8Array(proofDigest), 0);
|
|
556
|
-
digest.set(new Uint8Array(msgDigest), proofDigest.byteLength);
|
|
725
|
+
if ("https://w3id.org/security#proof" in msg) delete msg["https://w3id.org/security#proof"];
|
|
726
|
+
const candidates = [msg];
|
|
727
|
+
const normalized = await normalizePublicAudience(msg, options.contextLoader);
|
|
728
|
+
if (normalized !== msg) candidates.push(normalized);
|
|
557
729
|
let fetchedKey;
|
|
558
730
|
try {
|
|
559
731
|
fetchedKey = await publicKeyPromise;
|
|
@@ -582,7 +754,7 @@ async function verifyProofInternal(jsonLd, proof, options) {
|
|
|
582
754
|
return await verifyProof(jsonLd, proof, {
|
|
583
755
|
...options,
|
|
584
756
|
keyCache: {
|
|
585
|
-
get: () => Promise.resolve(
|
|
757
|
+
get: () => Promise.resolve(void 0),
|
|
586
758
|
set: async (keyId, key) => await options.keyCache?.set(keyId, key)
|
|
587
759
|
}
|
|
588
760
|
});
|
|
@@ -593,27 +765,32 @@ async function verifyProofInternal(jsonLd, proof, options) {
|
|
|
593
765
|
});
|
|
594
766
|
return null;
|
|
595
767
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
set: async (keyId, key) => await options.keyCache?.set(keyId, key)
|
|
607
|
-
}
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
logger.debug("Failed to verify the proof with the fetched key {keyId}:\n{proof}", {
|
|
768
|
+
const digest = new Uint8Array(proofDigest.byteLength + 32);
|
|
769
|
+
digest.set(new Uint8Array(proofDigest), 0);
|
|
770
|
+
for (const candidate of candidates) {
|
|
771
|
+
const msgBytes = encoder.encode(serialize(candidate));
|
|
772
|
+
const msgDigest = await crypto.subtle.digest("SHA-256", msgBytes);
|
|
773
|
+
digest.set(new Uint8Array(msgDigest), proofDigest.byteLength);
|
|
774
|
+
if (await crypto.subtle.verify("Ed25519", publicKey.publicKey, proof.proofValue.slice(), digest)) return publicKey;
|
|
775
|
+
}
|
|
776
|
+
if (fetchedKey.cached) {
|
|
777
|
+
logger.debug("Failed to verify the proof with the cached key {keyId}; retrying with the freshly fetched key...", {
|
|
611
778
|
keyId: proof.verificationMethodId.href,
|
|
612
779
|
proof
|
|
613
780
|
});
|
|
614
|
-
return
|
|
781
|
+
return await verifyProof(jsonLd, proof, {
|
|
782
|
+
...options,
|
|
783
|
+
keyCache: {
|
|
784
|
+
get: () => Promise.resolve(void 0),
|
|
785
|
+
set: async (keyId, key) => await options.keyCache?.set(keyId, key)
|
|
786
|
+
}
|
|
787
|
+
});
|
|
615
788
|
}
|
|
616
|
-
|
|
789
|
+
logger.debug("Failed to verify the proof with the fetched key {keyId}:\n{proof}", {
|
|
790
|
+
keyId: proof.verificationMethodId.href,
|
|
791
|
+
proof
|
|
792
|
+
});
|
|
793
|
+
return null;
|
|
617
794
|
}
|
|
618
795
|
/**
|
|
619
796
|
* Verifies the given object. It will verify all the proofs in the object,
|
|
@@ -654,4 +831,4 @@ async function verifyObject(cls, jsonLd, options = {}) {
|
|
|
654
831
|
return object;
|
|
655
832
|
}
|
|
656
833
|
//#endregion
|
|
657
|
-
export { verifyProof as a,
|
|
834
|
+
export { verifyProof as a, getKeyOwner as c, detachSignature as d, hasSignatureLike as f, verifySignature as h, verifyObject as i, attachSignature as l, verifyJsonLd as m, hasProofLike as n, normalizePublicAudience as o, signJsonLd as p, signObject as r, doesActorOwnKey as s, createProof as t, createSignature as u };
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
2
|
+
import "urlpattern-polyfill";
|
|
3
|
+
globalThis.addEventListener = () => {};
|
|
4
|
+
import { PUBLIC_COLLECTION } from "@fedify/vocab";
|
|
5
|
+
import { preloadedContexts } from "@fedify/vocab-runtime";
|
|
6
|
+
import { getLogger } from "@logtape/logtape";
|
|
7
|
+
import jsonld from "@fedify/vocab-runtime/jsonld";
|
|
8
|
+
//#region src/compat/public-audience.ts
|
|
9
|
+
const logger = getLogger([
|
|
10
|
+
"fedify",
|
|
11
|
+
"compat",
|
|
12
|
+
"public-audience"
|
|
13
|
+
]);
|
|
14
|
+
const PUBLIC_ADDRESSING_FIELDS = new Set([
|
|
15
|
+
"to",
|
|
16
|
+
"cc",
|
|
17
|
+
"bto",
|
|
18
|
+
"bcc",
|
|
19
|
+
"audience"
|
|
20
|
+
]);
|
|
21
|
+
const preloadedOnlyDocumentLoader = (url) => {
|
|
22
|
+
if (url in preloadedContexts) return Promise.resolve({
|
|
23
|
+
contextUrl: null,
|
|
24
|
+
documentUrl: url,
|
|
25
|
+
document: preloadedContexts[url]
|
|
26
|
+
});
|
|
27
|
+
return Promise.reject(/* @__PURE__ */ new Error("Refusing to fetch a non-preloaded JSON-LD context: " + url));
|
|
28
|
+
};
|
|
29
|
+
const AS_CONTEXT_URL = "https://www.w3.org/ns/activitystreams";
|
|
30
|
+
const MAX_TRAVERSAL_DEPTH = 64;
|
|
31
|
+
const KNOWN_SAFE_CONTEXT_URLS = new Set(Object.keys(preloadedContexts));
|
|
32
|
+
function hasPublicCurieInAddressing(value, parentKey, depth = 0) {
|
|
33
|
+
if (typeof value === "string") return parentKey != null && PUBLIC_ADDRESSING_FIELDS.has(parentKey) && (value === "as:Public" || value === "Public");
|
|
34
|
+
if (depth >= MAX_TRAVERSAL_DEPTH) return false;
|
|
35
|
+
if (Array.isArray(value)) return value.some((item) => hasPublicCurieInAddressing(item, parentKey, depth + 1));
|
|
36
|
+
if (typeof value !== "object" || value == null) return false;
|
|
37
|
+
const record = value;
|
|
38
|
+
for (const key of Object.keys(record)) {
|
|
39
|
+
if (key === "@context") continue;
|
|
40
|
+
if (hasPublicCurieInAddressing(record[key], key, depth + 1)) return true;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
function rewritePublicAudience(value, parentKey, depth = 0) {
|
|
45
|
+
if (typeof value === "string" && parentKey != null && PUBLIC_ADDRESSING_FIELDS.has(parentKey) && (value === "as:Public" || value === "Public")) return PUBLIC_COLLECTION.href;
|
|
46
|
+
if (depth >= MAX_TRAVERSAL_DEPTH) return value;
|
|
47
|
+
if (Array.isArray(value)) {
|
|
48
|
+
let changed = false;
|
|
49
|
+
const mapped = value.map((item) => {
|
|
50
|
+
const rewritten = rewritePublicAudience(item, parentKey, depth + 1);
|
|
51
|
+
if (rewritten !== item) changed = true;
|
|
52
|
+
return rewritten;
|
|
53
|
+
});
|
|
54
|
+
return changed ? mapped : value;
|
|
55
|
+
}
|
|
56
|
+
if (typeof value !== "object" || value == null) return value;
|
|
57
|
+
const record = value;
|
|
58
|
+
let changed = false;
|
|
59
|
+
const normalized = {};
|
|
60
|
+
for (const key of Object.keys(record)) {
|
|
61
|
+
const rewritten = key === "@context" ? record[key] : rewritePublicAudience(record[key], key, depth + 1);
|
|
62
|
+
if (rewritten !== record[key]) changed = true;
|
|
63
|
+
normalized[key] = rewritten;
|
|
64
|
+
}
|
|
65
|
+
return changed ? normalized : value;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Reports whether `value` carries an `@context` property anywhere inside
|
|
69
|
+
* its subtree (not counting the value itself). A nested `@context` can
|
|
70
|
+
* introduce a local term-definition scope that redefines `as:` or `Public`
|
|
71
|
+
* even when the top-level `@context` is safe, so the fast path must defer
|
|
72
|
+
* to the URDNA2015 equivalence check whenever one is present.
|
|
73
|
+
*/
|
|
74
|
+
function hasNestedContext(value, depth = 0) {
|
|
75
|
+
if (depth >= MAX_TRAVERSAL_DEPTH) return true;
|
|
76
|
+
if (Array.isArray(value)) return value.some((item) => hasNestedContext(item, depth + 1));
|
|
77
|
+
if (typeof value !== "object" || value == null) return false;
|
|
78
|
+
const record = value;
|
|
79
|
+
for (const key of Object.keys(record)) {
|
|
80
|
+
if (key === "@context") return true;
|
|
81
|
+
if (hasNestedContext(record[key], depth + 1)) return true;
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Checks whether the `@context` of a JSON-LD document is guaranteed not
|
|
87
|
+
* to redefine the `as:` prefix or the bare `Public` term. Only documents
|
|
88
|
+
* whose `@context` is a string, or an array of strings, drawn from Fedify's
|
|
89
|
+
* preloaded context set AND including the ActivityStreams URL qualify,
|
|
90
|
+
* AND no nested subtree carries its own `@context` that might redefine
|
|
91
|
+
* those terms within a local scope. When all of that holds the rewrite
|
|
92
|
+
* is provably semantics-preserving and the URDNA2015 equivalence check
|
|
93
|
+
* can be skipped. Any other shape (unknown external URLs, inline
|
|
94
|
+
* objects at the top level, nested `@context` blocks) is treated as
|
|
95
|
+
* potentially unsafe.
|
|
96
|
+
*/
|
|
97
|
+
function hasKnownSafeContext(jsonLd) {
|
|
98
|
+
if (typeof jsonLd !== "object" || jsonLd == null) return false;
|
|
99
|
+
const record = jsonLd;
|
|
100
|
+
if (!Object.hasOwn(record, "@context")) return false;
|
|
101
|
+
const ctx = record["@context"];
|
|
102
|
+
const entries = typeof ctx === "string" ? [ctx] : Array.isArray(ctx) ? ctx : null;
|
|
103
|
+
if (entries == null || entries.length === 0) return false;
|
|
104
|
+
let hasAs = false;
|
|
105
|
+
for (const entry of entries) {
|
|
106
|
+
if (typeof entry !== "string") return false;
|
|
107
|
+
if (!KNOWN_SAFE_CONTEXT_URLS.has(entry)) return false;
|
|
108
|
+
if (entry === AS_CONTEXT_URL) hasAs = true;
|
|
109
|
+
}
|
|
110
|
+
if (!hasAs) return false;
|
|
111
|
+
for (const key of Object.keys(record)) {
|
|
112
|
+
if (key === "@context") continue;
|
|
113
|
+
if (hasNestedContext(record[key])) return false;
|
|
114
|
+
}
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Rewrites the compact `as:Public` / `Public` CURIE appearing in activity
|
|
119
|
+
* addressing fields (`to`, `cc`, `bto`, `bcc`, `audience`) to the fully
|
|
120
|
+
* expanded `https://www.w3.org/ns/activitystreams#Public` URI.
|
|
121
|
+
*
|
|
122
|
+
* Several ActivityPub implementations, Lemmy among them, match these
|
|
123
|
+
* fields as plain URLs without running JSON-LD expansion, and silently
|
|
124
|
+
* drop activities whose public addressing appears in CURIE form. This
|
|
125
|
+
* helper works around that gap.
|
|
126
|
+
*
|
|
127
|
+
* For documents whose `@context` is drawn entirely from Fedify's
|
|
128
|
+
* preloaded context set and includes the ActivityStreams URL, the
|
|
129
|
+
* rewrite is applied directly: the content of every preloaded non-AS
|
|
130
|
+
* context is known not to redefine the `as:` prefix or the bare `Public`
|
|
131
|
+
* term, so the semantics are preserved by construction. Any other
|
|
132
|
+
* shape (an inline object, an unknown external URL, and so on) is
|
|
133
|
+
* treated as potentially unsafe and gated on a JSON-LD equivalence
|
|
134
|
+
* check; both forms are canonicalized with URDNA2015 and the resulting
|
|
135
|
+
* N-Quads are compared. When they differ, the original document is
|
|
136
|
+
* returned unchanged. Canonicalization failures also fall back to the
|
|
137
|
+
* original document.
|
|
138
|
+
*
|
|
139
|
+
* When no `contextLoader` is supplied the helper falls back to an
|
|
140
|
+
* internal loader that resolves only the URLs in Fedify's
|
|
141
|
+
* preloaded-contexts set and rejects every other URL without issuing a
|
|
142
|
+
* network request. That behaviour is deliberately narrower than
|
|
143
|
+
* `@fedify/vocab-runtime`'s `getDocumentLoader()`, which after its
|
|
144
|
+
* `validatePublicUrl` check will happily fetch non-preloaded URLs: the
|
|
145
|
+
* helper is reached from verification paths (`verifyProof()` /
|
|
146
|
+
* `verifyObject()`) that operate on inbound, potentially adversarial
|
|
147
|
+
* JSON-LD, and a default loader that fetches attacker-supplied
|
|
148
|
+
* `@context` URLs on the caller's behalf would be an SSRF vector.
|
|
149
|
+
* Canonicalization failures against the restricted loader fall back to
|
|
150
|
+
* the original document, same as any other canonicalization error.
|
|
151
|
+
* Callers that genuinely need the remote-fetch loader (for example
|
|
152
|
+
* applications that sign local JSON-LD against a custom vocabulary)
|
|
153
|
+
* should pass a `contextLoader` explicitly.
|
|
154
|
+
*
|
|
155
|
+
* Must be called before any signing step that canonicalizes the
|
|
156
|
+
* compact form byte-for-byte (for example, Object Integrity Proofs
|
|
157
|
+
* using the `eddsa-jcs-2022` cryptosuite), so the signed payload
|
|
158
|
+
* matches what is sent on the wire.
|
|
159
|
+
*/
|
|
160
|
+
async function normalizePublicAudience(jsonLd, contextLoader) {
|
|
161
|
+
if (!hasPublicCurieInAddressing(jsonLd)) return jsonLd;
|
|
162
|
+
const normalized = rewritePublicAudience(jsonLd);
|
|
163
|
+
if (hasKnownSafeContext(jsonLd)) return normalized;
|
|
164
|
+
const loader = contextLoader ?? preloadedOnlyDocumentLoader;
|
|
165
|
+
try {
|
|
166
|
+
const [before, after] = await Promise.all([jsonld.canonize(jsonLd, {
|
|
167
|
+
format: "application/n-quads",
|
|
168
|
+
documentLoader: loader
|
|
169
|
+
}), jsonld.canonize(normalized, {
|
|
170
|
+
format: "application/n-quads",
|
|
171
|
+
documentLoader: loader
|
|
172
|
+
})]);
|
|
173
|
+
if (before === after) return normalized;
|
|
174
|
+
logger.warn("Expanding the public audience CURIE to its full URI would change the canonical form of the activity; sending the activity as is. This usually means the active JSON-LD context redefines the `as:` prefix or the bare `Public` term.");
|
|
175
|
+
} catch (error) {
|
|
176
|
+
logger.debug("Failed to verify public audience normalization equivalence via JSON-LD canonicalization; sending the activity as is.\n{error}", { error });
|
|
177
|
+
}
|
|
178
|
+
return jsonLd;
|
|
179
|
+
}
|
|
180
|
+
//#endregion
|
|
181
|
+
export { normalizePublicAudience as t };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "@js-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 doubleKnock } from "./http-
|
|
4
|
+
import { n as version, t as name } from "./deno-cvysscWX.mjs";
|
|
5
|
+
import { n as doubleKnock } from "./http-Dy22pK-t.mjs";
|
|
6
6
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
7
7
|
import { getLogger } from "@logtape/logtape";
|
|
8
8
|
//#region src/federation/send.ts
|
package/dist/sig/http.test.mjs
CHANGED
|
@@ -7,8 +7,8 @@ import { a as assertExists, t as assertStringIncludes } from "../std__assert-Dui
|
|
|
7
7
|
import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
|
|
8
8
|
import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
|
|
9
9
|
import { t as assert } from "../assert-ddO5KLpe.mjs";
|
|
10
|
-
import { t as exportJwk } from "../key-
|
|
11
|
-
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-
|
|
10
|
+
import { t as exportJwk } from "../key-DXBoO6CC.mjs";
|
|
11
|
+
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-Dy22pK-t.mjs";
|
|
12
12
|
import { i as rsaPrivateKey2, l as rsaPublicKey5, o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-BAK-tUlf.mjs";
|
|
13
13
|
import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
14
14
|
import { FetchError, exportSpki } from "@fedify/vocab-runtime";
|
package/dist/sig/key.test.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
|
|
|
5
5
|
import "../std__assert-Duiq_YC9.mjs";
|
|
6
6
|
import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
|
|
7
7
|
import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
|
|
8
|
-
import { a as importJwk, i as generateCryptoKeyPair, n as fetchKey, o as validateCryptoKey, r as fetchKeyDetailed, t as exportJwk } from "../key-
|
|
8
|
+
import { a as importJwk, i as generateCryptoKeyPair, n as fetchKey, o as validateCryptoKey, r as fetchKeyDetailed, t as exportJwk } from "../key-DXBoO6CC.mjs";
|
|
9
9
|
import { c as rsaPublicKey3, i as rsaPrivateKey2, o as rsaPublicKey1, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
|
|
10
10
|
import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
11
11
|
import { CryptographicKey, Multikey } from "@fedify/vocab";
|
package/dist/sig/ld.test.mjs
CHANGED
|
@@ -5,9 +5,9 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
|
|
|
5
5
|
import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
|
|
6
6
|
import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
|
|
7
7
|
import { t as assert } from "../assert-ddO5KLpe.mjs";
|
|
8
|
-
import { i as generateCryptoKeyPair } from "../key-
|
|
8
|
+
import { i as generateCryptoKeyPair } from "../key-DXBoO6CC.mjs";
|
|
9
9
|
import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
|
|
10
|
-
import { a as signJsonLd, i as hasSignatureLike, n as createSignature, o as verifyJsonLd, r as detachSignature, s as verifySignature, t as attachSignature } from "../ld-
|
|
10
|
+
import { a as signJsonLd, i as hasSignatureLike, n as createSignature, o as verifyJsonLd, r as detachSignature, s as verifySignature, t as attachSignature } from "../ld-BW_1mHgq.mjs";
|
|
11
11
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
12
12
|
import { CryptographicKey } from "@fedify/vocab";
|
|
13
13
|
import { encodeBase64 } from "byte-encodings/base64";
|
package/dist/sig/mod.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const { Temporal } = require("@js-temporal/polyfill");
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
-
const require_http = require("../http-
|
|
5
|
-
const require_proof = require("../proof-
|
|
4
|
+
const require_http = require("../http-BJ7XtRRp.cjs");
|
|
5
|
+
const require_proof = require("../proof-B__J6A1_.cjs");
|
|
6
6
|
exports.attachSignature = require_proof.attachSignature;
|
|
7
7
|
exports.createProof = require_proof.createProof;
|
|
8
8
|
exports.createSignature = require_proof.createSignature;
|
package/dist/sig/mod.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
|
-
import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "../http-
|
|
4
|
-
import { a as verifyProof, c as
|
|
3
|
+
import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "../http-B0Tu7TW-.js";
|
|
4
|
+
import { a as verifyProof, c as getKeyOwner, d as detachSignature, f as hasSignatureLike, h as verifySignature, i as verifyObject, l as attachSignature, m as verifyJsonLd, n as hasProofLike, p as signJsonLd, r as signObject, s as doesActorOwnKey, t as createProof, u as createSignature } from "../proof-Bfx0NdYz.js";
|
|
5
5
|
export { attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, hasProofLike, hasSignatureLike, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
|
package/dist/sig/owner.test.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import "../std__assert-Duiq_YC9.mjs";
|
|
|
6
6
|
import { n as assertFalse } from "../assert_rejects-B-qJtC9Z.mjs";
|
|
7
7
|
import { t as assert } from "../assert-ddO5KLpe.mjs";
|
|
8
8
|
import { o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-BAK-tUlf.mjs";
|
|
9
|
-
import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-
|
|
9
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-CBdNJRwZ.mjs";
|
|
10
10
|
import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
11
11
|
import { Create, CryptographicKey, lookupObject } from "@fedify/vocab";
|
|
12
12
|
//#region src/sig/owner.test.ts
|