fix(noter): implement server-side wallet signature verification#52
Conversation
Replace the TODO comment in connectWallet with actual verification using verifyPersonalMessageSignature from @mysten/sui/verify. Also fix a double base64 encoding bug in wallet-client.ts where signPersonalMessage was typed as returning Uint8Array but Slush wallet standard (v0.15+) returns a base64 string — Buffer.from(str) without encoding treats the string as UTF-8, producing garbled bytes that always fail scheme validation on the server.
Aaron1924
left a comment
There was a problem hiding this comment.
looks good, and it confirms the new server-side verification path is working as expected.
I just have one remaining question before approving: is replay protection intentionally out of scope for this PR? The server now verifies that the signature matches the submitted message and address, but the message is still client-generated, so a previously captured {message, signature} pair could still be replayed to create a new session unless we move to a server-issued one-time challenge/nonce flow.
If that’s planned as follow-up work, I’m happy to treat this PR as a meaningful incremental security improvement.
Yes, replay protection was intentionally out of scope here; the changes needed (new DB table, new endpoint, frontend flow changes across multiple components) . Raised it as a follow-up: #53 |
Description
The connectWallet handler previously contained a TODO for server-side signature verification and trusted the client-provided signature.
While running the Noter application locally, I encountered consistent signature verification failures ("Unsupported signature scheme"), which led to identifying an encoding issue in the wallet client as well as the missing server-side verification.
This PR addresses both by implementing proper verification using @mysten/sui/verify and fixing the signature encoding bug in the client.
Changes
apps/noter/package/feature/auth/api/route.tsverifyPersonalMessageSignatureapps/noter/package/feature/auth/lib/wallet-client.tsFix signature encoding bug:
signPersonalMessagewas typed as returningUint8Array, but Slush returns the signature as a base64 stringBuffer.from(str)without an encoding argument treats the input as UTF-8, double-encoding the signature0x41instead of0x00)"Unsupported signature scheme"on every callAdded handling for both string and
Uint8Arrayreturn typesTest Plan
Tested locally with Noter against testnet using a Slush wallet: