From 534ec58ce019c51452966c0a5e0a10d436e63f8b Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer <ry@xmtp.com> Date: Fri, 22 Nov 2024 17:44:14 -0600 Subject: [PATCH] Refactor signature verification --- sdks/node-sdk/package.json | 1 + sdks/node-sdk/src/Client.ts | 31 +++++++++++++++++--------- sdks/node-sdk/test/Client.test.ts | 36 +++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/sdks/node-sdk/package.json b/sdks/node-sdk/package.json index ce6b39156..7e3fce5c3 100644 --- a/sdks/node-sdk/package.json +++ b/sdks/node-sdk/package.json @@ -69,6 +69,7 @@ "rollup-plugin-filesize": "^10.0.0", "rollup-plugin-tsconfig-paths": "^1.5.2", "typescript": "^5.6.3", + "uint8array-extras": "^1.4.0", "uuid": "^11.0.3", "viem": "^2.13.6", "vite": "^5.4.11", diff --git a/sdks/node-sdk/src/Client.ts b/sdks/node-sdk/src/Client.ts index 05550b6cf..2bd7eff06 100644 --- a/sdks/node-sdk/src/Client.ts +++ b/sdks/node-sdk/src/Client.ts @@ -17,6 +17,7 @@ import { GroupMessageKind, LogLevel, SignatureRequestType, + verifySignedWithPublicKey as verifySignedWithPublicKeyBinding, type Consent, type ConsentEntityType, type LogOptions, @@ -410,21 +411,31 @@ export class Client { signatureText: string, signatureBytes: Uint8Array, ) { - this.#innerClient.verifySignedWithInstallationKey( - signatureText, - signatureBytes, - ); + try { + this.#innerClient.verifySignedWithInstallationKey( + signatureText, + signatureBytes, + ); + return true; + } catch { + return false; + } } - verifySignedWithPublicKey( + static verifySignedWithPublicKey( signatureText: string, signatureBytes: Uint8Array, publicKey: Uint8Array, ) { - this.#innerClient.verifySignedWithPublicKey( - signatureText, - signatureBytes, - publicKey, - ); + try { + verifySignedWithPublicKeyBinding( + signatureText, + signatureBytes, + publicKey, + ); + return true; + } catch { + return false; + } } } diff --git a/sdks/node-sdk/test/Client.test.ts b/sdks/node-sdk/test/Client.test.ts index 5beff1d26..59e742f24 100644 --- a/sdks/node-sdk/test/Client.test.ts +++ b/sdks/node-sdk/test/Client.test.ts @@ -1,4 +1,5 @@ import { ConsentEntityType, ConsentState } from "@xmtp/node-bindings"; +import { uint8ArrayToHex } from "uint8array-extras"; import { v4 } from "uuid"; import { describe, expect, it } from "vitest"; import { Client } from "@/Client"; @@ -195,4 +196,39 @@ describe("Client", () => { await client2.getConsentState(ConsentEntityType.GroupId, group2!.id), ).toBe(ConsentState.Denied); }); + + it("should verify signatures", async () => { + const user = createUser(); + const client = await createRegisteredClient(user); + const signatureText = "gm1"; + const signature = client.signWithInstallationKey(signatureText); + const verified = client.verifySignedWithInstallationKey( + signatureText, + signature, + ); + expect(verified).toBe(true); + const verified2 = Client.verifySignedWithPublicKey( + signatureText, + signature, + client.installationIdBytes, + ); + expect(verified2).toBe(true); + + const signatureText2 = new Uint8Array(32).fill(1); + const signature2 = client.signWithInstallationKey( + uint8ArrayToHex(signatureText2), + ); + const verified3 = Client.verifySignedWithPublicKey( + uint8ArrayToHex(signatureText2), + signature2, + client.installationIdBytes, + ); + expect(verified3).toBe(true); + const verified4 = Client.verifySignedWithPublicKey( + uint8ArrayToHex(signatureText2), + signature, + client.installationIdBytes, + ); + expect(verified4).toBe(false); + }); });