Skip to content

Instantly share code, notes, and snippets.

@lunaspeed
Created September 10, 2025 03:01
Show Gist options
  • Save lunaspeed/221669a0ca2c369f6654c9d7302f8cc2 to your computer and use it in GitHub Desktop.
Save lunaspeed/221669a0ca2c369f6654c9d7302f8cc2 to your computer and use it in GitHub Desktop.
Public Key derivation from address for ed25519 and secp256k1
//For ed25519 (Solana):
import org.bitcoinj.core.Base58;
String solAddress = "5Fh..."; // base58
byte[] ed25519PubKey = Base58.decode(solAddress); // 32 bytes
//For secp256k1 (EVM):
import org.web3j.crypto.Sign;
import org.web3j.crypto.Keys;
import org.web3j.utils.Numeric;
import java.math.BigInteger;
String message = "get-pubkey";
// signature is 65-byte hex from personal_sign (0x...): r(32) + s(32) + v(1)
String sigHex = "0x...";
byte[] sig = Numeric.hexStringToByteArray(sigHex);
byte v = sig[64];
if (v < 27) v += 27;
byte[] r = java.util.Arrays.copyOfRange(sig, 0, 32);
byte[] s = java.util.Arrays.copyOfRange(sig, 32, 64);
Sign.SignatureData sd = new Sign.SignatureData(v, r, s);
// Ethereum Signed Message hash
byte[] msgHash = Sign.getEthereumMessageHash(message.getBytes(java.nio.charset.StandardCharsets.UTF_8));
BigInteger pubKeyBI = Sign.signedPrefixedMessageToKey(message.getBytes(java.nio.charset.StandardCharsets.UTF_8), sd);
// Or: BigInteger pubKeyBI = Sign.signedMessageToKey(msgHash, sd);
String uncompressedPubKeyHex = "0x" + Keys.getPublicKey(pubKeyBI); // 64-byte hex (no 0x04)
// If you need 65-byte uncompressed (0x04 + X + Y):
String uncompressed65 = "0x04" + Keys.getPublicKey(pubKeyBI);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment