Skip to main content

wx_rust_common/util/crypto/
pkcs7_encoder.rs

1//! PKCS7 填充编码器。
2//!
3//! 对应 Java `me.chanjar.weixin.common.util.crypto.PKCS7Encoder`(微信消息加解密专用)。
4
5/// 提供基于 PKCS7 算法的加解密填充(微信 32 字节块)。
6pub struct Pkcs7Encoder;
7
8impl Pkcs7Encoder {
9    /// 块大小(字节):微信使用 32
10    const BLOCK_SIZE: usize = 32;
11
12    /// 获得对明文进行补位填充的字节。
13    ///
14    /// # 参数
15    /// - `count`:需要进行填充补位操作的明文字节个数
16    ///
17    /// # 返回
18    /// 补齐用的字节数组
19    pub fn encode(count: usize) -> Vec<u8> {
20        // 计算需要填充的位数
21        let amount_to_pad = Self::BLOCK_SIZE - (count % Self::BLOCK_SIZE);
22        // 补位所用的字符(数值转 ASCII 字符)
23        let pad_chr = (amount_to_pad as u8) as char;
24        let mut out = Vec::with_capacity(amount_to_pad);
25        for _ in 0..amount_to_pad {
26            out.push(pad_chr as u8);
27        }
28        out
29    }
30
31    /// 删除解密后明文的补位字符。
32    ///
33    /// # 参数
34    /// - `decrypted`:解密后的明文
35    ///
36    /// # 返回
37    /// 删除补位字符后的明文
38    pub fn decode(decrypted: &[u8]) -> Vec<u8> {
39        if decrypted.is_empty() {
40            return decrypted.to_vec();
41        }
42        let pad = decrypted[decrypted.len() - 1] as usize;
43        // 非法填充长度(不在 1..=32 范围)时视为无填充
44        let pad = if (1..=32).contains(&pad) { pad } else { 0 };
45        let len = decrypted.len().saturating_sub(pad);
46        decrypted[..len].to_vec()
47    }
48}