~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
68 lines · 2.4 KB Raw History
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/);
  });
});