guidon 0.4.1

Library to initialize project from templates
Documentation
//! # Crypto module for guidon
//!
//!
use crate::errors::*;
use ansible_vault::*;
use std::env;

/// Encrypt a string with the given key
///
/// The key can be provided by an environment variable `GUIDON_KEY` or by the key option.
/// As of now, the environment variable will be used if set, even if a key is provided as an
/// argument.
/// A initialization vector (IV) can also be provided by environment variable `GUIDON_IV`. If not
/// the default on will be used. The IV must be 16 chars.
///
/// # Arguments
/// * `data`: The message to encrypt
/// * `key`: An option of the key to use. The key length should be 256.
///
/// # Example
/// ```rust
/// # use guidon::{gencrypt};
/// let key = "top_secret";
/// let enc_msg = gencrypt("Hello world !", Some(&key)).unwrap();
/// println!("{}", enc_msg);
/// ```
///
pub fn gencrypt(data: &str, key: Option<&str>) -> Result<String> {
    let guidon_key = env::var("GUIDON_KEY")
        .map_or_else(
            |_e| {
                key.map(String::from)
                    .ok_or(|| GuidonError::from("No key provided"))
            },
            Ok,
        )
        .map_err(|_| GuidonError::from_string("Can't retrieve key !"))?;

    encrypt(data.as_bytes(), &*guidon_key).map_err(|e| e.into())
}

/// Decrypt a string with the given key
///
/// The key can be provided by an environment variable `GUIDON_KEY` or by the key option.
/// As of now, the environment variable will be used if set, even if a key is provided as an
/// argument.
/// A initialization vector (IV) can also be provided by environment variable `GUIDON_IV`. If not
/// the default on will be used. The IV must be 16 chars.
///
/// # Arguments
/// * `data`: The message to decrypt
/// * `key`: An option of the key to use. The key length should be 256.
///
/// # Example
/// ```rust
/// # use guidon::{gencrypt, gdecrypt};
/// let key = "top_secret";
/// let enc_msg = gencrypt("Hello world !", Some(&key)).unwrap();
/// let msg = gdecrypt(&enc_msg, Some(&key)).unwrap();
/// assert_eq!("Hello world !", msg);
/// ```
///
pub fn gdecrypt(data: &str, key: Option<&str>) -> Result<String> {
    let guidon_key = env::var("GUIDON_KEY")
        .map_or_else(
            |_e| {
                key.map(String::from)
                    .ok_or(|| GuidonError::from("No key provided"))
            },
            Ok,
        )
        .map_err(|_| GuidonError::from_string("Can't retrieve key !"))?;
    String::from_utf8(decrypt(data.as_bytes(), &*guidon_key)?).map_err(|e| e.into())
}

#[cfg(test)]
mod tests {
    use crate::crypto::{gdecrypt, gencrypt};
    use log::info;
    use log::LevelFilter;
    use std::sync::Once;

    static INIT: Once = Once::new();

    fn setup() {
        INIT.call_once(|| {
            let _ = env_logger::builder()
                .is_test(true)
                .filter_level(LevelFilter::Trace)
                .try_init();
        });
    }

    #[test]
    fn should_gencrypt_gdecrypt() {
        setup();
        let message = "Hello World!";

        let key = "ôtempssuspendtonvol";
        info!("Key: {}", key);
        let encrypted_data = gencrypt(message, Some(&key)).ok().unwrap();
        info!("Encrypted data: {}", encrypted_data);
        let decrypted_data = gdecrypt(&encrypted_data, Some(&key)).ok().unwrap();
        info!("Decrypted_data: {}", decrypted_data);
        assert_eq!(message, &decrypted_data);
    }
}