1use 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
18pub 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
30pub fn md5_hash(input: &str) -> String {
32 format!("{:x}", md5::compute(input))
33}
34
35pub fn base64_encode(input: &[u8]) -> String {
37 use base64::Engine;
38 base64::engine::general_purpose::STANDARD.encode(input)
39}
40
41pub 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
48pub 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}