Search code examples
c++cryptographyblockchainsolanaed25519

Verify Phantom signature in C++ server


I'm building a online game with a Phantom wallet login. My server is written in C++ and I want to make the signature verification there. The connection between client and server is a socket connection sending JSON.

For the client side, I went through the Phantom documentation. I retrieved the public key as a string and the signature as a uint8array, example values:

  • public key: "26qv4GCcx98RihuK3c4T6ozB3J7L6VwCuFVc7Ta2A3Uo"
  • signature: [141,47,223,197,8,57,72,178,113,62,233,50,47,234,39,143,169,82,59,190,214,185,25,227,94,68,209,118,231,120,66,224,241,241,168,128,56,63,80,41,219,202,17,191,214,185,91,178,55,126,194,152,157,173,248,212,89,126,128,157,168,119,244,6]

I found that Solana uses ED25519 signature, and I also found this website that implements the algorithm. And after trying multiple different entries to sign a message, I realized that the signature always contains characters that can be displayed. Therefore my first question is, why are there invalid characters (unable to be displayed) in my signature ? Example with the above signature: "�/���9H�q>�2/�'��R;�ֹ��^D�v�xB�����8?P)����ֹ[�7~�����Y~���w��".

Concerning the server side, I found some libraries to verify the signature:

But after multiple attempts, I could not find any valid set (message, public key and signature) that succeed the verification method int crypto_sign_open(byte *m,word64 *mlen,const byte *sm,word64 n,const byte *pk)

Therefore, my big question is, how do I verify this signature ? I did not find a proper example verifying a Phantom signature, especially in another language than Javascript.

Thank you in advance for your help!


Solution

  • I finally succeed verifying this signature. My first mistake was that, for ED25519 signature, the public key has to be 32 bytes. However, the Phantom public key contains 44 bytes. I found a post for which one of the answers says that the 44 bytes public key needs to be decoded in base 58 that gives us a 32 bytes key.

    Secondly, in the server, the method to use to verify the signature was not the right one. Indeed the right one is: int crypto_sign_verify_detached(const unsigned char *sig, const unsigned char *m, unsigned long long mlen, const unsigned char *pk). The method is described here.

    With these two changes, the verification works perfectly!