rsa.SignPKCS1v15和VerifyPKCS1v15只接受哈希摘要而非原始请求体,需先用sha256.New()对标准化数据(method+path+timestamp+nonce+body hash)计算摘要,验签端必须完全复现该哈希过程,且公钥断言前须校验证书签名算法。

rsa.SignPKCS1v15 和 rsa.VerifyPKCS1v15 不能直接传原始请求体
这两个函数只接受哈希摘要,不是明文。直接把 req.Body 字节或 JSON 字符串喂给 rsa.SignPKCS1v15,会触发 crypto/rsa: message too long 或静默失败。
- 签名前必须显式计算哈希:用
sha256.New()写入标准化后的请求数据(method + path + timestamp + nonce + body hash),再取hash.Sum(nil) - 验签端必须复现**完全一致**的哈希过程:同一原始数据、同一哈希算法、同一拼接顺序、同一编码方式(如
url.PathEscape而非url.QueryEscape) - body 哈希必须基于原始字节流,不能用
c.ShouldBindJSON后的结构体——字段顺序、空格、换行差异会导致哈希不等
公钥类型断言失败:cert.PublicKey.(*rsa.PublicKey) 会 panic
从 *x509.Certificate 取出的 PublicKey 是 interface{},直接断言为 *rsa.PublicKey 在包路径不一致时(比如混用了不同模块的 crypto/rsa)会 panic,错误信息像 “interface conversion: interface {} is *rsa.PublicKey, not *rsa.PublicKey”。
- 安全写法是先检查证书签名算法:
if cert.SignatureAlgorithm != x509.SHA256WithRSA { return errors.New("not RSA cert") } - 再做断言:
pub, ok := cert.PublicKey.(*rsa.PublicKey); if !ok { return errors.New("public key is not RSA") } - 若从 PEM 解析公钥,用
x509.ParsePKIXPublicKey后同样要断言,且必须确认返回值不是*ecdsa.PublicKey等其他类型
HMAC 和 RSA 混用时,密钥和哈希参数极易错配
API 鉴权常同时用 HMAC 做内部服务通信、RSA 做客户端身份认证,但两套逻辑共享同一套签名拼接规则时,容易在哈希对象和密钥类型上栽跟头。
多Agent加密货币量化交易系统 — 基于TradingAgents多Agent框架+Binance执行层。支持:技术分析、消息分析、多Agent辩论、自动交易信号生成、Binance现货下单。适用场景:量化策略研究、自动交易Bot开发、加密货币组合分析。
-
hmac.New第二个参数必须是[]byte,不是string;rsa.SignPKCS1v15的opts参数里Hash字段必须是crypto.SHA256这类常量,不是sha256.New()实例 - 拼接字符串中 timestamp 若来自
time.Now().Unix(),服务端需校验 ±30s 误差,否则因时钟偏差导致验签失败 - nonce 必须单次使用、服务端记录已用列表或 Redis 过期键,否则重放攻击可绕过 RSA 验签
rsa.SignPSS 比 rsa.SignPKCS1v15 更适合新项目,但跨语言兼容性要测
rsa.SignPSS 使用概率填充,抗选择明文攻击,同一消息多次签名结果不同,安全性优于 PKCS#1 v1.5。但它对 opts 中的 SaltLength 和 Hash 更敏感,且部分旧版 Python/Java SDK 默认不支持 PSS。
立即学习“go语言免费学习笔记(深入)”;
- 推荐初始化 opts:
&rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthAuto, Hash: crypto.SHA256} - 验签时
rsa.VerifyPSS的第三个参数(哈希摘要长度)必须等于crypto.SHA256.Size(),不能硬编码 32 - 上线前务必用真实客户端(如 Node.js 的
crypto.createVerify或 Python 的pyca/cryptography)跑通端到端验签
crypto.ErrVerification 不告诉你哪一环错了——它可能是哈希没重置、timestamp 多了个空格、公钥解析成 ECDSA 却调了 RSA 验签函数,或是 base64 解码截断了最后两个字符。排查得从签名原文的每一个字节开始比对。

















