use process::Command;
use crate::{Error, Result};
#[derive(Clone, Debug, Default, Eq, PartialEq)]
#[cfg_attr(
feature = "derive",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "kebab-case")
)]
pub struct PgpCommands {
pub encrypt_cmd: Option<Command>,
pub encrypt_recipient_fmt: Option<String>,
pub encrypt_recipients_sep: Option<String>,
pub decrypt_cmd: Option<Command>,
pub sign_cmd: Option<Command>,
pub verify_cmd: Option<Command>,
}
impl PgpCommands {
pub fn default_encrypt_cmd() -> Command {
Command::new("gpg --encrypt --quiet --armor <recipients>")
}
pub fn default_encrypt_recipient_fmt() -> String {
String::from("--recipient <recipient>")
}
pub fn default_encrypt_recipients_sep() -> String {
String::from(" ")
}
pub fn default_decrypt_cmd() -> Command {
Command::new("gpg --decrypt --quiet")
}
pub fn default_sign_cmd() -> Command {
Command::new("gpg --sign --quiet --armor")
}
pub fn default_verify_cmd() -> Command {
Command::new("gpg --verify --quiet")
}
pub async fn encrypt(
&self,
recipients: impl IntoIterator<Item = String>,
plain_bytes: Vec<u8>,
) -> Result<Vec<u8>> {
let recipient_fmt = self
.encrypt_recipient_fmt
.clone()
.unwrap_or_else(Self::default_encrypt_recipient_fmt);
let recipients_sep = self
.encrypt_recipients_sep
.clone()
.unwrap_or_else(Self::default_encrypt_recipients_sep);
let recipients_str =
recipients
.into_iter()
.fold(String::new(), |mut recipients_str, recipient| {
if !recipients_str.is_empty() {
recipients_str.push_str(&recipients_sep);
}
recipients_str.push_str(&recipient_fmt.replace("<recipient>", &recipient));
recipients_str
});
let res = self
.encrypt_cmd
.clone()
.unwrap_or_else(Self::default_encrypt_cmd)
.replace("<recipients>", recipients_str)
.run_with(plain_bytes)
.await
.map_err(Error::EncryptCommandError)?;
Ok(res.into())
}
pub async fn decrypt(&self, encrypted_bytes: Vec<u8>) -> Result<Vec<u8>> {
let res = self
.decrypt_cmd
.clone()
.unwrap_or_else(Self::default_decrypt_cmd)
.run_with(encrypted_bytes)
.await
.map_err(Error::DecryptCommandError)?;
Ok(res.into())
}
pub async fn sign(&self, plain_bytes: Vec<u8>) -> Result<Vec<u8>> {
let res = self
.sign_cmd
.clone()
.unwrap_or_else(Self::default_sign_cmd)
.run_with(plain_bytes)
.await
.map_err(Error::SignCommandError)?;
Ok(res.into())
}
pub async fn verify(&self, signature_bytes: Vec<u8>, _signed_bytes: Vec<u8>) -> Result<()> {
self.verify_cmd
.clone()
.unwrap_or_else(Self::default_verify_cmd)
.run_with(signature_bytes)
.await
.map_err(Error::VerifyCommandError)?;
Ok(())
}
}