1use ed25519_dalek::SigningKey;
2use rand::rngs::OsRng;
3use rand::RngCore;
4use chacha20poly1305::{XChaCha20Poly1305, KeyInit, AeadCore};
5use chacha20poly1305::aead::Aead;
6use chacha20poly1305::XNonce;
7
8#[derive(Clone, Debug)]
9pub struct KeyPair {
10 pub public_key: Vec<u8>,
11 pub private_key: Vec<u8>,
12}
13
14impl KeyPair {
15 pub fn generate() -> Self {
16 let mut secret_bytes = [0u8; 32];
17 OsRng.fill_bytes(&mut secret_bytes);
18 let signing_key = SigningKey::from_bytes(&secret_bytes);
19 let verifying_key = signing_key.verifying_key();
20
21 KeyPair {
22 public_key: verifying_key.to_bytes().to_vec(),
23 private_key: signing_key.to_bytes().to_vec(),
24 }
25 }
26}
27
28pub fn encrypt_payload(data: &[u8], key: &[u8; 32]) -> (Vec<u8>, [u8; 24]) {
29 let cipher = XChaCha20Poly1305::new_from_slice(key).unwrap();
30 let nonce = XChaCha20Poly1305::generate_nonce(&mut OsRng);
31 let mut nonce_bytes = [0u8; 24];
32 nonce_bytes.copy_from_slice(nonce.as_slice());
33
34 let ciphertext = cipher.encrypt(&nonce, data).unwrap();
35
36 (ciphertext, nonce_bytes)
37}
38
39pub fn decrypt_payload(ciphertext: &[u8], key: &[u8; 32], nonce: &[u8; 24]) -> Result<Vec<u8>, String> {
40 let cipher = XChaCha20Poly1305::new_from_slice(key).unwrap();
41 let nonce = XNonce::from_slice(nonce);
42
43 let plaintext = cipher.decrypt(nonce, ciphertext)
44 .map_err(|e| format!("Decryption failed: {}", e))?;
45
46 Ok(plaintext)
47}
48
49pub fn hash_data(data: &[u8]) -> Vec<u8> {
50 use sha2::{Sha256, Digest};
51 Sha256::new().chain_update(data).finalize().to_vec()
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn test_keypair_generate() {
60 let kp1 = KeyPair::generate();
61 let kp2 = KeyPair::generate();
62 assert_eq!(kp1.public_key.len(), 32);
63 assert_eq!(kp1.private_key.len(), 32);
64 assert_ne!(kp1.public_key, kp2.public_key);
65 }
66
67 #[test]
68 fn test_encrypt_decrypt() {
69 let key = [1u8; 32];
70 let data = b"Hello, VCL!";
71
72 let (ciphertext, nonce) = encrypt_payload(data, &key);
73 let decrypted = decrypt_payload(&ciphertext, &key, &nonce).unwrap();
74
75 assert_eq!(data, decrypted.as_slice());
76 }
77
78 #[test]
79 fn test_decrypt_wrong_key_fails() {
80 let key1 = [1u8; 32];
81 let key2 = [2u8; 32];
82 let data = b"Secret message";
83
84 let (ciphertext, nonce) = encrypt_payload(data, &key1);
85 let result = decrypt_payload(&ciphertext, &key2, &nonce);
86
87 assert!(result.is_err());
88 }
89
90 #[test]
91 fn test_hash_data() {
92 let h1 = hash_data(b"test");
93 let h2 = hash_data(b"test");
94 let h3 = hash_data(b"Test");
95
96 assert_eq!(h1, h2);
97 assert_ne!(h1, h3);
98 assert_eq!(h1.len(), 32);
99 }
100}