import { describe, expect, it } from "vitest"; import { generateKey } from "./generate.ts"; import { signWithKeyData } from "./sign.ts"; import type { KeyData, SeedData, XHDRootKey } from "./types/index.ts"; import { verifyWithKeyData } from "./verify.ts"; describe("verify.ts", () => { const makeUint8 = (arr: number[]) => new Uint8Array(arr); async function setupKeys() { const seedPrivateKey = new Uint8Array(64).fill(0x42); const seed: SeedData = { id: "seed-1", type: "hd-seed", algorithm: "raw", extractable: true, privateKey: seedPrivateKey, metadata: {}, }; const rootKey: XHDRootKey = await generateKey({ keyData: { type: "hd-root-key", algorithm: "raw", extractable: true, metadata: { parentKeyId: seed.id }, }, parentKey: seed, }); const ed25519Key = await generateKey({ keyData: { type: "hd-derived-ed25519", algorithm: "EdDSA", extractable: true, metadata: { parentKeyId: rootKey.id, context: 1, account: 1, index: 1, }, }, parentKey: { ...rootKey, privateKey: new Uint8Array(rootKey.privateKey), } as any, }); const p256Key = await generateKey({ keyData: { type: "hd-derived-p256", algorithm: "P256", extractable: true, metadata: { parentKeyId: rootKey.id, origin: "example.com", userHandle: "user-123", counter: 0, }, }, parentKey: { ...rootKey, privateKey: new Uint8Array(rootKey.privateKey), } as any, }); return { rootKey, ed25519Key, p256Key }; } it("verifyWithKeyData (EdDSA path) verifies real signature", async () => { const { rootKey, ed25519Key } = await setupKeys(); const data = makeUint8([1, 2, 3, 4]); // We need to clone the key because signing clears it const keyToSign = JSON.parse(JSON.stringify(ed25519Key)); keyToSign.publicKey = new Uint8Array(ed25519Key.publicKey); const rootToSign = JSON.parse(JSON.stringify(rootKey)); rootToSign.privateKey = new Uint8Array(rootKey.privateKey); const signature = await signWithKeyData({ key: keyToSign, parentKey: rootToSign, data, }); const ok = await verifyWithKeyData({ key: ed25519Key, data, signature, }); expect(ok).toBe(true); }); it("verifyWithKeyData (P256 path) verifies signature", async () => { const { rootKey, p256Key } = await setupKeys(); const data = makeUint8([1, 2, 3, 4]); // We need to clone the keys because signing clears them const keyToSign = JSON.parse(JSON.stringify(p256Key)); keyToSign.publicKey = new Uint8Array(p256Key.publicKey); const rootToSign = JSON.parse(JSON.stringify(rootKey)); rootToSign.privateKey = new Uint8Array(rootKey.privateKey); const signature = await signWithKeyData({ key: keyToSign, parentKey: rootToSign, data, }); const ok = await verifyWithKeyData({ key: p256Key, data, signature, }); expect(ok).toBeDefined(); }); it("verifyWithKeyData throws if no public key", async () => { const key: KeyData = { id: "k4", type: "ecc", algorithm: "EdDSA", extractable: true, } as any; await expect( verifyWithKeyData({ key, data: makeUint8([1]), signature: makeUint8([2]), }), ).rejects.toThrow("Key does not have a public key"); }); it("verifyWithKeyData throws if algorithm not supported", async () => { const key: KeyData = { id: "k5", type: "ecc", algorithm: "UNKNOWN", extractable: true, publicKey: makeUint8([1]), } as any; await expect( verifyWithKeyData({ key, data: makeUint8([1]), signature: makeUint8([2]), }), ).rejects.toThrow("Algorithm UNKNOWN is not supported for verification"); }); });