1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use std::{
    fs::File,
    io::{Read, Write},
};

use aes_gcm_siv::{
    aead::{generic_array::GenericArray, Aead, Payload},
    Aes256GcmSiv, KeyInit,
};
use error::{AesError, Error};
use serde::{Deserialize, Serialize};

pub mod error;
pub mod stream;

/// Serializes a data structure into a Vec<u8> using CBOR format.
///
/// # Arguments
///
/// * `data` - A reference to the data to be serialized.
///
/// # Returns
///
/// * `Result<Vec<u8>, Error>` - The serialized data as a vector of bytes, or an error if serialization fails.
pub fn serialize<T: Serialize>(data: &T) -> Result<Vec<u8>, Error> {
    let cbor_data = serde_cbor::to_vec(data)?;
    Ok(cbor_data)
}

/// Deserializes a sequence of bytes into a data structure using CBOR format.
///
/// # Arguments
///
/// * `cbor_data` - A vector of bytes representing the serialized data.
///
/// # Returns
///
/// * `Result<T, Error>` - The deserialized data structure, or an error if deserialization fails.
pub fn deserialize<T: for<'a> Deserialize<'a>>(cbor_data: &Vec<u8>) -> Result<T, Error> {
    let data = serde_cbor::from_slice(&cbor_data)?;
    Ok(data)
}

/// Encrypts plaintext using AES-GCM-SIV algorithm.
///
/// # Arguments
///
/// * `key` - A reference to the 256-bit key for encryption.
/// * `nonce` - A reference to the 12-byte nonce.
/// * `plaintext` - A reference to the data to be encrypted.
/// * `associated_data` - A reference to the associated data.
///
/// # Returns
///
/// * `Result<Vec<u8>, Error>` - The encrypted data as a vector of bytes, or an error if encryption fails.
pub fn basic_encrypt(
    key: &[u8; 32],
    nonce: &[u8; 12],
    plaintext: &[u8],
    associated_data: &[u8],
) -> Result<Vec<u8>, Error> {
    let cipher = Aes256GcmSiv::new(GenericArray::from_slice(key));
    let nonce = GenericArray::from_slice(nonce);
    let payload = Payload { msg: plaintext, aad: associated_data };
    let ciphertext = cipher
        .encrypt(nonce, payload)
        .map_err(|_| Error::EcryptionError(AesError::Encrypt));

    ciphertext
}

/// Decrypts ciphertext using AES-GCM-SIV algorithm.
///
/// # Arguments
///
/// * `key` - A reference to the 256-bit key for decryption.
/// * `nonce` - A reference to the 12-byte nonce.
/// * `ciphertext` - A reference to the encrypted data.
/// * `associated_data` - A reference to the associated data.
///
/// # Returns
///
/// * `Result<Vec<u8>, Error>` - The decrypted data as a vector of bytes, or an error if decryption fails.
pub fn basic_decrypt(
    key: &[u8; 32],
    nonce: &[u8; 12],
    ciphertext: &[u8],
    associated_data: &[u8],
) -> Result<Vec<u8>, Error> {
    let cipher = Aes256GcmSiv::new(GenericArray::from_slice(key));
    let nonce = GenericArray::from_slice(nonce);
    let payload = Payload { msg: ciphertext, aad: associated_data };
    let plaintext = cipher
        .decrypt(nonce, payload)
        .map_err(|_| Error::EcryptionError(AesError::Decrypt));

    plaintext
}

/// Generates a random 256-bit key.
///
/// # Returns
///
/// * `[u8; 32]` - The generated key.
pub fn generate_key() -> [u8; 32] {
    let mut key = [0u8; 32];
    getrandom::getrandom(&mut key).expect("Error generating key");
    key
}

/// Saves a 256-bit key to a file.
///
/// # Arguments
///
/// * `key` - A reference to the 256-bit key to be saved.
/// * `file_path` - The path to the file where the key should be saved.
///
/// # Returns
///
/// * `std::io::Result<()>` - Returns `Ok(())` if successful, or an error if there was a problem saving the key.
pub fn save_key_to_file(key: &[u8; 32], file_path: &str) -> std::io::Result<()> {
    let mut file = File::create(file_path)?;
    file.write_all(key)?;
    Ok(())
}

/// Loads a 256-bit key from a file.
///
/// # Arguments
///
/// * `file_path` - The path to the file from which the key should be loaded.
///
/// # Returns
///
/// * `std::io::Result<[u8; 32]>` - The loaded key or an error if there was a problem loading the key.
pub fn load_key_from_file(file_path: &str) -> std::io::Result<[u8; 32]> {
    let mut file = File::open(file_path)?;
    let mut key = [0u8; 32];
    file.read_exact(&mut key)?;
    Ok(key)
}