11use 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 } } ;
33use rand:: Rng ;
44use sha1:: { Digest , Sha1 } ;
55
@@ -10,6 +10,15 @@ type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
1010
1111const 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.
7385pub 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