无法为Four.meme钱包认证生成有效签名的技术求助
问题描述
尝试使用Four.meme的钱包认证系统登录时,持续收到"Signature for this request is not valid"错误。已尝试多种私钥签名方式,均无法生成API接受的签名,相关代码如下:
import requests from web3 import Web3, Account from eth_account.messages import encode_defunct # 配置 PRIVATE_KEY = "YOUR_PRIVATE_KEY" # 已隐藏私钥 WALLET_ADDRESS = Web3.to_checksum_address("0x8358494c81a35db01AfB1EEb93cBfe995B0cF057") web3 = Web3(Web3.HTTPProvider("https://bsc-dataseed.binance.org/")) # 创建会话 session = requests.Session() session.headers.update({ "Origin": "https://four.meme", "Referer": "https://four.meme/", "User-Agent": "Mozilla/5.0", "Content-Type": "application/json" }) # 获取nonce nonce_url = "https://four.meme/meme-api/v1/private/user/nonce/generate" nonce_payload = { "accountAddress": WALLET_ADDRESS, "verifyType": "LOGIN" } resp = session.post(nonce_url, json=nonce_payload) nonce = resp.json()["data"] # 签名消息 message = str(nonce) # 仅使用nonce字符串,无额外格式 message_encoded = encode_defunct(text=message) signed_msg = Account.from_key(PRIVATE_KEY).sign_message(message_encoded) signature = signed_msg.signature.hex() if not signature.startswith("0x"): signature = "0x" + signature # 尝试登录 login_url = "https://four.meme/meme-api/v1/private/user/login/dex" login_payload = { "region": "WEB", "langType": "EN", "loginIp": "", "inviteCode": "", "verifyInfo": { "address": WALLET_ADDRESS, "networkCode": "BSC", "signature": signature, "verifyType": "LOGIN" }, "walletName": "MetaMask" } login_resp = session.post(login_url, json=login_payload) print(login_resp.json()) # 返回 {"code": -1006, "msg": "Signature for this request is not valid"}
已尝试方案
- 不同消息格式:仅nonce字符串、格式化消息
"Login Four.Meme:\n\n123456"、十六进制编码nonce、UTF-8编码字节 - 不同签名方式:使用
encode_defunct()多参数、切换恢复ID格式(0/1 vs 27/28)、以太坊特定前缀的个人签名格式 - 手动签名验证:在浏览器用MetaMask手动签名消息,脚本中使用相同nonce和签名仍报错
- 恢复验证:确认签名可恢复出正确地址,签名为带0x前缀的65字节格式
- 直接复制浏览器成功签名,脚本使用仍被拒绝
环境
Python 3.10、web3.py 6.0.0、币安智能链(BSC)、MetaMask(浏览器对比测试)
问题咨询
当签名格式正确且可恢复出钱包地址时,仍收到"Signature for this request is not valid"错误的原因是什么?是否遗漏了Four.meme签名验证的特定要求?
可能的原因及解决方法
签名消息的平台自定义前缀
很多Web3平台会给签名消息添加专属前缀,而非单纯使用nonce。建议抓包浏览器中MetaMask弹出的签名提示文本,对比脚本中的消息是否完全一致。比如Four.meme可能要求消息格式为"Four.Meme Authentication: {nonce}"或包含其他固定内容,需严格匹配该格式。Nonce与会话绑定
部分平台的nonce会和请求会话(如Cookie)绑定,脚本中获取nonce和登录时需使用同一个requests.Session(),且需保留平台返回的Cookie。可在获取nonce后打印session.cookies,确认登录请求携带了相同的Cookie信息。恢复ID格式不匹配
web3.py v6返回的签名恢复ID为27/28格式,但有些平台期望0/1格式。可尝试转换格式:# 将恢复ID从27/28转为0/1 sig_hex = signature[2:] # 去掉0x前缀 sig_bytes = bytes.fromhex(sig_hex) # 替换最后一位恢复ID corrected_sig_bytes = sig_bytes[:64] + bytes([sig_bytes[64] - 27]) corrected_signature = "0x" + corrected_sig_bytes.hex()使用转换后的签名重新尝试登录。
请求参数或头信息缺失
检查浏览器登录请求的完整头信息,确认是否有X-CSRF-Token等自定义头未在脚本中设置。另外,loginIp字段可能需要填写真实IP,部分平台会验证IP一致性。BSC签名的特殊处理
尽管BSC兼容以太坊签名,但部分平台可能对哈希算法或编码有特殊要求。可尝试直接对nonce的哈希进行签名:# 直接对nonce的Keccak哈希签名 message_hash = web3.keccak(text=str(nonce)) signed_msg = Account.from_key(PRIVATE_KEY).signHash(message_hash) signature = signed_msg.signature.hex()
内容的提问来源于stack exchange,提问作者Baran Bingöl

