1pub mod crypto_config;
51pub mod encrypt;
52pub mod encrypt_trait;
53pub mod error;
54pub mod hash;
55pub mod hash_trait;
56pub mod key_derivation;
57pub mod key_derivation_trait;
58pub mod sign;
59pub mod sign_trait;
60
61pub use crypto_config::*;
63pub use ed25519_dalek::{Signature, SigningKey, VerifyingKey};
64pub use encrypt::{Aes256GcmSivEncryptor, Ascon128Encryptor, EncryptionKeyManager, XChaCha20Poly1305Encryptor};
65pub use encrypt_trait::EncryptionAlgorithm;
66pub use error::CryptoError;
67pub use hash_trait::HashFunction;
68pub use key_derivation::{Argon2KeyDerivation, Pbkdf2KeyDerivation};
69pub use key_derivation_trait::KeyDerivationFunction;
70use serde_json::Value;
72pub use sign::{Ed25519Signer, SigningKeyManager};
73pub use sign_trait::SignatureAlgorithm;
74use tracing::{debug, trace};
75
76pub async fn hash_data(data: &Value) -> Result<String, CryptoError> {
78 trace!("Hashing data using global config");
79 let config = get_global_crypto_config().await?;
80 let result = match config.hash_algorithm {
81 HashAlgorithmChoice::Blake3 => crate::hash::Blake3Hasher::hash_data(data),
82 };
83 if let Ok(ref hash) = result {
84 debug!("Data hashed successfully: {}", hash);
85 }
86 result
87}
88
89pub async fn sign_hash(hash: &str, private_key: &SigningKey) -> Result<String, CryptoError> {
91 trace!("Signing hash using global config");
92 let config = get_global_crypto_config().await?;
93 let result = match config.signature_algorithm {
94 SignatureAlgorithmChoice::Ed25519 => Ed25519Signer::sign_hash(hash, private_key),
95 };
96 if let Ok(ref sig) = result {
97 debug!("Hash signed successfully: {}", sig);
98 }
99 result
100}
101
102pub async fn verify_signature(hash: &str, signature: &str, public_key: &VerifyingKey) -> Result<bool, CryptoError> {
104 trace!("Verifying signature using global config");
105 let config = get_global_crypto_config().await?;
106 let result = match config.signature_algorithm {
107 SignatureAlgorithmChoice::Ed25519 => Ed25519Signer::verify_signature(hash, signature, public_key),
108 };
109 debug!("Signature verification result: {:?}", result);
110 result
111}
112
113pub async fn encrypt_data(data: &[u8], key: &[u8; 32]) -> Result<String, CryptoError> {
115 trace!(
116 "Encrypting data using global config, data length: {}",
117 data.len()
118 );
119 let config = get_global_crypto_config().await?;
120 let result = match config.encryption_algorithm {
121 EncryptionAlgorithmChoice::XChaCha20Poly1305 => XChaCha20Poly1305Encryptor::encrypt_data(data, key),
122 EncryptionAlgorithmChoice::Aes256GcmSiv => Aes256GcmSivEncryptor::encrypt_data(data, key),
123 EncryptionAlgorithmChoice::Ascon128 => Ascon128Encryptor::encrypt_data(data, key),
124 };
125 if let Ok(ref encrypted) = result {
126 debug!(
127 "Data encrypted successfully, encrypted length: {}",
128 encrypted.len()
129 );
130 }
131 result
132}
133
134pub async fn decrypt_data(encrypted_data: &str, key: &[u8; 32]) -> Result<Vec<u8>, CryptoError> {
136 trace!(
137 "Decrypting data using global config, encrypted length: {}",
138 encrypted_data.len()
139 );
140 let config = get_global_crypto_config().await?;
141 let result = match config.encryption_algorithm {
142 EncryptionAlgorithmChoice::XChaCha20Poly1305 => XChaCha20Poly1305Encryptor::decrypt_data(encrypted_data, key),
143 EncryptionAlgorithmChoice::Aes256GcmSiv => Aes256GcmSivEncryptor::decrypt_data(encrypted_data, key),
144 EncryptionAlgorithmChoice::Ascon128 => Ascon128Encryptor::decrypt_data(encrypted_data, key),
145 };
146 if let Ok(ref decrypted) = result {
147 debug!(
148 "Data decrypted successfully, plaintext length: {}",
149 decrypted.len()
150 );
151 }
152 result
153}
154
155pub async fn derive_key_from_passphrase(passphrase: &str) -> Result<(Vec<u8>, [u8; 32]), CryptoError> {
158 trace!("Deriving key from passphrase using global config");
159 let config = get_global_crypto_config().await?;
160 let result = match config.key_derivation_algorithm {
161 KeyDerivationAlgorithmChoice::Argon2id => Argon2KeyDerivation::derive_key_from_passphrase(passphrase),
162 KeyDerivationAlgorithmChoice::Pbkdf2 => Pbkdf2KeyDerivation::derive_key_from_passphrase(passphrase),
163 };
164 if result.is_ok() {
165 debug!("Key derivation completed successfully");
166 }
167 result
168}
169
170pub async fn derive_key_from_passphrase_with_salt(passphrase: &str, salt: &[u8]) -> Result<[u8; 32], CryptoError> {
173 trace!("Deriving key from passphrase with salt using global config");
174 let config = get_global_crypto_config().await?;
175 let result = match config.key_derivation_algorithm {
176 KeyDerivationAlgorithmChoice::Argon2id => {
177 Argon2KeyDerivation::derive_key_from_passphrase_with_salt(passphrase, salt)
178 },
179 KeyDerivationAlgorithmChoice::Pbkdf2 => {
180 Pbkdf2KeyDerivation::derive_key_from_passphrase_with_salt(passphrase, salt)
181 },
182 };
183 if result.is_ok() {
184 debug!("Key derivation with salt completed successfully");
185 }
186 result
187}
188
189#[cfg(test)]
190mod tests {
191 use tracing_subscriber;
192
193 use super::*;
194
195 fn init_logging() {
196 let _ = tracing_subscriber::fmt()
197 .with_max_level(tracing::Level::TRACE)
198 .try_init();
199 }
200
201 #[tokio::test]
202 async fn test_hash_data() {
203 init_logging();
204 let data = serde_json::json!({"key": "value", "number": 42});
205 let hash = hash_data(&data).await.unwrap();
206 assert_eq!(hash.len(), 64);
207 let hash2 = hash_data(&data).await.unwrap();
208 assert_eq!(hash, hash2);
209 }
210
211 #[tokio::test]
212 #[serial_test::serial]
213 async fn test_set_global_crypto_config_already_set() {
214 init_logging();
215 reset_global_crypto_config_for_tests().await;
216 let config = CryptoConfig {
217 hash_algorithm: HashAlgorithmChoice::Blake3,
218 signature_algorithm: SignatureAlgorithmChoice::Ed25519,
219 encryption_algorithm: EncryptionAlgorithmChoice::Aes256GcmSiv, key_derivation_algorithm: KeyDerivationAlgorithmChoice::Argon2id,
221 };
222
223 let result1 = set_global_crypto_config(config.clone()).await;
225 assert!(result1.is_ok());
226
227 let result2 = set_global_crypto_config(config).await;
229 assert!(result2.is_ok());
230 }
231
232 #[tokio::test]
233 #[serial_test::serial]
234 async fn test_aes256gcm_siv_encryption() {
235 init_logging();
236 reset_global_crypto_config_for_tests().await;
237 let config = CryptoConfig {
238 hash_algorithm: HashAlgorithmChoice::Blake3,
239 signature_algorithm: SignatureAlgorithmChoice::Ed25519,
240 encryption_algorithm: EncryptionAlgorithmChoice::Aes256GcmSiv,
241 key_derivation_algorithm: KeyDerivationAlgorithmChoice::Argon2id,
242 };
243 set_global_crypto_config(config).await.unwrap();
244
245 let key = [0u8; 32];
246 let test_data = b"test data";
247 let encrypted = encrypt_data(test_data, &key).await.unwrap();
248 let decrypted = decrypt_data(&encrypted, &key).await.unwrap();
250 assert_eq!(test_data, decrypted.as_slice());
251 }
252
253 #[tokio::test]
254 #[serial_test::serial]
255 async fn test_ascon128_encryption() {
256 init_logging();
257 reset_global_crypto_config_for_tests().await;
258 let config = CryptoConfig {
259 hash_algorithm: HashAlgorithmChoice::Blake3,
260 signature_algorithm: SignatureAlgorithmChoice::Ed25519,
261 encryption_algorithm: EncryptionAlgorithmChoice::Ascon128,
262 key_derivation_algorithm: KeyDerivationAlgorithmChoice::Argon2id,
263 };
264 set_global_crypto_config(config).await.unwrap();
265
266 let key = [0u8; 32];
267 let test_data = b"test data";
268 let encrypted = encrypt_data(test_data, &key).await.unwrap();
269 let decrypted = decrypt_data(&encrypted, &key).await.unwrap();
271 assert_eq!(test_data, decrypted.as_slice());
272 }
273
274 #[tokio::test]
275 #[serial_test::serial]
276 async fn test_pbkdf2_key_derivation() {
277 init_logging();
278 reset_global_crypto_config_for_tests().await;
279 let config = CryptoConfig {
280 hash_algorithm: HashAlgorithmChoice::Blake3,
281 signature_algorithm: SignatureAlgorithmChoice::Ed25519,
282 encryption_algorithm: EncryptionAlgorithmChoice::XChaCha20Poly1305,
283 key_derivation_algorithm: KeyDerivationAlgorithmChoice::Pbkdf2,
284 };
285 let _ = set_global_crypto_config(config).await; let derived = derive_key_from_passphrase("test passphrase").await.unwrap();
288 assert_eq!(derived.1.len(), 32);
289 assert_eq!(derived.0.len(), 32);
290 }
291
292 #[tokio::test]
293 async fn test_sign_and_verify_hash() {
294 init_logging();
295 let data = serde_json::json!({"key": "value"});
296 let hash = hash_data(&data).await.unwrap();
297 assert_eq!(hash.len(), 64);
298
299 let key_bytes = [0u8; 32];
300 let key = SigningKey::from_bytes(&key_bytes);
301 let signature = sign_hash(&hash, &key).await.unwrap();
302
303 let public_key = key.verifying_key();
304 let verified = verify_signature(&hash, &signature, &public_key)
305 .await
306 .unwrap();
307 assert!(verified);
308
309 let invalid_verified = verify_signature("wrong_hash", &signature, &public_key)
311 .await
312 .unwrap();
313 assert!(!invalid_verified);
314
315 let hex_error = verify_signature(&hash, "invalid", &public_key).await;
317 assert!(hex_error.is_err());
318 }
319
320 #[tokio::test]
321 #[serial_test::serial]
322 async fn test_decrypt_corrupted_data() {
323 init_logging();
324 reset_global_crypto_config_for_tests().await;
325 let config = CryptoConfig {
326 hash_algorithm: HashAlgorithmChoice::Blake3,
327 signature_algorithm: SignatureAlgorithmChoice::Ed25519,
328 encryption_algorithm: EncryptionAlgorithmChoice::XChaCha20Poly1305,
329 key_derivation_algorithm: KeyDerivationAlgorithmChoice::Argon2id,
330 };
331 let _ = set_global_crypto_config(config).await;
332
333 let key = [0u8; 32];
334 let test_data = b"test data";
335 let encrypted = encrypt_data(test_data, &key).await.unwrap();
336
337 let mut corrupted = encrypted.clone();
339 if let Some(last) = corrupted.chars().last() {
340 let new_last = if last == 'a' { 'b' } else { 'a' };
341 corrupted = corrupted[.. encrypted.len() - 1].to_string() + &new_last.to_string();
342 }
343
344 let result = decrypt_data(&corrupted, &key).await;
345 assert!(result.is_err());
346 }
348
349 #[tokio::test]
350 async fn test_verify_signature_invalid_hex() {
351 init_logging();
352 let data = serde_json::json!({"key": "value"});
353 let hash = hash_data(&data).await.unwrap();
354
355 let key_bytes = [0u8; 32];
356 let key = SigningKey::from_bytes(&key_bytes);
357
358 let result = verify_signature(&hash, "invalid_hex", &key.verifying_key()).await;
360 assert!(result.is_err());
361 }
363
364 #[tokio::test]
365 async fn test_verify_signature_wrong_signature() {
366 init_logging();
367 let data = serde_json::json!({"key": "value"});
368 let hash = hash_data(&data).await.unwrap();
369
370 let key_bytes = [0u8; 32];
371 let key = SigningKey::from_bytes(&key_bytes);
372 let signature = sign_hash(&hash, &key).await.unwrap();
373
374 let wrong_key_bytes = [1u8; 32];
375 let wrong_key = SigningKey::from_bytes(&wrong_key_bytes);
376
377 let result = verify_signature(&hash, &signature, &wrong_key.verifying_key()).await;
378 assert!(matches!(result, Ok(false)));
379 }
381
382 #[tokio::test]
383 #[serial_test::serial]
384 async fn test_derive_key_from_passphrase_with_empty_passphrase() {
385 init_logging();
386 reset_global_crypto_config_for_tests().await;
387 let config = CryptoConfig {
388 hash_algorithm: HashAlgorithmChoice::Blake3,
389 signature_algorithm: SignatureAlgorithmChoice::Ed25519,
390 encryption_algorithm: EncryptionAlgorithmChoice::XChaCha20Poly1305,
391 key_derivation_algorithm: KeyDerivationAlgorithmChoice::Argon2id,
392 };
393 set_global_crypto_config(config).await.unwrap();
394
395 let passphrase = "";
396 let salt = b"1234567890123456"; let result = derive_key_from_passphrase_with_salt(passphrase, salt).await;
399 assert!(result.is_ok());
401 }
402
403 #[tokio::test]
404 #[serial_test::serial]
405 async fn test_decrypt_short_ciphertext() {
406 init_logging();
407 reset_global_crypto_config_for_tests().await;
408 let config = CryptoConfig {
409 hash_algorithm: HashAlgorithmChoice::Blake3,
410 signature_algorithm: SignatureAlgorithmChoice::Ed25519,
411 encryption_algorithm: EncryptionAlgorithmChoice::XChaCha20Poly1305,
412 key_derivation_algorithm: KeyDerivationAlgorithmChoice::Argon2id,
413 };
414 let _ = set_global_crypto_config(config).await;
415
416 let key = [0u8; 32];
417 let short_ciphertext = "short";
418
419 let result = decrypt_data(short_ciphertext, &key).await;
420 assert!(result.is_err());
421 }
423}