@fedify/fedify 0.9.0-dev.179 → 0.9.0-dev.181
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of @fedify/fedify might be problematic. Click here for more details.
- package/CHANGES.md +11 -0
- package/esm/federation/middleware.js +7 -3
- package/esm/httpsig/mod.js +60 -283
- package/esm/runtime/docloader.js +3 -3
- package/esm/sig/http.js +229 -0
- package/esm/{httpsig → sig}/key.js +0 -3
- package/esm/sig/mod.js +8 -0
- package/esm/sig/owner.js +94 -0
- package/package.json +7 -1
- package/types/federation/middleware.d.ts.map +1 -1
- package/types/httpsig/mod.d.ts +45 -48
- package/types/httpsig/mod.d.ts.map +1 -1
- package/types/sig/http.d.ts +54 -0
- package/types/sig/http.d.ts.map +1 -0
- package/types/sig/http.test.d.ts.map +1 -0
- package/types/{httpsig → sig}/key.d.ts +0 -3
- package/types/sig/key.d.ts.map +1 -0
- package/types/sig/key.test.d.ts.map +1 -0
- package/types/sig/mod.d.ts +9 -0
- package/types/sig/mod.d.ts.map +1 -0
- package/types/sig/owner.d.ts +50 -0
- package/types/sig/owner.d.ts.map +1 -0
- package/types/sig/owner.test.d.ts.map +1 -0
- package/types/httpsig/key.d.ts.map +0 -1
- package/types/httpsig/key.test.d.ts.map +0 -1
package/CHANGES.md
CHANGED
@@ -47,11 +47,22 @@ To be released.
|
|
47
47
|
- The signature of the `verify()` function is revamped; it now optionally
|
48
48
|
takes a `VerifyOptions` object as the second parameter.
|
49
49
|
|
50
|
+
- Renamed the `@fedify/fedify/httpsig` module to `@fedify/fedify/sig`, and
|
51
|
+
also:
|
52
|
+
|
53
|
+
- Deprecated `sign()` function. Use `signRequest()` instead.
|
54
|
+
- Deprecated `verify()` function. Use `verifyRequest()` instead.
|
55
|
+
- Deprecated `VerifyOptions` interface. Use `VerifyRequestOptions`
|
56
|
+
instead.
|
57
|
+
|
50
58
|
- Added more log messages using the [LogTape] library. Currently the below
|
51
59
|
logger categories are used:
|
52
60
|
|
53
61
|
- `["fedify", "federation", "actor"]`
|
54
62
|
- `["fedify", "federation", "http"]`
|
63
|
+
- `["fedify", "sig", "http"]`
|
64
|
+
- `["fedify", "sig", "key"]`
|
65
|
+
- `["fedify", "sig", "owner"]`
|
55
66
|
|
56
67
|
[#48]: https://github.com/dahlia/fedify/issues/48
|
57
68
|
[#52]: https://github.com/dahlia/fedify/issues/52
|
@@ -1,7 +1,8 @@
|
|
1
1
|
import * as dntShim from "../_dnt.shims.js";
|
2
2
|
import { getLogger } from "@logtape/logtape";
|
3
|
-
import {
|
4
|
-
import {
|
3
|
+
import { verifyRequest } from "../sig/http.js";
|
4
|
+
import { exportJwk, importJwk, validateCryptoKey } from "../sig/key.js";
|
5
|
+
import { getKeyOwner } from "../sig/owner.js";
|
5
6
|
import { handleNodeInfo, handleNodeInfoJrd } from "../nodeinfo/handler.js";
|
6
7
|
import { fetchDocumentLoader, getAuthenticatedDocumentLoader, kvCache, } from "../runtime/docloader.js";
|
7
8
|
import { Activity, CryptographicKey } from "../vocab/mod.js";
|
@@ -381,7 +382,10 @@ export class Federation {
|
|
381
382
|
async getSignedKey() {
|
382
383
|
if (signedKey !== undefined)
|
383
384
|
return signedKey;
|
384
|
-
return signedKey = await
|
385
|
+
return signedKey = await verifyRequest(request, {
|
386
|
+
...context,
|
387
|
+
timeWindow,
|
388
|
+
});
|
385
389
|
},
|
386
390
|
async getSignedKeyOwner() {
|
387
391
|
if (signedKeyOwner !== undefined)
|
package/esm/httpsig/mod.js
CHANGED
@@ -1,18 +1,7 @@
|
|
1
|
-
/**
|
2
|
-
* The implementation of the [HTTP
|
3
|
-
* Signatures](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12).
|
4
|
-
*
|
5
|
-
* @module
|
6
|
-
*/
|
7
|
-
import * as dntShim from "../_dnt.shims.js";
|
8
1
|
import { getLogger } from "@logtape/logtape";
|
9
|
-
import {
|
10
|
-
import {
|
11
|
-
import {
|
12
|
-
import { isActor } from "../vocab/actor.js";
|
13
|
-
import { CryptographicKey, Object as ASObject, } from "../vocab/vocab.js";
|
14
|
-
import { validateCryptoKey } from "./key.js";
|
15
|
-
export { exportJwk, generateCryptoKeyPair, importJwk } from "./key.js";
|
2
|
+
import { signRequest, verifyRequest, } from "../sig/http.js";
|
3
|
+
import { exportJwk as newExportJwk, generateCryptoKeyPair as newGenerateCryptoKeyPair, importJwk as newImportJwk, } from "../sig/key.js";
|
4
|
+
import { doesActorOwnKey as newDoesActorOwnKey, getKeyOwner as newGetKeyOwner, } from "../sig/owner.js";
|
16
5
|
/**
|
17
6
|
* Signs a request using the given private key.
|
18
7
|
* @param request The request to sign.
|
@@ -21,45 +10,12 @@ export { exportJwk, generateCryptoKeyPair, importJwk } from "./key.js";
|
|
21
10
|
* verifier.
|
22
11
|
* @returns The signed request.
|
23
12
|
* @throws {TypeError} If the private key is invalid or unsupported.
|
13
|
+
* @deprecated
|
24
14
|
*/
|
25
|
-
export
|
26
|
-
|
27
|
-
|
28
|
-
const body = request.method !== "GET" && request.method !== "HEAD"
|
29
|
-
? await request.arrayBuffer()
|
30
|
-
: null;
|
31
|
-
const headers = new Headers(request.headers);
|
32
|
-
if (!headers.has("Host")) {
|
33
|
-
headers.set("Host", url.host);
|
34
|
-
}
|
35
|
-
if (!headers.has("Digest") && body != null) {
|
36
|
-
const digest = await dntShim.crypto.subtle.digest("SHA-256", body);
|
37
|
-
headers.set("Digest", `sha-256=${encodeBase64(digest)}`);
|
38
|
-
}
|
39
|
-
if (!headers.has("Date")) {
|
40
|
-
headers.set("Date", new Date().toUTCString());
|
41
|
-
}
|
42
|
-
const serialized = [
|
43
|
-
["(request-target)", `${request.method.toLowerCase()} ${url.pathname}`],
|
44
|
-
...headers,
|
45
|
-
];
|
46
|
-
const headerNames = serialized.map(([name]) => name);
|
47
|
-
const message = serialized
|
48
|
-
.map(([name, value]) => `${name}: ${value.trim()}`).join("\n");
|
49
|
-
// TODO: support other than RSASSA-PKCS1-v1_5:
|
50
|
-
const signature = await dntShim.crypto.subtle.sign("RSASSA-PKCS1-v1_5", privateKey, new TextEncoder().encode(message));
|
51
|
-
const sigHeader = `keyId="${keyId.href}",headers="${headerNames.join(" ")}",signature="${encodeBase64(signature)}"`;
|
52
|
-
headers.set("Signature", sigHeader);
|
53
|
-
return new Request(request, {
|
54
|
-
headers,
|
55
|
-
body,
|
56
|
-
});
|
15
|
+
export function sign(request, privateKey, keyId) {
|
16
|
+
getLogger(["fedify", "httpsig", "sign"]).warn("The sign() function is deprecated. Use signRequest() instead.");
|
17
|
+
return signRequest(request, privateKey, keyId);
|
57
18
|
}
|
58
|
-
const supportedHashAlgorithms = {
|
59
|
-
"sha": "SHA-1",
|
60
|
-
"sha-256": "SHA-256",
|
61
|
-
"sha-512": "SHA-512",
|
62
|
-
};
|
63
19
|
/**
|
64
20
|
* Verifies the signature of a request.
|
65
21
|
*
|
@@ -72,167 +28,11 @@ const supportedHashAlgorithms = {
|
|
72
28
|
* @param options Options for verifying the request.
|
73
29
|
* @returns The public key of the verified signature, or `null` if the signature
|
74
30
|
* could not be verified.
|
31
|
+
* @deprecated
|
75
32
|
*/
|
76
|
-
export
|
77
|
-
|
78
|
-
request
|
79
|
-
const dateHeader = request.headers.get("Date");
|
80
|
-
if (dateHeader == null) {
|
81
|
-
logger.debug("Failed to verify; no Date header found.", { headers: Object.fromEntries(request.headers.entries()) });
|
82
|
-
return null;
|
83
|
-
}
|
84
|
-
const sigHeader = request.headers.get("Signature");
|
85
|
-
if (sigHeader == null) {
|
86
|
-
logger.debug("Failed to verify; no Signature header found.", { headers: Object.fromEntries(request.headers.entries()) });
|
87
|
-
return null;
|
88
|
-
}
|
89
|
-
const digestHeader = request.headers.get("Digest");
|
90
|
-
if (request.method !== "GET" && request.method !== "HEAD" &&
|
91
|
-
digestHeader == null) {
|
92
|
-
logger.debug("Failed to verify; no Digest header found.", { headers: Object.fromEntries(request.headers.entries()) });
|
93
|
-
return null;
|
94
|
-
}
|
95
|
-
let body = null;
|
96
|
-
if (digestHeader != null) {
|
97
|
-
body = await request.arrayBuffer();
|
98
|
-
const digests = digestHeader.split(",").map((pair) => pair.includes("=") ? pair.split("=", 2) : [pair, ""]);
|
99
|
-
let matched = false;
|
100
|
-
for (let [algo, digestBase64] of digests) {
|
101
|
-
algo = algo.trim().toLowerCase();
|
102
|
-
if (!(algo in supportedHashAlgorithms))
|
103
|
-
continue;
|
104
|
-
const digest = decodeBase64(digestBase64);
|
105
|
-
const expectedDigest = await dntShim.crypto.subtle.digest(supportedHashAlgorithms[algo], body);
|
106
|
-
if (!equals(digest, new Uint8Array(expectedDigest))) {
|
107
|
-
logger.debug("Failed to verify; digest mismatch ({algorithm}): " +
|
108
|
-
"{digest} != {expectedDigest}.", {
|
109
|
-
algorithm: algo,
|
110
|
-
digest: digestBase64,
|
111
|
-
expectedDigest: encodeBase64(expectedDigest),
|
112
|
-
});
|
113
|
-
return null;
|
114
|
-
}
|
115
|
-
matched = true;
|
116
|
-
}
|
117
|
-
if (!matched) {
|
118
|
-
logger.debug("Failed to verify; no supported digest algorithm found. " +
|
119
|
-
"Supported: {supportedAlgorithms}; found: {algorithms}.", {
|
120
|
-
supportedAlgorithms: Object.keys(supportedHashAlgorithms),
|
121
|
-
algorithms: digests.map(([algo]) => algo),
|
122
|
-
});
|
123
|
-
return null;
|
124
|
-
}
|
125
|
-
}
|
126
|
-
const date = dntShim.Temporal.Instant.from(new Date(dateHeader).toISOString());
|
127
|
-
const now = currentTime ?? dntShim.Temporal.Now.instant();
|
128
|
-
const tw = timeWindow ?? { minutes: 1 };
|
129
|
-
if (dntShim.Temporal.Instant.compare(date, now.add(tw)) > 0) {
|
130
|
-
logger.debug("Failed to verify; Date is too far in the future.", { date: date.toString(), now: now.toString() });
|
131
|
-
return null;
|
132
|
-
}
|
133
|
-
else if (dntShim.Temporal.Instant.compare(date, now.subtract(tw)) < 0) {
|
134
|
-
logger.debug("Failed to verify; Date is too far in the past.", { date: date.toString(), now: now.toString() });
|
135
|
-
return null;
|
136
|
-
}
|
137
|
-
const sigValues = Object.fromEntries(sigHeader.split(",").map((pair) => pair.match(/^\s*([A-Za-z]+)="([^"]*)"\s*$/)).filter((m) => m != null).map((m) => m.slice(1, 3)));
|
138
|
-
if (!("keyId" in sigValues)) {
|
139
|
-
logger.debug("Failed to verify; no keyId field found in the Signature header.", { signature: sigHeader });
|
140
|
-
return null;
|
141
|
-
}
|
142
|
-
else if (!("headers" in sigValues)) {
|
143
|
-
logger.debug("Failed to verify; no headers field found in the Signature header.", { signature: sigHeader });
|
144
|
-
return null;
|
145
|
-
}
|
146
|
-
else if (!("signature" in sigValues)) {
|
147
|
-
logger.debug("Failed to verify; no signature field found in the Signature header.", { signature: sigHeader });
|
148
|
-
return null;
|
149
|
-
}
|
150
|
-
const { keyId, headers, signature } = sigValues;
|
151
|
-
logger.debug("Fetching key {keyId} to verify signature...", { keyId });
|
152
|
-
let document;
|
153
|
-
try {
|
154
|
-
const remoteDocument = await (documentLoader ?? fetchDocumentLoader)(keyId);
|
155
|
-
document = remoteDocument.document;
|
156
|
-
}
|
157
|
-
catch (_) {
|
158
|
-
logger.debug("Failed to fetch key {keyId}.", { keyId });
|
159
|
-
return null;
|
160
|
-
}
|
161
|
-
let object;
|
162
|
-
try {
|
163
|
-
object = await ASObject.fromJsonLd(document, {
|
164
|
-
documentLoader,
|
165
|
-
contextLoader,
|
166
|
-
});
|
167
|
-
}
|
168
|
-
catch (e) {
|
169
|
-
if (!(e instanceof TypeError))
|
170
|
-
throw e;
|
171
|
-
try {
|
172
|
-
object = await CryptographicKey.fromJsonLd(document, {
|
173
|
-
documentLoader,
|
174
|
-
contextLoader,
|
175
|
-
});
|
176
|
-
}
|
177
|
-
catch (e) {
|
178
|
-
if (e instanceof TypeError) {
|
179
|
-
logger.debug("Failed to verify; key {keyId} returned an invalid object.", { keyId });
|
180
|
-
return null;
|
181
|
-
}
|
182
|
-
throw e;
|
183
|
-
}
|
184
|
-
}
|
185
|
-
let key = null;
|
186
|
-
if (object instanceof CryptographicKey)
|
187
|
-
key = object;
|
188
|
-
else if (isActor(object)) {
|
189
|
-
for await (const k of object.getPublicKeys({ documentLoader, contextLoader })) {
|
190
|
-
if (k.id?.href === keyId) {
|
191
|
-
key = k;
|
192
|
-
break;
|
193
|
-
}
|
194
|
-
}
|
195
|
-
if (key == null) {
|
196
|
-
logger.debug("Failed to verify; object {keyId} returned an {actorType}, " +
|
197
|
-
"but has no key matching {keyId}.", { keyId, actorType: object.constructor.name });
|
198
|
-
return null;
|
199
|
-
}
|
200
|
-
}
|
201
|
-
else {
|
202
|
-
logger.debug("Failed to verify; key {keyId} returned an invalid object.", { keyId });
|
203
|
-
return null;
|
204
|
-
}
|
205
|
-
if (key.publicKey == null) {
|
206
|
-
logger.debug("Failed to verify; key {keyId} has no publicKeyPem field.", { keyId });
|
207
|
-
return null;
|
208
|
-
}
|
209
|
-
const headerNames = headers.split(/\s+/g);
|
210
|
-
if (!headerNames.includes("(request-target)") || !headerNames.includes("date")) {
|
211
|
-
logger.debug("Failed to verify; required headers missing in the Signature header: " +
|
212
|
-
"{headers}.", { headers });
|
213
|
-
return null;
|
214
|
-
}
|
215
|
-
if (body != null && !headerNames.includes("digest")) {
|
216
|
-
logger.debug("Failed to verify; required headers missing in the Signature header: " +
|
217
|
-
"{headers}.", { headers });
|
218
|
-
return null;
|
219
|
-
}
|
220
|
-
const message = headerNames.map((name) => `${name}: ` +
|
221
|
-
(name == "(request-target)"
|
222
|
-
? `${request.method.toLowerCase()} ${new URL(request.url).pathname}`
|
223
|
-
: name == "host"
|
224
|
-
? request.headers.get("host") ?? new URL(request.url).host
|
225
|
-
: request.headers.get(name))).join("\n");
|
226
|
-
const sig = decodeBase64(signature);
|
227
|
-
// TODO: support other than RSASSA-PKCS1-v1_5:
|
228
|
-
const verified = await dntShim.crypto.subtle.verify("RSASSA-PKCS1-v1_5", key.publicKey, sig, new TextEncoder().encode(message));
|
229
|
-
if (!verified) {
|
230
|
-
logger.debug("Failed to verify; signature {signature} is invalid. " +
|
231
|
-
"Check if the key is correct or if the signed message is correct. " +
|
232
|
-
"The message to sign is:\n{message}", { signature, message });
|
233
|
-
return null;
|
234
|
-
}
|
235
|
-
return key;
|
33
|
+
export function verify(request, options = {}) {
|
34
|
+
getLogger(["fedify", "httpsig", "verify"]).warn("The verify() function is deprecated. Use verifyRequest() instead.");
|
35
|
+
return verifyRequest(request, options);
|
236
36
|
}
|
237
37
|
/**
|
238
38
|
* Checks if the actor of the given activity owns the specified key.
|
@@ -240,19 +40,12 @@ export async function verify(request, { documentLoader, contextLoader, timeWindo
|
|
240
40
|
* @param key The public key to check.
|
241
41
|
* @param options Options for checking the key ownership.
|
242
42
|
* @returns Whether the actor is the owner of the key.
|
43
|
+
* @deprecated
|
243
44
|
*/
|
244
|
-
export
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
const actor = await activity.getActor(options);
|
249
|
-
if (actor == null || !isActor(actor))
|
250
|
-
return false;
|
251
|
-
for (const publicKeyId of actor.publicKeyIds) {
|
252
|
-
if (key.id != null && publicKeyId.href === key.id.href)
|
253
|
-
return true;
|
254
|
-
}
|
255
|
-
return false;
|
45
|
+
export function doesActorOwnKey(activity, key, options) {
|
46
|
+
getLogger(["fedify", "httpsig"]).warn("The doesActorOwnKey() function from @fedify/fedify/httpsig is deprecated. " +
|
47
|
+
"Use doesActorOwnKey() from @fedify/fedify/sig instead.");
|
48
|
+
return newDoesActorOwnKey(activity, key, options);
|
256
49
|
}
|
257
50
|
/**
|
258
51
|
* Gets the actor that owns the specified key. Returns `null` if the key has no
|
@@ -263,65 +56,49 @@ export async function doesActorOwnKey(activity, key, options) {
|
|
263
56
|
* @returns The actor that owns the key, or `null` if the key has no known
|
264
57
|
* owner.
|
265
58
|
* @since 0.7.0
|
59
|
+
* @deprecated
|
60
|
+
*/
|
61
|
+
export function getKeyOwner(keyId, options) {
|
62
|
+
getLogger(["fedify", "httpsig"]).warn("The getKeyOwner() function from @fedify/fedify/httpsig is deprecated. " +
|
63
|
+
"Use getKeyOwner() from @fedify/fedify/sig instead.");
|
64
|
+
return newGetKeyOwner(keyId, options);
|
65
|
+
}
|
66
|
+
/**
|
67
|
+
* Generates a key pair which is appropriate for Fedify.
|
68
|
+
* @returns The generated key pair.
|
69
|
+
* @since 0.3.0
|
70
|
+
* @deprecated
|
71
|
+
*/
|
72
|
+
export function generateCryptoKeyPair() {
|
73
|
+
getLogger(["fedify", "httpsig", "key"]).warn("The generateCryptoKeyPair() from @fedify/fedify/httpsig is deprecated. " +
|
74
|
+
"Please use generateKeyPair() from @fedify/fedify/sig instead.");
|
75
|
+
return newGenerateCryptoKeyPair();
|
76
|
+
}
|
77
|
+
/**
|
78
|
+
* Exports a key in JWK format.
|
79
|
+
* @param key The key to export. Either public or private key.
|
80
|
+
* @returns The exported key in JWK format. The key is suitable for
|
81
|
+
* serialization and storage.
|
82
|
+
* @throws {TypeError} If the key is invalid or unsupported.
|
83
|
+
* @since 0.3.0
|
84
|
+
* @deprecated
|
85
|
+
*/
|
86
|
+
export function exportJwk(key) {
|
87
|
+
getLogger(["fedify", "httpsig", "key"]).warn("The exportJwk() function from @fedify/fedify/httpsig is deprecated. " +
|
88
|
+
"Please use exportJwk() from @fedify/fedify/sig instead.");
|
89
|
+
return newExportJwk(key);
|
90
|
+
}
|
91
|
+
/**
|
92
|
+
* Imports a key from JWK format.
|
93
|
+
* @param jwk The key in JWK format.
|
94
|
+
* @param type Which type of key to import, either `"public"`" or `"private"`".
|
95
|
+
* @returns The imported key.
|
96
|
+
* @throws {TypeError} If the key is invalid or unsupported.
|
97
|
+
* @since 0.3.0
|
98
|
+
* @deprecated
|
266
99
|
*/
|
267
|
-
export
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
if (keyId instanceof CryptographicKey) {
|
272
|
-
object = keyId;
|
273
|
-
if (object.id == null)
|
274
|
-
return null;
|
275
|
-
keyId = object.id;
|
276
|
-
}
|
277
|
-
else {
|
278
|
-
let keyDoc;
|
279
|
-
try {
|
280
|
-
const { document } = await documentLoader(keyId.href);
|
281
|
-
keyDoc = document;
|
282
|
-
}
|
283
|
-
catch (_) {
|
284
|
-
return null;
|
285
|
-
}
|
286
|
-
try {
|
287
|
-
object = await ASObject.fromJsonLd(keyDoc, {
|
288
|
-
documentLoader,
|
289
|
-
contextLoader,
|
290
|
-
});
|
291
|
-
}
|
292
|
-
catch (e) {
|
293
|
-
if (!(e instanceof TypeError))
|
294
|
-
throw e;
|
295
|
-
try {
|
296
|
-
object = await CryptographicKey.fromJsonLd(keyDoc, {
|
297
|
-
documentLoader,
|
298
|
-
contextLoader,
|
299
|
-
});
|
300
|
-
}
|
301
|
-
catch (e) {
|
302
|
-
if (e instanceof TypeError)
|
303
|
-
return null;
|
304
|
-
throw e;
|
305
|
-
}
|
306
|
-
}
|
307
|
-
}
|
308
|
-
let owner = null;
|
309
|
-
if (object instanceof CryptographicKey) {
|
310
|
-
if (object.ownerId == null)
|
311
|
-
return null;
|
312
|
-
owner = await object.getOwner({ documentLoader, contextLoader });
|
313
|
-
}
|
314
|
-
else if (isActor(object)) {
|
315
|
-
owner = object;
|
316
|
-
}
|
317
|
-
else {
|
318
|
-
return null;
|
319
|
-
}
|
320
|
-
if (owner == null)
|
321
|
-
return null;
|
322
|
-
for (const kid of owner.publicKeyIds) {
|
323
|
-
if (kid.href === keyId.href)
|
324
|
-
return owner;
|
325
|
-
}
|
326
|
-
return null;
|
100
|
+
export function importJwk(jwk, type) {
|
101
|
+
getLogger(["fedify", "httpsig", "key"]).warn("The importJwk() function from @fedify/fedify/httpsig is deprecated. " +
|
102
|
+
"Please use importJwk() from @fedify/fedify/sig instead.");
|
103
|
+
return newImportJwk(jwk, type);
|
327
104
|
}
|
package/esm/runtime/docloader.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import * as dntShim from "../_dnt.shims.js";
|
2
2
|
import { getLogger } from "@logtape/logtape";
|
3
|
-
import {
|
4
|
-
import {
|
3
|
+
import { signRequest } from "../sig/http.js";
|
4
|
+
import { validateCryptoKey } from "../sig/key.js";
|
5
5
|
const logger = getLogger(["fedify", "runtime", "docloader"]);
|
6
6
|
/**
|
7
7
|
* Error thrown when fetching a JSON-LD document failed.
|
@@ -94,7 +94,7 @@ export function getAuthenticatedDocumentLoader(identity) {
|
|
94
94
|
validateCryptoKey(identity.privateKey);
|
95
95
|
async function load(url) {
|
96
96
|
let request = createRequest(url);
|
97
|
-
request = await
|
97
|
+
request = await signRequest(request, identity.privateKey, identity.keyId);
|
98
98
|
logRequest(request);
|
99
99
|
const response = await fetch(request, {
|
100
100
|
// Since Bun has a bug that ignores the `Request.redirect` option,
|
package/esm/sig/http.js
ADDED
@@ -0,0 +1,229 @@
|
|
1
|
+
import * as dntShim from "../_dnt.shims.js";
|
2
|
+
import { getLogger } from "@logtape/logtape";
|
3
|
+
import { equals } from "../deps/jsr.io/@std/bytes/0.224.0/mod.js";
|
4
|
+
import { decodeBase64, encodeBase64 } from "../deps/jsr.io/@std/encoding/0.224.3/base64.js";
|
5
|
+
import { fetchDocumentLoader, } from "../runtime/docloader.js";
|
6
|
+
import { isActor } from "../vocab/actor.js";
|
7
|
+
import { CryptographicKey, Object as ASObject } from "../vocab/vocab.js";
|
8
|
+
import { validateCryptoKey } from "./key.js";
|
9
|
+
/**
|
10
|
+
* Signs a request using the given private key.
|
11
|
+
* @param request The request to sign.
|
12
|
+
* @param privateKey The private key to use for signing.
|
13
|
+
* @param keyId The key ID to use for the signature. It will be used by the
|
14
|
+
* verifier.
|
15
|
+
* @returns The signed request.
|
16
|
+
* @throws {TypeError} If the private key is invalid or unsupported.
|
17
|
+
*/
|
18
|
+
export async function signRequest(request, privateKey, keyId) {
|
19
|
+
validateCryptoKey(privateKey, "private");
|
20
|
+
const url = new URL(request.url);
|
21
|
+
const body = request.method !== "GET" && request.method !== "HEAD"
|
22
|
+
? await request.arrayBuffer()
|
23
|
+
: null;
|
24
|
+
const headers = new Headers(request.headers);
|
25
|
+
if (!headers.has("Host")) {
|
26
|
+
headers.set("Host", url.host);
|
27
|
+
}
|
28
|
+
if (!headers.has("Digest") && body != null) {
|
29
|
+
const digest = await dntShim.crypto.subtle.digest("SHA-256", body);
|
30
|
+
headers.set("Digest", `sha-256=${encodeBase64(digest)}`);
|
31
|
+
}
|
32
|
+
if (!headers.has("Date")) {
|
33
|
+
headers.set("Date", new Date().toUTCString());
|
34
|
+
}
|
35
|
+
const serialized = [
|
36
|
+
["(request-target)", `${request.method.toLowerCase()} ${url.pathname}`],
|
37
|
+
...headers,
|
38
|
+
];
|
39
|
+
const headerNames = serialized.map(([name]) => name);
|
40
|
+
const message = serialized
|
41
|
+
.map(([name, value]) => `${name}: ${value.trim()}`).join("\n");
|
42
|
+
// TODO: support other than RSASSA-PKCS1-v1_5:
|
43
|
+
const signature = await dntShim.crypto.subtle.sign("RSASSA-PKCS1-v1_5", privateKey, new TextEncoder().encode(message));
|
44
|
+
const sigHeader = `keyId="${keyId.href}",headers="${headerNames.join(" ")}",signature="${encodeBase64(signature)}"`;
|
45
|
+
headers.set("Signature", sigHeader);
|
46
|
+
return new Request(request, {
|
47
|
+
headers,
|
48
|
+
body,
|
49
|
+
});
|
50
|
+
}
|
51
|
+
const supportedHashAlgorithms = {
|
52
|
+
"sha": "SHA-1",
|
53
|
+
"sha-256": "SHA-256",
|
54
|
+
"sha-512": "SHA-512",
|
55
|
+
};
|
56
|
+
/**
|
57
|
+
* Verifies the signature of a request.
|
58
|
+
*
|
59
|
+
* Note that this function consumes the request body, so it should not be used
|
60
|
+
* if the request body is already consumed. Consuming the request body after
|
61
|
+
* calling this function is okay, since this function clones the request
|
62
|
+
* under the hood.
|
63
|
+
*
|
64
|
+
* @param request The request to verify.
|
65
|
+
* @param options Options for verifying the request.
|
66
|
+
* @returns The public key of the verified signature, or `null` if the signature
|
67
|
+
* could not be verified.
|
68
|
+
*/
|
69
|
+
export async function verifyRequest(request, { documentLoader, contextLoader, timeWindow, currentTime } = {}) {
|
70
|
+
const logger = getLogger(["fedify", "sig", "http"]);
|
71
|
+
request = request.clone();
|
72
|
+
const dateHeader = request.headers.get("Date");
|
73
|
+
if (dateHeader == null) {
|
74
|
+
logger.debug("Failed to verify; no Date header found.", { headers: Object.fromEntries(request.headers.entries()) });
|
75
|
+
return null;
|
76
|
+
}
|
77
|
+
const sigHeader = request.headers.get("Signature");
|
78
|
+
if (sigHeader == null) {
|
79
|
+
logger.debug("Failed to verify; no Signature header found.", { headers: Object.fromEntries(request.headers.entries()) });
|
80
|
+
return null;
|
81
|
+
}
|
82
|
+
const digestHeader = request.headers.get("Digest");
|
83
|
+
if (request.method !== "GET" && request.method !== "HEAD" &&
|
84
|
+
digestHeader == null) {
|
85
|
+
logger.debug("Failed to verify; no Digest header found.", { headers: Object.fromEntries(request.headers.entries()) });
|
86
|
+
return null;
|
87
|
+
}
|
88
|
+
let body = null;
|
89
|
+
if (digestHeader != null) {
|
90
|
+
body = await request.arrayBuffer();
|
91
|
+
const digests = digestHeader.split(",").map((pair) => pair.includes("=") ? pair.split("=", 2) : [pair, ""]);
|
92
|
+
let matched = false;
|
93
|
+
for (let [algo, digestBase64] of digests) {
|
94
|
+
algo = algo.trim().toLowerCase();
|
95
|
+
if (!(algo in supportedHashAlgorithms))
|
96
|
+
continue;
|
97
|
+
const digest = decodeBase64(digestBase64);
|
98
|
+
const expectedDigest = await dntShim.crypto.subtle.digest(supportedHashAlgorithms[algo], body);
|
99
|
+
if (!equals(digest, new Uint8Array(expectedDigest))) {
|
100
|
+
logger.debug("Failed to verify; digest mismatch ({algorithm}): " +
|
101
|
+
"{digest} != {expectedDigest}.", {
|
102
|
+
algorithm: algo,
|
103
|
+
digest: digestBase64,
|
104
|
+
expectedDigest: encodeBase64(expectedDigest),
|
105
|
+
});
|
106
|
+
return null;
|
107
|
+
}
|
108
|
+
matched = true;
|
109
|
+
}
|
110
|
+
if (!matched) {
|
111
|
+
logger.debug("Failed to verify; no supported digest algorithm found. " +
|
112
|
+
"Supported: {supportedAlgorithms}; found: {algorithms}.", {
|
113
|
+
supportedAlgorithms: Object.keys(supportedHashAlgorithms),
|
114
|
+
algorithms: digests.map(([algo]) => algo),
|
115
|
+
});
|
116
|
+
return null;
|
117
|
+
}
|
118
|
+
}
|
119
|
+
const date = dntShim.Temporal.Instant.from(new Date(dateHeader).toISOString());
|
120
|
+
const now = currentTime ?? dntShim.Temporal.Now.instant();
|
121
|
+
const tw = timeWindow ?? { minutes: 1 };
|
122
|
+
if (dntShim.Temporal.Instant.compare(date, now.add(tw)) > 0) {
|
123
|
+
logger.debug("Failed to verify; Date is too far in the future.", { date: date.toString(), now: now.toString() });
|
124
|
+
return null;
|
125
|
+
}
|
126
|
+
else if (dntShim.Temporal.Instant.compare(date, now.subtract(tw)) < 0) {
|
127
|
+
logger.debug("Failed to verify; Date is too far in the past.", { date: date.toString(), now: now.toString() });
|
128
|
+
return null;
|
129
|
+
}
|
130
|
+
const sigValues = Object.fromEntries(sigHeader.split(",").map((pair) => pair.match(/^\s*([A-Za-z]+)="([^"]*)"\s*$/)).filter((m) => m != null).map((m) => m.slice(1, 3)));
|
131
|
+
if (!("keyId" in sigValues)) {
|
132
|
+
logger.debug("Failed to verify; no keyId field found in the Signature header.", { signature: sigHeader });
|
133
|
+
return null;
|
134
|
+
}
|
135
|
+
else if (!("headers" in sigValues)) {
|
136
|
+
logger.debug("Failed to verify; no headers field found in the Signature header.", { signature: sigHeader });
|
137
|
+
return null;
|
138
|
+
}
|
139
|
+
else if (!("signature" in sigValues)) {
|
140
|
+
logger.debug("Failed to verify; no signature field found in the Signature header.", { signature: sigHeader });
|
141
|
+
return null;
|
142
|
+
}
|
143
|
+
const { keyId, headers, signature } = sigValues;
|
144
|
+
logger.debug("Fetching key {keyId} to verify signature...", { keyId });
|
145
|
+
let document;
|
146
|
+
try {
|
147
|
+
const remoteDocument = await (documentLoader ?? fetchDocumentLoader)(keyId);
|
148
|
+
document = remoteDocument.document;
|
149
|
+
}
|
150
|
+
catch (_) {
|
151
|
+
logger.debug("Failed to fetch key {keyId}.", { keyId });
|
152
|
+
return null;
|
153
|
+
}
|
154
|
+
let object;
|
155
|
+
try {
|
156
|
+
object = await ASObject.fromJsonLd(document, {
|
157
|
+
documentLoader,
|
158
|
+
contextLoader,
|
159
|
+
});
|
160
|
+
}
|
161
|
+
catch (e) {
|
162
|
+
if (!(e instanceof TypeError))
|
163
|
+
throw e;
|
164
|
+
try {
|
165
|
+
object = await CryptographicKey.fromJsonLd(document, {
|
166
|
+
documentLoader,
|
167
|
+
contextLoader,
|
168
|
+
});
|
169
|
+
}
|
170
|
+
catch (e) {
|
171
|
+
if (e instanceof TypeError) {
|
172
|
+
logger.debug("Failed to verify; key {keyId} returned an invalid object.", { keyId });
|
173
|
+
return null;
|
174
|
+
}
|
175
|
+
throw e;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
let key = null;
|
179
|
+
if (object instanceof CryptographicKey)
|
180
|
+
key = object;
|
181
|
+
else if (isActor(object)) {
|
182
|
+
for await (const k of object.getPublicKeys({ documentLoader, contextLoader })) {
|
183
|
+
if (k.id?.href === keyId) {
|
184
|
+
key = k;
|
185
|
+
break;
|
186
|
+
}
|
187
|
+
}
|
188
|
+
if (key == null) {
|
189
|
+
logger.debug("Failed to verify; object {keyId} returned an {actorType}, " +
|
190
|
+
"but has no key matching {keyId}.", { keyId, actorType: object.constructor.name });
|
191
|
+
return null;
|
192
|
+
}
|
193
|
+
}
|
194
|
+
else {
|
195
|
+
logger.debug("Failed to verify; key {keyId} returned an invalid object.", { keyId });
|
196
|
+
return null;
|
197
|
+
}
|
198
|
+
if (key.publicKey == null) {
|
199
|
+
logger.debug("Failed to verify; key {keyId} has no publicKeyPem field.", { keyId });
|
200
|
+
return null;
|
201
|
+
}
|
202
|
+
const headerNames = headers.split(/\s+/g);
|
203
|
+
if (!headerNames.includes("(request-target)") || !headerNames.includes("date")) {
|
204
|
+
logger.debug("Failed to verify; required headers missing in the Signature header: " +
|
205
|
+
"{headers}.", { headers });
|
206
|
+
return null;
|
207
|
+
}
|
208
|
+
if (body != null && !headerNames.includes("digest")) {
|
209
|
+
logger.debug("Failed to verify; required headers missing in the Signature header: " +
|
210
|
+
"{headers}.", { headers });
|
211
|
+
return null;
|
212
|
+
}
|
213
|
+
const message = headerNames.map((name) => `${name}: ` +
|
214
|
+
(name == "(request-target)"
|
215
|
+
? `${request.method.toLowerCase()} ${new URL(request.url).pathname}`
|
216
|
+
: name == "host"
|
217
|
+
? request.headers.get("host") ?? new URL(request.url).host
|
218
|
+
: request.headers.get(name))).join("\n");
|
219
|
+
const sig = decodeBase64(signature);
|
220
|
+
// TODO: support other than RSASSA-PKCS1-v1_5:
|
221
|
+
const verified = await dntShim.crypto.subtle.verify("RSASSA-PKCS1-v1_5", key.publicKey, sig, new TextEncoder().encode(message));
|
222
|
+
if (!verified) {
|
223
|
+
logger.debug("Failed to verify; signature {signature} is invalid. " +
|
224
|
+
"Check if the key is correct or if the signed message is correct. " +
|
225
|
+
"The message to sign is:\n{message}", { signature, message });
|
226
|
+
return null;
|
227
|
+
}
|
228
|
+
return key;
|
229
|
+
}
|
@@ -28,7 +28,6 @@ export function validateCryptoKey(key, type) {
|
|
28
28
|
/**
|
29
29
|
* Generates a key pair which is appropriate for Fedify.
|
30
30
|
* @returns The generated key pair.
|
31
|
-
* @since 0.3.0
|
32
31
|
*/
|
33
32
|
export function generateCryptoKeyPair() {
|
34
33
|
return dntShim.crypto.subtle.generateKey({
|
@@ -44,7 +43,6 @@ export function generateCryptoKeyPair() {
|
|
44
43
|
* @returns The exported key in JWK format. The key is suitable for
|
45
44
|
* serialization and storage.
|
46
45
|
* @throws {TypeError} If the key is invalid or unsupported.
|
47
|
-
* @since 0.3.0
|
48
46
|
*/
|
49
47
|
export async function exportJwk(key) {
|
50
48
|
validateCryptoKey(key);
|
@@ -56,7 +54,6 @@ export async function exportJwk(key) {
|
|
56
54
|
* @param type Which type of key to import, either `"public"`" or `"private"`".
|
57
55
|
* @returns The imported key.
|
58
56
|
* @throws {TypeError} If the key is invalid or unsupported.
|
59
|
-
* @since 0.3.0
|
60
57
|
*/
|
61
58
|
export async function importJwk(jwk, type) {
|
62
59
|
const key = await dntShim.crypto.subtle.importKey("jwk", jwk, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, true, type === "public" ? ["verify"] : ["sign"]);
|
package/esm/sig/mod.js
ADDED
package/esm/sig/owner.js
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
import { fetchDocumentLoader, } from "../runtime/docloader.js";
|
2
|
+
import { isActor } from "../vocab/actor.js";
|
3
|
+
import { CryptographicKey, Object as ASObject, } from "../vocab/vocab.js";
|
4
|
+
export { exportJwk, generateCryptoKeyPair, importJwk } from "./key.js";
|
5
|
+
/**
|
6
|
+
* Checks if the actor of the given activity owns the specified key.
|
7
|
+
* @param activity The activity to check.
|
8
|
+
* @param key The public key to check.
|
9
|
+
* @param options Options for checking the key ownership.
|
10
|
+
* @returns Whether the actor is the owner of the key.
|
11
|
+
*/
|
12
|
+
export async function doesActorOwnKey(activity, key, options) {
|
13
|
+
if (key.ownerId != null) {
|
14
|
+
return key.ownerId.href === activity.actorId?.href;
|
15
|
+
}
|
16
|
+
const actor = await activity.getActor(options);
|
17
|
+
if (actor == null || !isActor(actor))
|
18
|
+
return false;
|
19
|
+
for (const publicKeyId of actor.publicKeyIds) {
|
20
|
+
if (key.id != null && publicKeyId.href === key.id.href)
|
21
|
+
return true;
|
22
|
+
}
|
23
|
+
return false;
|
24
|
+
}
|
25
|
+
/**
|
26
|
+
* Gets the actor that owns the specified key. Returns `null` if the key has no
|
27
|
+
* known owner.
|
28
|
+
*
|
29
|
+
* @param keyId The ID of the key to check, or the key itself.
|
30
|
+
* @param options Options for getting the key owner.
|
31
|
+
* @returns The actor that owns the key, or `null` if the key has no known
|
32
|
+
* owner.
|
33
|
+
*/
|
34
|
+
export async function getKeyOwner(keyId, options) {
|
35
|
+
const documentLoader = options.documentLoader ?? fetchDocumentLoader;
|
36
|
+
const contextLoader = options.contextLoader ?? fetchDocumentLoader;
|
37
|
+
let object;
|
38
|
+
if (keyId instanceof CryptographicKey) {
|
39
|
+
object = keyId;
|
40
|
+
if (object.id == null)
|
41
|
+
return null;
|
42
|
+
keyId = object.id;
|
43
|
+
}
|
44
|
+
else {
|
45
|
+
let keyDoc;
|
46
|
+
try {
|
47
|
+
const { document } = await documentLoader(keyId.href);
|
48
|
+
keyDoc = document;
|
49
|
+
}
|
50
|
+
catch (_) {
|
51
|
+
return null;
|
52
|
+
}
|
53
|
+
try {
|
54
|
+
object = await ASObject.fromJsonLd(keyDoc, {
|
55
|
+
documentLoader,
|
56
|
+
contextLoader,
|
57
|
+
});
|
58
|
+
}
|
59
|
+
catch (e) {
|
60
|
+
if (!(e instanceof TypeError))
|
61
|
+
throw e;
|
62
|
+
try {
|
63
|
+
object = await CryptographicKey.fromJsonLd(keyDoc, {
|
64
|
+
documentLoader,
|
65
|
+
contextLoader,
|
66
|
+
});
|
67
|
+
}
|
68
|
+
catch (e) {
|
69
|
+
if (e instanceof TypeError)
|
70
|
+
return null;
|
71
|
+
throw e;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
}
|
75
|
+
let owner = null;
|
76
|
+
if (object instanceof CryptographicKey) {
|
77
|
+
if (object.ownerId == null)
|
78
|
+
return null;
|
79
|
+
owner = await object.getOwner({ documentLoader, contextLoader });
|
80
|
+
}
|
81
|
+
else if (isActor(object)) {
|
82
|
+
owner = object;
|
83
|
+
}
|
84
|
+
else {
|
85
|
+
return null;
|
86
|
+
}
|
87
|
+
if (owner == null)
|
88
|
+
return null;
|
89
|
+
for (const kid of owner.publicKeyIds) {
|
90
|
+
if (kid.href === keyId.href)
|
91
|
+
return owner;
|
92
|
+
}
|
93
|
+
return null;
|
94
|
+
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@fedify/fedify",
|
3
|
-
"version": "0.9.0-dev.
|
3
|
+
"version": "0.9.0-dev.181+d5e0642c",
|
4
4
|
"description": "An ActivityPub server framework",
|
5
5
|
"keywords": [
|
6
6
|
"ActivityPub",
|
@@ -53,6 +53,12 @@
|
|
53
53
|
"default": "./esm/runtime/mod.js"
|
54
54
|
}
|
55
55
|
},
|
56
|
+
"./sig": {
|
57
|
+
"import": {
|
58
|
+
"types": "./types/sig/mod.d.ts",
|
59
|
+
"default": "./esm/sig/mod.js"
|
60
|
+
}
|
61
|
+
},
|
56
62
|
"./vocab": {
|
57
63
|
"import": {
|
58
64
|
"types": "./types/vocab/mod.d.ts",
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/federation/middleware.ts"],"names":[],"mappings":";;AAAA,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/federation/middleware.ts"],"names":[],"mappings":"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"}
|
package/types/httpsig/mod.d.ts
CHANGED
@@ -5,12 +5,13 @@
|
|
5
5
|
* Signatures](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12).
|
6
6
|
*
|
7
7
|
* @module
|
8
|
+
* @deprecated
|
8
9
|
*/
|
9
10
|
import * as dntShim from "../_dnt.shims.js";
|
10
|
-
import { type
|
11
|
-
import { type
|
12
|
-
import
|
13
|
-
|
11
|
+
import { type VerifyRequestOptions } from "../sig/http.js";
|
12
|
+
import { type DoesActorOwnKeyOptions as NewDoesActorOwnKeyOptions, type GetKeyOwnerOptions as NewGetKeyOwnerOptions } from "../sig/owner.js";
|
13
|
+
import type { Actor } from "../vocab/actor.js";
|
14
|
+
import type { Activity, CryptographicKey } from "../vocab/vocab.js";
|
14
15
|
/**
|
15
16
|
* Signs a request using the given private key.
|
16
17
|
* @param request The request to sign.
|
@@ -19,34 +20,16 @@ export { exportJwk, generateCryptoKeyPair, importJwk } from "./key.js";
|
|
19
20
|
* verifier.
|
20
21
|
* @returns The signed request.
|
21
22
|
* @throws {TypeError} If the private key is invalid or unsupported.
|
23
|
+
* @deprecated
|
22
24
|
*/
|
23
25
|
export declare function sign(request: Request, privateKey: dntShim.CryptoKey, keyId: URL): Promise<Request>;
|
24
26
|
/**
|
25
27
|
* Options for {@link verify}.
|
26
28
|
*
|
27
29
|
* @since 0.9.0
|
30
|
+
* @deprecated
|
28
31
|
*/
|
29
|
-
export
|
30
|
-
/**
|
31
|
-
* The document loader to use for fetching the public key.
|
32
|
-
*/
|
33
|
-
documentLoader?: DocumentLoader;
|
34
|
-
/**
|
35
|
-
* The context loader to use for JSON-LD context retrieval.
|
36
|
-
*/
|
37
|
-
contextLoader?: DocumentLoader;
|
38
|
-
/**
|
39
|
-
* The time window to allow for the request date. The actual time window is
|
40
|
-
* twice the value of this option, with the current time as the center.
|
41
|
-
* A minute by default.
|
42
|
-
*/
|
43
|
-
timeWindow?: dntShim.Temporal.DurationLike;
|
44
|
-
/**
|
45
|
-
* The current time. If not specified, the current time is used. This is
|
46
|
-
* useful for testing.
|
47
|
-
*/
|
48
|
-
currentTime?: dntShim.Temporal.Instant;
|
49
|
-
}
|
32
|
+
export type VerifyOptions = VerifyRequestOptions;
|
50
33
|
/**
|
51
34
|
* Verifies the signature of a request.
|
52
35
|
*
|
@@ -59,44 +42,30 @@ export interface VerifyOptions {
|
|
59
42
|
* @param options Options for verifying the request.
|
60
43
|
* @returns The public key of the verified signature, or `null` if the signature
|
61
44
|
* could not be verified.
|
45
|
+
* @deprecated
|
62
46
|
*/
|
63
|
-
export declare function verify(request: Request,
|
47
|
+
export declare function verify(request: Request, options?: VerifyRequestOptions): Promise<CryptographicKey | null>;
|
64
48
|
/**
|
65
49
|
* Options for {@link doesActorOwnKey}.
|
66
50
|
* @since 0.8.0
|
51
|
+
* @deprecated
|
67
52
|
*/
|
68
|
-
export
|
69
|
-
/**
|
70
|
-
* The document loader to use for fetching the actor.
|
71
|
-
*/
|
72
|
-
documentLoader?: DocumentLoader;
|
73
|
-
/**
|
74
|
-
* The context loader to use for JSON-LD context retrieval.
|
75
|
-
*/
|
76
|
-
contextLoader?: DocumentLoader;
|
77
|
-
}
|
53
|
+
export type DoesActorOwnKeyOptions = NewDoesActorOwnKeyOptions;
|
78
54
|
/**
|
79
55
|
* Checks if the actor of the given activity owns the specified key.
|
80
56
|
* @param activity The activity to check.
|
81
57
|
* @param key The public key to check.
|
82
58
|
* @param options Options for checking the key ownership.
|
83
59
|
* @returns Whether the actor is the owner of the key.
|
60
|
+
* @deprecated
|
84
61
|
*/
|
85
|
-
export declare function doesActorOwnKey(activity: Activity, key: CryptographicKey, options:
|
62
|
+
export declare function doesActorOwnKey(activity: Activity, key: CryptographicKey, options: NewDoesActorOwnKeyOptions): Promise<boolean>;
|
86
63
|
/**
|
87
64
|
* Options for {@link getKeyOwner}.
|
88
65
|
* @since 0.8.0
|
66
|
+
* @deprecated
|
89
67
|
*/
|
90
|
-
export
|
91
|
-
/**
|
92
|
-
* The document loader to use for fetching the key and its owner.
|
93
|
-
*/
|
94
|
-
documentLoader?: DocumentLoader;
|
95
|
-
/**
|
96
|
-
* The context loader to use for JSON-LD context retrieval.
|
97
|
-
*/
|
98
|
-
contextLoader?: DocumentLoader;
|
99
|
-
}
|
68
|
+
export type GetKeyOwnerOptions = NewGetKeyOwnerOptions;
|
100
69
|
/**
|
101
70
|
* Gets the actor that owns the specified key. Returns `null` if the key has no
|
102
71
|
* known owner.
|
@@ -106,6 +75,34 @@ export interface GetKeyOwnerOptions {
|
|
106
75
|
* @returns The actor that owns the key, or `null` if the key has no known
|
107
76
|
* owner.
|
108
77
|
* @since 0.7.0
|
78
|
+
* @deprecated
|
109
79
|
*/
|
110
|
-
export declare function getKeyOwner(keyId: URL | CryptographicKey, options:
|
80
|
+
export declare function getKeyOwner(keyId: URL | CryptographicKey, options: NewGetKeyOwnerOptions): Promise<Actor | null>;
|
81
|
+
/**
|
82
|
+
* Generates a key pair which is appropriate for Fedify.
|
83
|
+
* @returns The generated key pair.
|
84
|
+
* @since 0.3.0
|
85
|
+
* @deprecated
|
86
|
+
*/
|
87
|
+
export declare function generateCryptoKeyPair(): Promise<dntShim.CryptoKeyPair>;
|
88
|
+
/**
|
89
|
+
* Exports a key in JWK format.
|
90
|
+
* @param key The key to export. Either public or private key.
|
91
|
+
* @returns The exported key in JWK format. The key is suitable for
|
92
|
+
* serialization and storage.
|
93
|
+
* @throws {TypeError} If the key is invalid or unsupported.
|
94
|
+
* @since 0.3.0
|
95
|
+
* @deprecated
|
96
|
+
*/
|
97
|
+
export declare function exportJwk(key: dntShim.CryptoKey): Promise<dntShim.JsonWebKey>;
|
98
|
+
/**
|
99
|
+
* Imports a key from JWK format.
|
100
|
+
* @param jwk The key in JWK format.
|
101
|
+
* @param type Which type of key to import, either `"public"`" or `"private"`".
|
102
|
+
* @returns The imported key.
|
103
|
+
* @throws {TypeError} If the key is invalid or unsupported.
|
104
|
+
* @since 0.3.0
|
105
|
+
* @deprecated
|
106
|
+
*/
|
107
|
+
export declare function importJwk(jwk: dntShim.JsonWebKey, type: "public" | "private"): Promise<dntShim.CryptoKey>;
|
111
108
|
//# sourceMappingURL=mod.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/httpsig/mod.ts"],"names":[],"mappings":";;AAAA
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/httpsig/mod.ts"],"names":[],"mappings":";;AAAA;;;;;;GAMG;AACH,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAG5C,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,gBAAgB,CAAC;AAMxB,OAAO,EAEL,KAAK,sBAAsB,IAAI,yBAAyB,EAExD,KAAK,kBAAkB,IAAI,qBAAqB,EACjD,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEpE;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAClB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,OAAO,CAAC,SAAS,EAC7B,KAAK,EAAE,GAAG,GACT,OAAO,CAAC,OAAO,CAAC,CAKlB;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,oBAAoB,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CACpB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAKlC;AAED;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAE/D;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,OAAO,CAAC,CAMlB;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,qBAAqB,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,GAAG,GAAG,gBAAgB,EAC7B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAMvB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAMtE;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAM7E;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,OAAO,CAAC,UAAU,EACvB,IAAI,EAAE,QAAQ,GAAG,SAAS,GACzB,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAM5B"}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
/// <reference types="node" />
|
3
|
+
import * as dntShim from "../_dnt.shims.js";
|
4
|
+
import { type DocumentLoader } from "../runtime/docloader.js";
|
5
|
+
import { CryptographicKey } from "../vocab/vocab.js";
|
6
|
+
/**
|
7
|
+
* Signs a request using the given private key.
|
8
|
+
* @param request The request to sign.
|
9
|
+
* @param privateKey The private key to use for signing.
|
10
|
+
* @param keyId The key ID to use for the signature. It will be used by the
|
11
|
+
* verifier.
|
12
|
+
* @returns The signed request.
|
13
|
+
* @throws {TypeError} If the private key is invalid or unsupported.
|
14
|
+
*/
|
15
|
+
export declare function signRequest(request: Request, privateKey: dntShim.CryptoKey, keyId: URL): Promise<Request>;
|
16
|
+
/**
|
17
|
+
* Options for {@link verify}.
|
18
|
+
*/
|
19
|
+
export interface VerifyRequestOptions {
|
20
|
+
/**
|
21
|
+
* The document loader to use for fetching the public key.
|
22
|
+
*/
|
23
|
+
documentLoader?: DocumentLoader;
|
24
|
+
/**
|
25
|
+
* The context loader to use for JSON-LD context retrieval.
|
26
|
+
*/
|
27
|
+
contextLoader?: DocumentLoader;
|
28
|
+
/**
|
29
|
+
* The time window to allow for the request date. The actual time window is
|
30
|
+
* twice the value of this option, with the current time as the center.
|
31
|
+
* A minute by default.
|
32
|
+
*/
|
33
|
+
timeWindow?: dntShim.Temporal.DurationLike;
|
34
|
+
/**
|
35
|
+
* The current time. If not specified, the current time is used. This is
|
36
|
+
* useful for testing.
|
37
|
+
*/
|
38
|
+
currentTime?: dntShim.Temporal.Instant;
|
39
|
+
}
|
40
|
+
/**
|
41
|
+
* Verifies the signature of a request.
|
42
|
+
*
|
43
|
+
* Note that this function consumes the request body, so it should not be used
|
44
|
+
* if the request body is already consumed. Consuming the request body after
|
45
|
+
* calling this function is okay, since this function clones the request
|
46
|
+
* under the hood.
|
47
|
+
*
|
48
|
+
* @param request The request to verify.
|
49
|
+
* @param options Options for verifying the request.
|
50
|
+
* @returns The public key of the verified signature, or `null` if the signature
|
51
|
+
* could not be verified.
|
52
|
+
*/
|
53
|
+
export declare function verifyRequest(request: Request, { documentLoader, contextLoader, timeWindow, currentTime }?: VerifyRequestOptions): Promise<CryptographicKey | null>;
|
54
|
+
//# sourceMappingURL=http.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/sig/http.ts"],"names":[],"mappings":";;AAAA,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAI5C,OAAO,EACL,KAAK,cAAc,EAEpB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,gBAAgB,EAAsB,MAAM,mBAAmB,CAAC;AAGzE;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,OAAO,CAAC,SAAS,EAC7B,KAAK,EAAE,GAAG,GACT,OAAO,CAAC,OAAO,CAAC,CAuClB;AAQD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;OAEG;IACH,aAAa,CAAC,EAAE,cAAc,CAAC;IAE/B;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAE3C;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;CACxC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,GACxD,oBAAyB,GAC1B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CA+NlC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"http.test.d.ts","sourceRoot":"","sources":["../../src/sig/http.test.ts"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC"}
|
@@ -11,7 +11,6 @@ export declare function validateCryptoKey(key: dntShim.CryptoKey, type?: "public
|
|
11
11
|
/**
|
12
12
|
* Generates a key pair which is appropriate for Fedify.
|
13
13
|
* @returns The generated key pair.
|
14
|
-
* @since 0.3.0
|
15
14
|
*/
|
16
15
|
export declare function generateCryptoKeyPair(): Promise<dntShim.CryptoKeyPair>;
|
17
16
|
/**
|
@@ -20,7 +19,6 @@ export declare function generateCryptoKeyPair(): Promise<dntShim.CryptoKeyPair>;
|
|
20
19
|
* @returns The exported key in JWK format. The key is suitable for
|
21
20
|
* serialization and storage.
|
22
21
|
* @throws {TypeError} If the key is invalid or unsupported.
|
23
|
-
* @since 0.3.0
|
24
22
|
*/
|
25
23
|
export declare function exportJwk(key: dntShim.CryptoKey): Promise<dntShim.JsonWebKey>;
|
26
24
|
/**
|
@@ -29,7 +27,6 @@ export declare function exportJwk(key: dntShim.CryptoKey): Promise<dntShim.JsonW
|
|
29
27
|
* @param type Which type of key to import, either `"public"`" or `"private"`".
|
30
28
|
* @returns The imported key.
|
31
29
|
* @throws {TypeError} If the key is invalid or unsupported.
|
32
|
-
* @since 0.3.0
|
33
30
|
*/
|
34
31
|
export declare function importJwk(jwk: dntShim.JsonWebKey, type: "public" | "private"): Promise<dntShim.CryptoKey>;
|
35
32
|
//# sourceMappingURL=key.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"key.d.ts","sourceRoot":"","sources":["../../src/sig/key.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAE5C,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,OAAO,CAAC,SAAS,EACtB,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,GAC1B,IAAI,CAqBN;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAWtE;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAGnF;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,OAAO,CAAC,UAAU,EACvB,IAAI,EAAE,QAAQ,GAAG,SAAS,GACzB,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAU5B"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"key.test.d.ts","sourceRoot":"","sources":["../../src/sig/key.test.ts"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC"}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
/**
|
2
|
+
* HTTP Signatures implementation.
|
3
|
+
*
|
4
|
+
* @module
|
5
|
+
*/
|
6
|
+
export { signRequest, verifyRequest, type VerifyRequestOptions, } from "./http.js";
|
7
|
+
export { exportJwk, generateCryptoKeyPair, importJwk } from "./key.js";
|
8
|
+
export { doesActorOwnKey, type DoesActorOwnKeyOptions, getKeyOwner, type GetKeyOwnerOptions, } from "./owner.js";
|
9
|
+
//# sourceMappingURL=mod.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/sig/mod.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,WAAW,EACX,aAAa,EACb,KAAK,oBAAoB,GAC1B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACvE,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,EAC3B,WAAW,EACX,KAAK,kBAAkB,GACxB,MAAM,YAAY,CAAC"}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
import { type DocumentLoader } from "../runtime/docloader.js";
|
3
|
+
import { type Actor } from "../vocab/actor.js";
|
4
|
+
import { type Activity, CryptographicKey } from "../vocab/vocab.js";
|
5
|
+
export { exportJwk, generateCryptoKeyPair, importJwk } from "./key.js";
|
6
|
+
/**
|
7
|
+
* Options for {@link doesActorOwnKey}.
|
8
|
+
*/
|
9
|
+
export interface DoesActorOwnKeyOptions {
|
10
|
+
/**
|
11
|
+
* The document loader to use for fetching the actor.
|
12
|
+
*/
|
13
|
+
documentLoader?: DocumentLoader;
|
14
|
+
/**
|
15
|
+
* The context loader to use for JSON-LD context retrieval.
|
16
|
+
*/
|
17
|
+
contextLoader?: DocumentLoader;
|
18
|
+
}
|
19
|
+
/**
|
20
|
+
* Checks if the actor of the given activity owns the specified key.
|
21
|
+
* @param activity The activity to check.
|
22
|
+
* @param key The public key to check.
|
23
|
+
* @param options Options for checking the key ownership.
|
24
|
+
* @returns Whether the actor is the owner of the key.
|
25
|
+
*/
|
26
|
+
export declare function doesActorOwnKey(activity: Activity, key: CryptographicKey, options: DoesActorOwnKeyOptions): Promise<boolean>;
|
27
|
+
/**
|
28
|
+
* Options for {@link getKeyOwner}.
|
29
|
+
*/
|
30
|
+
export interface GetKeyOwnerOptions {
|
31
|
+
/**
|
32
|
+
* The document loader to use for fetching the key and its owner.
|
33
|
+
*/
|
34
|
+
documentLoader?: DocumentLoader;
|
35
|
+
/**
|
36
|
+
* The context loader to use for JSON-LD context retrieval.
|
37
|
+
*/
|
38
|
+
contextLoader?: DocumentLoader;
|
39
|
+
}
|
40
|
+
/**
|
41
|
+
* Gets the actor that owns the specified key. Returns `null` if the key has no
|
42
|
+
* known owner.
|
43
|
+
*
|
44
|
+
* @param keyId The ID of the key to check, or the key itself.
|
45
|
+
* @param options Options for getting the key owner.
|
46
|
+
* @returns The actor that owns the key, or `null` if the key has no known
|
47
|
+
* owner.
|
48
|
+
*/
|
49
|
+
export declare function getKeyOwner(keyId: URL | CryptographicKey, options: GetKeyOwnerOptions): Promise<Actor | null>;
|
50
|
+
//# sourceMappingURL=owner.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"owner.d.ts","sourceRoot":"","sources":["../../src/sig/owner.ts"],"names":[],"mappings":";AAAA,OAAO,EACL,KAAK,cAAc,EAEpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,KAAK,KAAK,EAAW,MAAM,mBAAmB,CAAC;AACxD,OAAO,EACL,KAAK,QAAQ,EACb,gBAAgB,EAEjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;OAEG;IACH,aAAa,CAAC,EAAE,cAAc,CAAC;CAChC;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,OAAO,CAAC,CAUlB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;OAEG;IACH,aAAa,CAAC,EAAE,cAAc,CAAC;CAChC;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,GAAG,GAAG,gBAAgB,EAC7B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAgDvB"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"owner.test.d.ts","sourceRoot":"","sources":["../../src/sig/owner.test.ts"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"key.d.ts","sourceRoot":"","sources":["../../src/httpsig/key.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAE5C,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,OAAO,CAAC,SAAS,EACtB,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,GAC1B,IAAI,CAqBN;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAWtE;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAGnF;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,OAAO,CAAC,UAAU,EACvB,IAAI,EAAE,QAAQ,GAAG,SAAS,GACzB,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAU5B"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"key.test.d.ts","sourceRoot":"","sources":["../../src/httpsig/key.test.ts"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC"}
|