Skip to content

fix(noter): implement server-side wallet signature verification#52

Merged
Aaron1924 merged 1 commit intoMystenLabs:devfrom
Ashwin-3cS:fix/noter-wallet-signature-verification
Mar 26, 2026
Merged

fix(noter): implement server-side wallet signature verification#52
Aaron1924 merged 1 commit intoMystenLabs:devfrom
Ashwin-3cS:fix/noter-wallet-signature-verification

Conversation

@Ashwin-3cS
Copy link
Copy Markdown
Contributor

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.ts

  • Replace TODO with verifyPersonalMessageSignature
  • Reject requests where the recovered signer address does not match the claimed address

apps/noter/package/feature/auth/lib/wallet-client.ts

  • Fix signature encoding bug:

    • signPersonalMessage was typed as returning Uint8Array, but Slush returns the signature as a base64 string
    • Buffer.from(str) without an encoding argument treats the input as UTF-8, double-encoding the signature
    • The server then decodes invalid bytes (scheme byte 0x41 instead of 0x00)
    • This causes "Unsupported signature scheme" on every call
  • Added handling for both string and Uint8Array return types


Test Plan

Tested locally with Noter against testnet using a Slush wallet:

  • Valid signature + correct address → session created (200)
  • Valid signature + tampered address → 401 "Signature does not match address"
Screenshot 2026-03-26 192506

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.
Copy link
Copy Markdown
Collaborator

@Aaron1924 Aaron1924 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@Ashwin-3cS
Copy link
Copy Markdown
Contributor Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants