deadbolt-crypto 0.1.1

Cryptography wrapper for deadbolt
Documentation
use std::error::Error;

use aes_gcm::{
    aead::{generic_array::GenericArray, Aead, KeyInit},
    aes::cipher::ArrayLength,
    Aes256Gcm, Nonce,
};

use chacha20::ChaCha8;
use chacha20::{
    cipher::{KeyIvInit, StreamCipher, StreamCipherSeek},
    ChaCha20,
};

use chacha20poly1305::ChaCha20Poly1305;
use rand::Rng;
use secrecy::{ExposeSecret, SecretVec};
pub struct Encryption {
    aes_cipher: Aes256Gcm,
    chacha_cipher: ChaCha20Poly1305,
}

pub struct EncryptionPayload {
    pub data: Vec<u8>,
    pub nonce: [u8; 12],
}

impl Encryption {
    pub fn new(master_key: &SecretVec<u8>) -> Encryption {
        Encryption {
            aes_cipher: Aes256Gcm::new(GenericArray::from_slice(master_key.expose_secret())),
            chacha_cipher: ChaCha20Poly1305::new(GenericArray::from_slice(
                master_key.expose_secret(),
            )),
        }
    }

    pub fn encrypt(
        &mut self,
        plaintext: Vec<u8>,
        algorithm: u8,
    ) -> Result<EncryptionPayload, Box<dyn Error>> {
        let mut nonce: [u8; 12] = [0; 12];
        let mut rng = rand::thread_rng();
        rng.fill(&mut nonce);

        match algorithm {
            1 => {
                let encryption_result = self
                    .aes_cipher
                    .encrypt(GenericArray::from_slice(&nonce), plaintext.as_ref());

                match encryption_result {
                    Ok(ciphertext) => Ok(EncryptionPayload {
                        data: ciphertext,
                        nonce,
                    }),
                    Err(e) => Err(e.to_string().into()),
                }
            }
            2 => {
                let encryption_result = self
                    .chacha_cipher
                    .encrypt(GenericArray::from_slice(&nonce), plaintext.as_ref());

                match encryption_result {
                    Ok(ciphertext) => Ok(EncryptionPayload {
                        data: ciphertext,
                        nonce,
                    }),
                    Err(e) => Err(e.to_string().into()),
                }
            }
            _ => Err("Unknown algorithm".to_string().into()),
        }
    }

    pub fn decrypt(
        &mut self,
        nonce: [u8; 12],
        ciphertext: Vec<u8>,
        algorithm: u8,
    ) -> Result<EncryptionPayload, Box<dyn Error>> {
        match algorithm {
            1 => {
                let decryption_result = self.aes_cipher.decrypt(
                    GenericArray::from_slice(nonce.as_ref()),
                    ciphertext.as_ref(),
                );

                match decryption_result {
                    Ok(plaintext) => Ok(EncryptionPayload {
                        data: plaintext,
                        nonce,
                    }),
                    Err(e) => Err(e.to_string().into()),
                }
            }
            2 => {
                let decryption_result = self.chacha_cipher.decrypt(
                    GenericArray::from_slice(nonce.as_ref()),
                    ciphertext.as_ref(),
                );

                match decryption_result {
                    Ok(plaintext) => Ok(EncryptionPayload {
                        data: plaintext,
                        nonce,
                    }),
                    Err(e) => Err(e.to_string().into()),
                }
            }
            _ => Err("Unknown algorithm".to_string().into()),
        }
    }
}

pub struct StreamEncryption {}

impl StreamEncryption {
    pub fn encrypt(child_key: &SecretVec<u8>, plaintext: &[u8]) -> Vec<u8> {
        let mut nonce: [u8; 12] = [0; 12];
        let mut rng = rand::thread_rng();
        rng.fill(&mut nonce);

        let key = GenericArray::from_slice(child_key.expose_secret());

        let mut cipher = ChaCha8::new(key, &nonce.into());
        let mut buffer = plaintext.to_owned();

        cipher.apply_keystream(&mut buffer);

        let mut ciphertext: Vec<u8> = nonce.to_vec();
        ciphertext.extend(buffer);

        ciphertext
    }

    pub fn decrypt(child_key: &SecretVec<u8>, ciphertext: &[u8]) -> Vec<u8> {
        let key = GenericArray::from_slice(child_key.expose_secret());

        let mut cipher = ChaCha8::new(key, ciphertext[..12].try_into().unwrap());
        let mut buffer = ciphertext[12..].to_vec();

        cipher.apply_keystream(&mut buffer);

        buffer
    }
}