wechat_api_rs/
crypto.rs

1//! WeChat cryptographic utilities
2
3use thiserror::Error;
4use sha1::{Sha1, Digest};
5
6#[derive(Error, Debug)]
7pub enum CryptoError {
8    #[error("Invalid signature")]
9    InvalidSignature,
10    #[error("Decryption failed: {0}")]
11    DecryptionFailed(String),
12    #[error("Encryption failed: {0}")]
13    EncryptionFailed(String),
14}
15
16pub type Result<T> = std::result::Result<T, CryptoError>;
17
18/// Verify WeChat signature
19pub fn verify_signature(token: &str, timestamp: &str, nonce: &str, signature: &str) -> bool {
20    let mut params = vec![token, timestamp, nonce];
21    params.sort();
22    let content = params.join("");
23
24    let mut hasher = Sha1::new();
25    hasher.update(content.as_bytes());
26    let hash = format!("{:x}", hasher.finalize());
27    hash == signature
28}
29
30/// Generate MD5 hash
31pub fn md5_hash(input: &str) -> String {
32    format!("{:x}", md5::compute(input))
33}
34
35/// Base64 encode
36pub fn base64_encode(input: &[u8]) -> String {
37    use base64::Engine;
38    base64::engine::general_purpose::STANDARD.encode(input)
39}
40
41/// Base64 decode
42pub fn base64_decode(input: &str) -> Result<Vec<u8>> {
43    use base64::Engine;
44    base64::engine::general_purpose::STANDARD.decode(input)
45        .map_err(|e| CryptoError::DecryptionFailed(e.to_string()))
46}
47
48/// Generate signature for API calls
49pub fn generate_signature(params: &[(&str, &str)]) -> String {
50    let mut params: Vec<_> = params.iter().collect();
51    params.sort_by(|a, b| a.0.cmp(b.0));
52
53    let content: String = params
54        .iter()
55        .map(|(k, v)| format!("{}={}", k, v))
56        .collect::<Vec<_>>()
57        .join("&");
58
59    md5_hash(&content).to_uppercase()
60}