diff --git a/crypto/crypto.test.ts b/crypto/crypto.test.ts index d5acfd7..f6ef6c3 100644 --- a/crypto/crypto.test.ts +++ b/crypto/crypto.test.ts @@ -1,5 +1,6 @@ import { expect } from "@std/expect"; -import { BlahKeyPair } from "./mod.ts"; +import { BlahKeyPair, BlahPublicKey } from "./mod.ts"; +import z from "zod"; let keypair: BlahKeyPair; @@ -32,6 +33,38 @@ Deno.test("sign & verify payload", async () => { expect(verifiedPayload).toEqual(payload); }); +Deno.test("parse and verify payload", async () => { + const payloadSchema = z.object({ + foo: z.string(), + baz: z.number(), + }).strict(); + const payload = { foo: "bar", baz: 123 }; + const signedPayload = await keypair.signPayload(payload); + const { payload: verifiedPayload, key } = await BlahPublicKey + .parseAndVerifyPayload( + payloadSchema, + signedPayload, + ); + + expect(verifiedPayload).toEqual(payload); + expect(key.id).toBe(keypair.id); +}); + +Deno.test("parse and verify corrupted payload", async () => { + const payloadSchema = z.object({ + foo: z.string(), + baz: z.number(), + }).strict(); + const payload = { foo: "bar", baz: 123, qux: "quux" }; + const signedPayload = await keypair.signPayload(payload); + + expect(BlahPublicKey + .parseAndVerifyPayload( + payloadSchema, + signedPayload, + )).rejects.toMatch(/unrecognized/); +}); + Deno.test("sign & verify payload with wrong keypair", async () => { const keypair2 = await BlahKeyPair.generate(); const payload = { foo: "bar", baz: 123 }; diff --git a/crypto/publicKey.ts b/crypto/publicKey.ts index 7118110..c668850 100644 --- a/crypto/publicKey.ts +++ b/crypto/publicKey.ts @@ -1,5 +1,9 @@ +import type z from "zod"; import canonicalize from "./canonicalize.ts"; -import type { BlahSignedPayload } from "./signedPayload.ts"; +import { + type BlahSignedPayload, + blahSignedPayloadSchemaOf, +} from "./signedPayload.ts"; import { bufToHex, hexToBuf } from "./utils.ts"; export class BlahPublicKey { @@ -42,6 +46,15 @@ export class BlahPublicKey { return { payload: await key.verifyPayload(signedPayload), key }; } + static async parseAndVerifyPayload

( + schema: P, + signedPayload: unknown, + ): Promise<{ payload: P; key: BlahPublicKey }> { + const signedPayloadSchema = blahSignedPayloadSchemaOf(schema); + const parsed = signedPayloadSchema.parse(signedPayload); + return await BlahPublicKey.verifyPayload(parsed as BlahSignedPayload

); + } + async verifyPayload

(signedPayload: BlahSignedPayload

): Promise

{ const { sig, signee } = signedPayload; const signingKey = signee.act_key;