import { beforeAll, describe, expect, it } from "@suaveplan/testing/runner"; import { sodiumReady } from "../../init/init.js"; import { ristretto255 } from "./ristretto255.js"; describe("ristretto255", () => { beforeAll(async () => { await sodiumReady(); }, 30_000); it("random() produces 32-byte group element", { timeout: 30_000, }, async () => { const p = await ristretto255.random(); expect(p.length).toBe(32); }); it("random() produces different elements each call", { timeout: 30_000, }, async () => { const p = await ristretto255.random(); const q = await ristretto255.random(); expect(p).not.toEqual(q); }); it("fromHash() maps 64 bytes to a group element", { timeout: 30_000, }, async () => { const hash = new Uint8Array(64).fill(0x42); const point = await ristretto255.fromHash(hash); expect(point.length).toBe(32); }); it("add(p, q) is commutative: add(p,q) == add(q,p)", { timeout: 30_000, }, async () => { const p = await ristretto255.random(); const q = await ristretto255.random(); const pq = await ristretto255.add(p, q); const qp = await ristretto255.add(q, p); expect(pq).toEqual(qp); }); it("add then sub is identity", { timeout: 30_000 }, async () => { const p = await ristretto255.random(); const q = await ristretto255.random(); const sum = await ristretto255.add(p, q); const back = await ristretto255.sub(sum, q); expect(back).toEqual(p); }); it("mul scalar*point produces a 32-byte element", { timeout: 30_000, }, async () => { const p = await ristretto255.random(); // Use a small non-zero scalar const scalar = new Uint8Array(32); scalar[0] = 2; const result = await ristretto255.mul(scalar, p); expect(result.length).toBe(32); }); it("toBytes returns a copy of the point", { timeout: 30_000 }, async () => { const p = await ristretto255.random(); const bytes = await ristretto255.toBytes(p); expect(bytes).toEqual(p); // Mutation of result doesn't affect original bytes[0] ^= 0xff; expect(bytes).not.toEqual(p); }); it("fromBytes accepts a valid point", { timeout: 30_000 }, async () => { const p = await ristretto255.random(); const back = await ristretto255.fromBytes(p); expect(back).toEqual(p); }); it("fromBytes throws for invalid point", { timeout: 30_000 }, async () => { // High-bit patterns outside the ristretto255 field are not valid points const bad = new Uint8Array(32).fill(0xff); await expect(ristretto255.fromBytes(bad)).rejects.toThrow(RangeError); }); });