use sha2::{Sha256, Digest}; use hmac::{Hmac, Mac}; use base64::{Engine as _, engine::general_purpose}; use crate::error::{CommonResult as Result, CommonError as Error}; /// Hash a string using SHA-256 pub fn hash_sha256(input: &str) -> String { let mut hasher = Sha256::new(); hasher.update(input.as_bytes()); format!("{:x}", hasher.finalize()) } /// Generate HMAC signature pub fn generate_hmac_signature(data: &str, secret: &str) -> Result { let mut mac = Hmac::::new_from_slice(secret.as_bytes()) .map_err(|_| Error::InternalError("Invalid HMAC secret".to_string()))?; mac.update(data.as_bytes()); let result = mac.finalize(); let signature = general_purpose::STANDARD.encode(result.into_bytes()); Ok(signature) } /// Verify HMAC signature pub fn verify_hmac_signature(data: &str, signature: &str, secret: &str) -> Result { let expected = generate_hmac_signature(data, secret)?; Ok(signature == expected) } /// Encode data to base64 pub fn encode_base64(data: &[u8]) -> String { general_purpose::STANDARD.encode(data) } /// Decode base64 data pub fn decode_base64(data: &str) -> Result> { general_purpose::STANDARD.decode(data) .map_err(|e| Error::SerializationError(format!("Base64 decode error: {}", e))) } /// Convert bytes to hex string pub fn bytes_to_hex(bytes: &[u8]) -> String { bytes.iter().map(|b| format!("{:02x}", b)).collect() } /// Convert hex string to bytes pub fn hex_to_bytes(hex: &str) -> Result> { if hex.len() % 2 != 0 { return Err(Error::ValidationError("Hex string must have even length".to_string())); } let mut bytes = Vec::new(); for chunk in hex.as_bytes().chunks(2) { let byte_str = std::str::from_utf8(chunk) .map_err(|_| Error::ValidationError("Invalid hex string".to_string()))?; let byte = u8::from_str_radix(byte_str, 16) .map_err(|_| Error::ValidationError("Invalid hex character".to_string()))?; bytes.push(byte); } Ok(bytes) }