Skip to content

Commit 9d0149a

Browse files
committed
fix: 升级 go-pay/crypto 至 v0.0.3,修复回调解密 panic 隐患
微信 V3 回调报文中的 resource.nonce、resource.ciphertext 均来自外部 JSON,此前会被原样传给 aes.GCMDecrypt。nonce 长度不为 12 字节时, crypto/cipher 内部直接 panic,伪造的回调请求即可打挂商户进程。 DecryptPayCipherText 等解密方法与 VerifySignByPKMap 相互独立,验签 并非必经步骤,因此该路径无需任何凭证即可触达。 go-pay/crypto v0.0.3 将 aes/des 的非法 nonce、非法密文长度、iv 过短、 非法 PKCS 填充等原本 panic 的路径改为返回 error,函数签名与既有行为 均未变更。 同时补充 wechat/v3 回归测试,锁定畸形 nonce / 密文只返回 error。 release_note.md:cmbpay 与本次修复归入未发布的 v1.5.123,此前误写入 已随 37d526d 发布的 v1.5.122 段落。
1 parent fd4db2b commit 9d0149a

4 files changed

Lines changed: 32 additions & 4 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/go-pay/gopay
33
go 1.25.0
44

55
require (
6-
github.com/go-pay/crypto v0.0.2
6+
github.com/go-pay/crypto v0.0.3
77
github.com/go-pay/errgroup v0.0.3
88
github.com/go-pay/smap v0.0.2
99
github.com/go-pay/util v0.0.4

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
github.com/go-pay/crypto v0.0.2 h1:UDJ8RUuvf8X1rsnK7pqs3LDY8IqzohaWPu6d9YK9Pvo=
2-
github.com/go-pay/crypto v0.0.2/go.mod h1:41oEIvHMKbNcYlWUlRWtsnC6+ASgh7u29z0gJXe5bes=
1+
github.com/go-pay/crypto v0.0.3 h1:PDYO7OduTBSSAujF/OLqMRFlcqcebEmAYNRKeTi1rdk=
2+
github.com/go-pay/crypto v0.0.3/go.mod h1:41oEIvHMKbNcYlWUlRWtsnC6+ASgh7u29z0gJXe5bes=
33
github.com/go-pay/errgroup v0.0.3 h1:DB4s8e8oWYDyETKQ1y1riMJ7y29zE1uIsMCSjEOFSbU=
44
github.com/go-pay/errgroup v0.0.3/go.mod h1:0+4b8mvFMS71MIzsaC+gVvB4x37I93lRb2dqrwuU8x8=
55
github.com/go-pay/smap v0.0.2 h1:kKflYor5T5FgZltPFBMTFfjJvqYMHr5VnIFSEyhVTcA=

release_note.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## 版本号:v1.5.122
1+
## 版本号:v1.5.123
22

33
* 修改记录:
44
* 新增 招商银行聚合支付 SDK(cmbpay)。
@@ -20,6 +20,16 @@
2020
* `client.ParseNotify()` / `ParseNotifyValues()` / `ParseNotifyBytes()`,异步通知验签并结构化。
2121
* `client.NotifySuccessBody()` / `NotifyFailBody()`,生成商户应答报文(加签失败时返回 error)。
2222
* `(n *NotifyData).IsPaySuccess()`,判断是否支付成功(仅 `tradeState=S` 为 true)。
23+
* 修复 底层加解密的 panic 隐患(依赖 `github.com/go-pay/crypto` 升级至 v0.0.3)。
24+
* AES-GCM 的 nonce 长度非法时返回 error,不再 panic。微信 V3 回调报文中的
25+
`resource.nonce` 来自外部输入,此前长度不为 12 字节会打挂商户进程。
26+
* AES / DES 的 CBC、ECB 解密在密文长度非分组整数倍、iv 短于一个分组时返回 error,
27+
不再 panic。
28+
* PKCS5 / PKCS7 去填充对空数据、非法填充数不再越界 panic,原样返回。
29+
30+
## 版本号:v1.5.122
31+
32+
* 修改记录:
2333
* 新增 抖音支付 SDK。
2434
* 基础设施:
2535
* `douyin.NewClient()`,初始化抖音支付客户端。

wechat/v3/encrypt_decrypt_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,24 @@ bdz/NH6klplarq02xmXk6pwxd11bfq3AvckrUdjywiRfGw6C1+bO+w==
4646
-----END RSA PRIVATE KEY-----`
4747
)
4848

49+
// TestV3DecryptNotifyMalformedNonce 回调报文中的 nonce/ciphertext 均来自外部输入,
50+
// 长度非法时必须返回 error 而不是 panic,否则伪造的回调请求可以打挂商户进程。
51+
func TestV3DecryptNotifyMalformedNonce(t *testing.T) {
52+
apiV3Key := "Cj5xC9RXf0GFCKWeD9PyY1ZWLgionbvx"
53+
// 合法 AES-GCM nonce 为 12 字节,这里全部是非法长度。
54+
for _, nonce := range []string{"", "1", "123456", "0123456789abc"} {
55+
if _, err := V3DecryptPayNotifyCipherText("O9EOFzUdQESzEGqSo511CbQmt7ZlPuX/yg8n+agktdns0kFG2L0BCg==", nonce, "transaction", apiV3Key); err == nil {
56+
t.Errorf("nonce 长度 %d 时应返回错误", len(nonce))
57+
}
58+
}
59+
// 密文为非法 Base64 或长度不足一个 GCM tag 时同样只能返回错误。
60+
for _, ciphertext := range []string{"", "!!!not-base64!!!", "AAAA"} {
61+
if _, err := V3DecryptPayNotifyCipherText(ciphertext, "gopaynonce12", "transaction", apiV3Key); err == nil {
62+
t.Errorf("密文 %q 应返回错误", ciphertext)
63+
}
64+
}
65+
}
66+
4967
func TestV3EncryptTextAndV3DecryptText(t *testing.T) {
5068
text := "I love GoPay"
5169
cipherText, err := V3EncryptText(text, []byte(publicPKCS1))

0 commit comments

Comments
 (0)