@fedify/fedify 0.9.0-dev.179 → 0.9.0-dev.181
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/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"}
|