Skip to content

Commit e5e39e2

Browse files
committed
feat: 添加宽松 Base64 解码器以支持微信 EncodingAESKey 的兼容性
1 parent 8e9b41e commit e5e39e2

1 file changed

Lines changed: 15 additions & 2 deletions

File tree

src/crypto.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
2-
use base64::{Engine, engine::general_purpose::STANDARD as BASE64};
2+
use base64::{Engine, alphabet, engine::{GeneralPurpose, GeneralPurposeConfig, general_purpose::STANDARD as BASE64}};
33
use rand::Rng;
44
use sha1::{Digest, Sha1};
55

@@ -10,6 +10,15 @@ type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
1010

1111
const AES_BLOCK_SIZE: usize = 16;
1212

13+
/// 宽松 Base64 解码器(允许尾部 bits 不为 0)
14+
///
15+
/// 微信生成的 EncodingAESKey 可能在 Base64 尾部填充位不为 0,
16+
/// 标准解码器会拒绝,这里使用宽松模式兼容。
17+
const LENIENT_BASE64: GeneralPurpose = GeneralPurpose::new(
18+
&alphabet::STANDARD,
19+
GeneralPurposeConfig::new().with_decode_allow_trailing_bits(true),
20+
);
21+
1322
/// Verify the WeChat server callback signature.
1423
///
1524
/// WeChat sends `signature`, `timestamp`, and `nonce` as query parameters.
@@ -70,13 +79,17 @@ pub fn check_msg_signature(
7079
///
7180
/// EncodingAESKey is a 43-character Base64-encoded string.
7281
/// We need to append "=" to make it valid Base64, then decode to get 32 bytes.
82+
///
83+
/// Note: WeChat's EncodingAESKey may have non-zero trailing bits, so we use
84+
/// a lenient decoder that allows this.
7385
pub fn decode_aes_key(encoding_aes_key: &str) -> Result<[u8; 32]> {
7486
if encoding_aes_key.len() != 43 {
7587
return Err(WeChatError::InvalidAesKey);
7688
}
7789

7890
let padded = format!("{}=", encoding_aes_key);
79-
let decoded = BASE64
91+
// 使用宽松解码器,兼容微信可能生成的非标准 Base64
92+
let decoded = LENIENT_BASE64
8093
.decode(padded)
8194
.map_err(|_| WeChatError::InvalidAesKey)?;
8295

0 commit comments

Comments
 (0)