waterfalls 0.9.2

Waterfalls provide blockchain data to liquid and bitcoin light-client wallets
Documentation
use age::x25519::{Identity, Recipient};
use base64::prelude::BASE64_STANDARD_NO_PAD;
use base64::Engine;
use std::io::{Read, Write};

use super::Error;

pub fn encrypt(plaintext: &str, recipient: Recipient) -> Result<String, Error> {
    let encryptor =
        age::Encryptor::with_recipients([recipient].iter().map(|e| e as &dyn age::Recipient))
            .expect("we provided a recipient");

    let mut encrypted = vec![];
    let mut writer = encryptor
        .wrap_output(&mut encrypted)
        .map_err(|_| Error::CannotEncrypt)?;
    writer.write_all(plaintext.as_ref()).unwrap();
    writer.finish().map_err(|_| Error::CannotEncrypt)?;
    let result = BASE64_STANDARD_NO_PAD.encode(encrypted);
    Ok(result)
}
pub fn decrypt(base64_encrypted: &str, key: &Identity) -> Result<String, Error> {
    let encrypted = BASE64_STANDARD_NO_PAD
        .decode(base64_encrypted)
        .map_err(|_| Error::CannotDecrypt)?;

    let decryptor = age::Decryptor::new(&encrypted[..]).map_err(|_| Error::CannotDecrypt)?;

    let mut decrypted = vec![];
    let mut reader = decryptor
        .decrypt(std::iter::once(key as &dyn age::Identity))
        .map_err(|_| Error::CannotDecrypt)?;
    reader.read_to_end(&mut decrypted).unwrap();

    let result = std::str::from_utf8(&decrypted)
        .map_err(|_| Error::CannotDecrypt)?
        .to_string();
    Ok(result)
}

#[cfg(test)]
mod test {
    use age::x25519::Identity;

    use super::{decrypt, encrypt};

    #[test]
    fn test_enc_dec() {
        let idendity = Identity::generate();
        let recipient = idendity.to_public();
        let plaintext = "Hello world!";

        let encrypted = encrypt(plaintext, recipient).unwrap();

        let decrypted = decrypt(&encrypted, &idendity).unwrap();

        assert_eq!(decrypted, plaintext);
        assert_ne!(encrypted, plaintext);
    }
}