You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python discord_interactions库verify_key函数报错:签名伪造或损坏

Discord机器人交互端点签名验证失败问题排查

问题描述

我编写了用于Discord机器人交互端点验证的代码片段:

def interactions_view(request):
    if request.method == 'POST':
        try:
            raw_body = request.body
            signature = request.headers.get('X-Signature-Ed25519')
            timestamp = request.headers.get('X-Signature-Timestamp')

            logger.debug(f"Signature (type: {type(signature)}): {signature}")
            logger.debug(f"Timestamp (type: {type(timestamp)}): {timestamp}")
            logger.debug(f"Raw Body (type: {type(raw_body)}): {raw_body}")

            if not signature or not timestamp:
                return JsonResponse({'Error': 'Missing signature or timestamp'}, status=400)

            try:
                verify_key(raw_body, signature, timestamp, PUBLIC_KEY)
            except Exception as e:
                logger.error(f"Signature verification failed: {e}")
                return JsonResponse({'Error': 'Signature verification failed'}, status=401)

. . .

服务器日志返回错误:

2024-06-29T22:14:41.227687+00:00 app[web.1]: Signature was forged or corrupt

且Discord发送POST请求时始终返回200 OK状态码。我尝试对密钥进行编解码转换,出现“could not concatenate str object to bytes”等不同错误,也进行了日志调试,但问题仍未解决,请问哪里遗漏或操作有误?

问题排查与解决方法

1. 签名参数编解码不符合要求

Discord Ed25519签名验证要求所有核心参数必须是字节类型,且需按正确格式处理:

  • signature:从十六进制字符串解码为字节(bytes.fromhex(signature))
  • timestamp:转换为UTF-8编码的字节(timestamp.encode('utf-8'))
  • PUBLIC_KEY:从十六进制字符串解码为字节(bytes.fromhex(PUBLIC_KEY))
  • 验证时需将timestamp字节与raw_body字节拼接,作为待验证的消息体,而非单独传入两个参数

修正后的验证逻辑示例(基于PyNaCl库):

from nacl.signing import VerifyKey
from nacl.exceptions import BadSignatureError

# 处理参数编码
signature_bytes = bytes.fromhex(signature)
timestamp_bytes = timestamp.encode('utf-8')
public_key_bytes = bytes.fromhex(PUBLIC_KEY)
# 拼接timestamp和原始请求体
message = timestamp_bytes + raw_body

try:
    verify_key = VerifyKey(public_key_bytes)
    verify_key.verify(message, signature_bytes)
except BadSignatureError:
    logger.error("Signature verification failed: forged or corrupt")
    return JsonResponse({'Error': 'Signature verification failed'}, status=401)

2. 请求体被篡改

  • 必须确保raw_body是请求的原始未修改字节,禁止使用框架解析后的请求体(如Django的request.POST),这类解析会改变原始字节结构,导致签名验证失败
  • 检查是否有中间件对请求体进行了解码、修改或压缩,这类操作会破坏签名验证的原始数据

3. 状态码返回逻辑异常

Discord要求验证失败时返回401 Unauthorized,若Discord收到200,说明代码存在未覆盖的分支:

  • 检查外层try-except是否捕获了验证异常并返回了默认200
  • 确认验证失败分支的return语句被正确执行,没有被其他逻辑覆盖

4. 公钥配置错误

  • 确认PUBLIC_KEY是Discord开发者平台中机器人的公钥(十六进制字符串),无多余空格、换行或字符
  • 禁止直接传入字符串类型的公钥,必须转换为字节类型后再用于验证

内容的提问来源于stack exchange,提问作者GwenSt11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 20:52:37