entrust-core 0.6.0

En-/decryption and password store management for entrust
Documentation
use crate::age;
use crate::backend::is_age_encrypted;
use anyhow::anyhow;
use std::io::{IsTerminal, Read};
use std::path::Path;
use std::process::{Command, Stdio};
use std::{env, fs, io};

#[cfg(feature = "agent")]
pub use age::agent::get_identity;
#[cfg(not(feature = "agent"))]
pub use age::no_agent::get_identity;

pub fn read_identity() -> anyhow::Result<Vec<u8>> {
    if !io::stdin().is_terminal() {
        read_identity_from_stdin()
    } else if let Some(identity_file) = identity_file() {
        read_identity_from_file(identity_file)
    } else {
        Err(anyhow!("AGE_IDENTITY is not set"))
    }
}

fn read_identity_from_stdin() -> anyhow::Result<Vec<u8>> {
    let mut identity = Vec::new();
    io::stdin().read_to_end(&mut identity)?;
    Ok(identity)
}

fn read_identity_from_file(identity_file: String) -> anyhow::Result<Vec<u8>> {
    if is_age_encrypted(Path::new(identity_file.as_str()))? {
        decrypt_identity_file(identity_file)
    } else {
        fs::read(identity_file).map_err(anyhow::Error::from)
    }
}

fn decrypt_identity_file(identity_file: String) -> anyhow::Result<Vec<u8>> {
    let output = Command::new("age")
        .arg("--decrypt")
        .arg(identity_file)
        .stdin(Stdio::inherit())
        .stdout(Stdio::piped())
        .stderr(Stdio::inherit())
        .output()?;
    if output.status.success() {
        Ok(output.stdout)
    } else {
        Err(anyhow!("age exited with an error"))
    }
}

fn identity_file() -> Option<String> {
    env::var("AGE_IDENTITY").ok()
}