Skip to main content

vcl_protocol/
crypto.rs

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