Something went wrong. Try again.
An AT Protocol Personal Data Server written in JavaScript pdsjs.dev
pds atproto
Something went wrong. Try again.
5.2 kB · 145 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146// Runs the reference implementation's verifier over artifacts pds.js produced.// Copied into the atproto worktree by scripts/space-reference/run.sh as a// scratch file; never committed there.
import { readFileSync } from 'node:fs';import { verifySignature } from '@atproto/crypto';import { describe, expect, it } from 'vitest';import { verifyRepoCarFull } from '../src/index.js';
const DIR = process.env.ARTIFACTS_DIR ?? '/tmp/pdsjs-conformance';const manifest = JSON.parse(readFileSync(`${DIR}/manifest.json`, 'utf8'));const car = new Uint8Array(readFileSync(`${DIR}/repo.car`));
const fromB64 = (s: string) => new Uint8Array(Buffer.from(s, 'base64'));
describe('reference verifies pds.js output', () => { it('accepts the getRepo CAR', async () => { // This single call checks: exactly two roots, the commit block leads, the // commit's signature and MAC verify, the index follows, the index's set // hash equals the commit's hash, and every record block matches its index // entry in order. If it passes, BLAKE3, LtHash, the ctx encoding, the MAC, // the signature and the canonical block ordering all agree. const verified = await verifyRepoCarFull([car], { space: manifest.space, author: manifest.author, didKey: manifest.userDidKey, });
expect(verified.commit.rev).toBe(manifest.rev); expect(verified.records).toHaveLength(manifest.recordCount);
const paths = verified.records.map((r) => `${r.collection}/${r.rkey}`); // Canonical DAG-CBOR key order: shortest first, then bytewise. expect(paths).toEqual([ 'com.e.p/x', 'com.example.post/aaa', 'com.example.post/bbb', 'com.example.reply/zz', ]);
// Records round-tripped through DAG-CBOR intact, nested values included. const reply = verified.records.find( (r) => r.collection === 'com.example.reply', ); expect(reply?.record).toEqual({ $type: 'com.example.reply', deep: { nested: [1, 2, 3] }, }); });
it('rejects the CAR when told the wrong author', async () => { // The author is bound into the signed ctx, so this must fail — otherwise // the test above would pass for the wrong reason. await expect( verifyRepoCarFull([car], { space: manifest.space, author: 'did:plc:someoneelse', didKey: manifest.userDidKey, }), ).rejects.toThrow(); });
it('rejects the CAR when told the wrong space', async () => { await expect( verifyRepoCarFull([car], { space: 'at://did:plc:conformauthority/space/com.example.forum/other', author: manifest.author, didKey: manifest.userDidKey, }), ).rejects.toThrow(); });
it('verifies the getLatestCommit JSON signature', async () => { // Rebuild the ctx the way the reference does and check our wire-format // commit against the user's key. const { commit } = manifest; const enc = new TextEncoder(); const parts = [ enc.encode(manifest.space), enc.encode(manifest.author), enc.encode(commit.rev), fromB64(commit.ikm.$bytes), ]; let size = 16; for (const p of parts) size += 2 + p.length; const ctx = new Uint8Array(size); ctx.set(enc.encode('atproto-space-v1')); let off = 16; for (const p of parts) { ctx[off++] = (p.length >>> 8) & 0xff; ctx[off++] = p.length & 0xff; ctx.set(p, off); off += p.length; }
const ok = await verifySignature( manifest.userDidKey, ctx, fromB64(commit.sig.$bytes), { jwtAlg: 'ES256' }, ); expect(ok).toBe(true); });});
describe('reference verifies pds.js tokens', () => { it('accepts the delegation token', async () => { const { verifySpaceToken } = await import('../src/index.js'); const { payload } = await verifySpaceToken( 'delegation', manifest.delegationToken, { getSigningKey: () => manifest.userDidKey, aud: manifest.delegationAud, sub: manifest.space, }, ); expect(payload.iss).toBe(manifest.author); expect(payload.sub).toBe(manifest.space); });
it('accepts the space credential', async () => { const { verifySpaceToken } = await import('../src/index.js'); const { payload, header } = await verifySpaceToken( 'credential', manifest.credential, { getSigningKey: () => manifest.authorityDidKey, sub: manifest.space }, ); expect(payload.iss).toBe(manifest.authority); // The key the holder proves possession of. The reference refuses to parse a // credential without it, so reaching this line is already half the check. expect(payload.cnf?.jkt).toBe(manifest.credentialJkt); // An authority hosted on a PDS signs with the account's own key. expect(header.kid).toBe('#atproto'); });
it('rejects a delegation token presented as a credential', async () => { const { verifySpaceToken } = await import('../src/index.js'); await expect( verifySpaceToken('credential', manifest.delegationToken, { getSigningKey: () => manifest.userDidKey, }), ).rejects.toThrow(); });});