Solana Phantom钱包Python后端签名验证失败求助
Phantom钱包签名验证报错:ValueError: expected a sequence of length 32 (got 44) 解决方法
问题场景
尝试通过Phantom钱包实现用户认证,但Django后端无法完成签名验证,运行时抛出错误:ValueError: expected a sequence of length 32 (got 44)
前端代码
const response = await solana.connect(); console.log("wallet account ", response.publicKey.toString()); setWalletKey(response.publicKey.toString()); const message = new TextEncoder().encode("hello"); const signature = await solana.signMessage(message); const resp_backend = await Axios.post("http://localhost:8000/api/auth/",{message:"hello", pub_key:response.publicKey.toString(), signature:bs58.encode(signature.signature)})
后端代码(原错误版本)
from nacl.signing import VerifyKey import base58 from solders.pubkey import Pubkey def verify_signature_for_user(public_key, signature, message): pub_key = Pubkey(public_key) print(len(public_key)) msg = bytes(message, encoding='utf-8') signed = bytes(signature, 'utf-8') result = VerifyKey(pub_key).verify(smessage=msg, signature=base58.b58decode(signed)) return result
报错信息
ValueError: expected a sequence of length 32 (got 44)
问题原因
- 公钥传递错误:
VerifyKey需要的是32字节的原始公钥字节序列,但代码直接传入了solders.Pubkey对象,而Pubkey的字符串形式是44长度的base58编码值,导致验证时字节长度不匹配。 - 签名处理冗余:前端已经用
bs58.encode处理了签名,后端无需先转成bytes再解码,直接对签名字符串解码即可。
修正后的后端代码
from nacl.signing import VerifyKey import base58 from solders.pubkey import Pubkey def verify_signature_for_user(public_key, signature, message): # 将base58格式的公钥字符串转为Pubkey对象,再提取32字节原始公钥 pub_key = Pubkey(public_key) raw_pubkey = pub_key.to_bytes() msg = bytes(message, encoding='utf-8') # 直接解码前端传来的base58签名字符串 decoded_signature = base58.b58decode(signature) # 使用原始公钥初始化VerifyKey并验证 result = VerifyKey(raw_pubkey).verify(msg, decoded_signature) return result
验证说明
修正后,raw_pubkey是标准的32字节公钥,decoded_signature是64字节的签名数据,完全符合nacl.signing.VerifyKey.verify的参数要求,能够正确完成Phantom钱包签名的验证。
内容的提问来源于stack exchange,提问作者Nika110
相关产品推荐
相关产品推荐

