I am able to sign a message on the client side using something like this:
const encodedMessage = new TextEncoder().encode("some message");
const signedMessage = await provider.signMessage(encodedMessage, "utf8");
Now I want to verify the signature on the back end side using Kotlin (or Java).
Problem:
Question: How can I verify a signature from the Phantom wallet using Java? Or generally how can I do that in any language? (I will port it to Java then).
The easiest way to do it in Java or Kotlin is using sol4k.
First, add it to your project (Gradle as an example):
implementation 'org.sol4k:sol4k:0.5.1'
Then call it from your Java code:
import org.sol4k.Base58;
import org.sol4k.PublicKey;
// ...
boolean verifySignature(String signature, String walletAddress) {
String message = "signing message";
byte[] messageBytes = message.getBytes();
PublicKey publicKey = new PublicKey(walletAddress);
byte[] signatureBytes = Base58.decode(signature);
return publicKey.verify(signatureBytes, messageBytes);
}
Here, signature
and walletAddress
are Base58 encoded strings.
Frontend example how to get wallet address and the signature (Phantom docs):
const provider = window.phantom.solana;
const encodedMessage = new TextEncoder().encode('signing message');
const signedMessage = await provider.signMessage(encodedMessage, "utf8");
const base58 = await import("bs58");
const walletAddress = provider.publicKey.toString();
const signature = base58.encode(signedMessage.signature);
Here is a blogpost on the subject.