chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
import { describe, expect, it } from 'vitest';
import { decapsulate, encapsulate, uncompressedKey } from '../src/kem.js';
import { SpaceMacError } from '../src/mac.js';
import { makeKemKey } from './helpers/kem.js';
import { fromHex, toHex, vectors } from './helpers/vectors.js';
describe('KEM', () => {
it('derives the reference shared secret from its key share', async () => {
const secret = await decapsulate(
fromHex(vectors.kem.authorPrivateKeyHex),
vectors.kem.keyShare,
);
expect(toHex(secret)).toBe(vectors.kem.sharedSecretHex);
});
it('derives the same secret on both sides', async () => {
const author = await makeKemKey();
const { keyShare, sharedSecret } = await encapsulate(author.didKey);
expect(sharedSecret).toHaveLength(32);
expect(await decapsulate(author.privateKey, keyShare)).toEqual(
sharedSecret,
);
});
it('uses a fresh key share per encapsulation', async () => {
const { didKey } = await makeKemKey();
const a = await encapsulate(didKey);
const b = await encapsulate(didKey);
expect(a.keyShare).not.toBe(b.keyShare);
expect(a.sharedSecret).not.toEqual(b.sharedSecret);
});
it('derives a different secret under a different author key', async () => {
const author = await makeKemKey();
const other = await makeKemKey();
const { keyShare, sharedSecret } = await encapsulate(author.didKey);
expect(await decapsulate(other.privateKey, keyShare)).not.toEqual(
sharedSecret,
);
});
it('decompresses both parities of y', async () => {
for (let i = 0; i < 8; i++) {
const { didKey } = await makeKemKey();
const key = uncompressedKey(didKey);
expect(key).toHaveLength(65);
expect(key[0]).toBe(4);
}
});
it('rejects a key that is not P-256', async () => {
const k256 = 'did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme';
await expect(encapsulate(k256)).rejects.toThrow(SpaceMacError);
const author = await makeKemKey();
await expect(decapsulate(author.privateKey, k256)).rejects.toThrow(
SpaceMacError,
);
await expect(
decapsulate(author.privateKey, 'did:key:nope'),
).rejects.toThrow(SpaceMacError);
});
it('refuses a private key of the wrong length', async () => {
await expect(
decapsulate(new Uint8Array(31), vectors.kem.keyShare),
).rejects.toThrow(/32 bytes/);
});
});