1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import assert from "node:assert/strict";
import { createPublicKey, verify } from "node:crypto";
import { test } from "node:test";
import { createDidKey, didkeyCall, GET_SERVICE_AUTH, ingressHost, SIGN, serviceAud } from "./index.js";
const N = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551n;
const key = await createDidKey();
const pub = createPublicKey({ key: { kty: "EC", crv: "P-256", x: key.jwk.x, y: key.jwk.y }, format: "jwk" });
const verifies = (data, sig) => verify("sha256", data, { key: pub, dsaEncoding: "ieee-p1363" }, sig);
const unb64url = (text) => Buffer.from(text, "base64url");
test("the did is a P-256 did:key, stable for the same JWK", async () => {
assert.match(key.did, /^did:key:zDn[1-9A-HJ-NP-Za-km-z]{44,46}$/);
assert.equal((await createDidKey(key.jwk)).did, key.did);
assert.notEqual((await createDidKey()).did, key.did);
assert.equal(ingressHost(key.did), `${key.did.replaceAll(":", "-").toLowerCase()}.xrpc.fedproxy.com`);
});
test("sign is sha256 ECDSA, compact and low-S", async () => {
for (let i = 0; i < 20; i++) {
const data = crypto.getRandomValues(new Uint8Array(64));
const sig = await key.sign(data);
assert.equal(sig.length, 64);
assert.ok(BigInt(`0x${Buffer.from(sig.subarray(32)).toString("hex")}`) <= N / 2n);
assert.ok(verifies(data, sig));
}
});
test("serviceAuth is an ES256 JWT the did:key signs for itself, exp capped at an hour", async () => {
const now = Math.floor(Date.now() / 1000);
const token = await key.serviceAuth({ aud: "did:web:xrpc.fedproxy.com", lxm: "com.fedproxy.temp.xrpc.subscribe", exp: now + 99999 });
const [header, payload, sig] = token.split(".");
assert.deepEqual(JSON.parse(unb64url(header)), { typ: "JWT", alg: "ES256" });
const claims = JSON.parse(unb64url(payload));
assert.equal(claims.iss, key.did);
assert.equal(claims.aud, "did:web:xrpc.fedproxy.com");
assert.equal(claims.lxm, "com.fedproxy.temp.xrpc.subscribe");
assert.ok(claims.exp <= now + 3601 && claims.exp >= now + 3599);
assert.ok(verifies(Buffer.from(`${header}.${payload}`), unb64url(sig)));
const short = JSON.parse(unb64url((await key.serviceAuth({ aud: "did:web:x", lxm: "a.b.c" })).split(".")[1]));
assert.ok(short.exp - short.iat === 300);
});
test("didkeyCall answers the pseudo-calls, signs service calls it is told to, passes the rest on", async () => {
const fetched = [];
const passed = [];
const call = didkeyCall(key, async (nsid, request) => (passed.push([nsid, request]), { inner: true }), {
services: ["https://xrpc.fedproxy.com"],
fetch: async (url, init) => (fetched.push([url, init]), new Response(JSON.stringify({ nonce: "bm9uY2U=" }))),
});
const auth = await call(GET_SERVICE_AUTH, { params: { aud: "did:web:xrpc.fedproxy.com", lxm: "com.fedproxy.temp.xrpc.getRegistrationNonce" } });
assert.equal(auth.did, key.did);
assert.equal(JSON.parse(unb64url(auth.token.split(".")[1])).lxm, "com.fedproxy.temp.xrpc.getRegistrationNonce");
await assert.rejects(call(GET_SERVICE_AUTH, { params: { aud: "nope", lxm: "a.b.c" } }), /aud/);
const nonce = crypto.getRandomValues(new Uint8Array(64));
const signed = await call(SIGN, { input: { data: Buffer.from(nonce).toString("base64") } });
assert.equal(signed.did, key.did);
assert.ok(verifies(nonce, Buffer.from(signed.signature, "base64")));
await assert.rejects(call(SIGN, { input: {} }), /data/);
// only the relay nonce shape: a module must not get a JWS signing input signed (its own JWT)
const jws = (await key.serviceAuth({ aud: "did:web:x", lxm: "a.b.c" })).split(".").slice(0, 2).join(".");
for (const bad of [Buffer.from("hello"), Buffer.from(jws), Buffer.from(jws.slice(0, 64)), Buffer.concat([nonce, nonce])])
await assert.rejects(call(SIGN, { input: { data: bad.toString("base64") } }), /only a relay nonce/);
assert.deepEqual(await call("com.fedproxy.temp.xrpc.getRegistrationNonce", { service: "https://xrpc.fedproxy.com", input: { key: key.did, signatures: [] } }), { nonce: "bm9uY2U=" });
const [url, init] = fetched[0];
assert.equal(url, "https://xrpc.fedproxy.com/xrpc/com.fedproxy.temp.xrpc.getRegistrationNonce");
assert.equal(init.method, "POST");
assert.deepEqual(JSON.parse(init.body), { key: key.did, signatures: [] });
const claims = JSON.parse(unb64url(init.headers.authorization.slice("Bearer ".length).split(".")[1]));
assert.deepEqual([claims.iss, claims.aud, claims.lxm], [key.did, "did:web:xrpc.fedproxy.com", "com.fedproxy.temp.xrpc.getRegistrationNonce"]);
// Subscriptions, other services and plain calls are the inner call's.
await call("com.fedproxy.temp.xrpc.subscribe", { service: "https://xrpc.fedproxy.com", subscribe: true, params: {} });
await call("a.b.c", { service: "https://elsewhere.example" });
await call("com.atproto.repo.describeRepo", { service: "did:plc:abc", params: { repo: "did:plc:abc" } });
assert.deepEqual(passed.map(([nsid]) => nsid), ["com.fedproxy.temp.xrpc.subscribe", "a.b.c", "com.atproto.repo.describeRepo"]);
assert.equal(fetched.length, 1);
});
test("serviceAud: did:web of the service host, a port as %3A<port> (the Rust host's service_aud)", () => {
assert.equal(serviceAud("https://svc.example/x"), "did:web:svc.example");
assert.equal(serviceAud("https://svc.example:443/"), "did:web:svc.example");
assert.equal(serviceAud("https://svc.example:8443/xrpc"), "did:web:svc.example%3A8443");
});
test("didkeyCall: a subscribe with serviceAuth to a listed service carries a token the did:key signs", async () => {
const key = await createDidKey();
const seen = [];
const inner = async (nsid, request) => (seen.push(request), { async *[Symbol.asyncIterator]() { yield "message"; }, close() {} });
const call = didkeyCall(key, inner, { services: ["https://xrpc.fedproxy.com"] });
const NSID = "com.fedproxy.temp.xrpc.subscribe";
const first = await call(NSID, { subscribe: true, service: "https://xrpc.fedproxy.com", params: { did: key.did }, serviceAuth: { param: "service_auth" } });
// one serving instance per did:key: another relay subscribe is refused while this one is open
await assert.rejects(call(NSID, { subscribe: true, service: "https://xrpc.fedproxy.com", serviceAuth: {} }), /already serving in another run/);
first.close();
const second = await call(NSID, { subscribe: true, service: "https://xrpc.fedproxy.com", serviceAuth: {} });
for await (const message of second) assert.equal(message, "message"); // the stream ending gives the lease back too
(await call(NSID, { subscribe: true, service: "https://xrpc.fedproxy.com", serviceAuth: {} })).close();
await call(NSID, { subscribe: true, service: "https://other.example", serviceAuth: {} });
const claims = (jwt) => JSON.parse(Buffer.from(jwt.split(".")[1], "base64url"));
assert.equal(seen[0].serviceAuth, undefined);
assert.deepEqual({ ...claims(seen[0].params.service_auth), exp: 0, iat: 0, jti: 0 }, { ...claims(seen[0].params.service_auth), iss: key.did, aud: "did:web:xrpc.fedproxy.com", lxm: NSID, exp: 0, iat: 0, jti: 0 });
assert.match(seen[1].headers.authorization, /^Bearer ey/);
assert.deepEqual(seen[3].serviceAuth, {}, "not a listed service: left for the host (the session's token)");
const browser = didkeyCall(key, inner, { services: ["https://xrpc.fedproxy.com"], canHeader: false });
await assert.rejects(browser(NSID, { subscribe: true, service: "https://xrpc.fedproxy.com", serviceAuth: {} }), /browsers cannot set WebSocket headers/);
});