You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

262 lines
5.1 KiB

use super::*;
use std::{
path::{
PathBuf,
},
};
/// The type of key to generate
#[derive(Debug,Eq,PartialEq)]
pub enum GenerateKey
{
Rsa,
Aes,
}
/// The key serialise format
#[derive(Debug,Eq,PartialEq)]
pub enum KeyOutputFormat
{
Binary,
Text,
/// PEM format only valid for RSA keys
PEM,
}
impl FromStr for KeyOutputFormat
{
type Err = Error;
fn from_str(value: &str) -> Result<Self, Self::Err> {
Ok(match value.to_uppercase().as_str() {
"TEXT" => KeyOutputFormat::Text,
"BIN" => KeyOutputFormat::Binary,
"PEM" => KeyOutputFormat::PEM,
d => return Err(format!("Unknown key output format `{}`. Expected `TEXT`, `BIN` or `PEM`.", d))?,
})
}
}
impl KeyOutputFormat
{
pub fn is_aes_okay(&self) -> bool
{
if let KeyOutputFormat::PEM = self {
false
} else {
true
}
}
}
/// Operation mode for `Operation::Normal`
#[derive(Debug,Eq,PartialEq)]
pub enum OperationMode
{
Autodetect,
Encrypt,
Decrypt,
Verify,
}
/// The operation for this run
#[derive(Debug,Eq,PartialEq)]
pub enum Operation
{
/// Crypto
Normal{
mode: OperationMode,
rsa: Vec<PathBuf>,
sign: Vec<PathBuf>,
auto_sign: bool,
aes: Vec<PathBuf>,
translate: Vec<(PathBuf, Option<PathBuf>)>,
in_place: bool,
verbose: bool,
#[cfg(feature="threads")]
sync: bool,
},
/// Generate key
KeyGen{
key_type: GenerateKey,
format: KeyOutputFormat,
cycle: Option<PathBuf>,
use_password: bool,
password: Option<String>,
output: Option<PathBuf>,
private_only: bool,
public_only: bool,
output_public: Option<PathBuf>,
verbose: bool,
},
/// Print help
Help,
}
impl Operation
{
/// Is verbose logging enabled
pub fn verbose(&self) -> bool
{
match self {
Self::Normal { verbose, .. } |
Self::KeyGen { verbose, .. } => *verbose,
_ => false,
}
}
}
macro_rules! transcribe {
($cond:expr => $if:expr; $else:expr) => {
if $cond {$if} else {$else}
};
}
use std::fmt;
impl fmt::Display for Operation
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match &self {
Self::Help => writeln!(f, "Display help"),
Self::Normal{
mode,
rsa,
sign,
auto_sign,
aes,
in_place,
verbose,
#[cfg(feature="threads")]
sync,
..
} => {
write!(f, "Mode: ")?;
match mode {
OperationMode::Encrypt => writeln!(f, "Encrypt")?,
OperationMode::Decrypt => writeln!(f, "Decrypt")?,
OperationMode::Verify => writeln!(f, "Verify")?,
_ => writeln!(f, "Autodetected")?,
}
if rsa.len() > 0 {
writeln!(f, "RSA encryption enabled for {} keys.", rsa.len())?;
}
if sign.len() > 0 || *auto_sign {
writeln!(f, "Signing with {} keys.", sign.len() + transcribe!(*auto_sign => rsa.len(); 0))?;
}
writeln!(f, "AES encrypting with {} keys.", aes.len())?;
writeln!(f, " (will generate {} session keys.)",
transcribe!(aes.len() > 0 =>
aes.len() * transcribe!(rsa.len()>0 => rsa.len(); 1);
rsa.len()))?;
if *in_place {
writeln!(f, "In-place")?;
}
#[cfg(feature="threads")]
if *sync {
writeln!(f, "Single-threaded mode")?;
}
#[cfg(not(feature="threads"))]
writeln!(f, "Single-threaded mode")?;
if *verbose {
writeln!(f, "Verbose mode")?;
}
Ok(())
},
Self::KeyGen {
key_type: GenerateKey::Rsa,
format,
cycle,
password,
use_password,
output,
verbose,
private_only,
output_public,
public_only,
} => {
writeln!(f, "Generate key: RSA")?;
writeln!(f, "Output format: {}", format)?;
if let Some(cycle) = cycle {
if output.is_some() || output_public.is_some() {
writeln!(f, "Input: {:?}", cycle)?;
} else {
writeln!(f, "In-place: {:?}", cycle)?;
}
}
if password.is_some() || *use_password {
writeln!(f, "Using password.")?;
}
if let Some(output) = output {
writeln!(f, "Outputting to: {:?}", output)?;
}
if let Some(output_public) = output_public {
if *public_only {
writeln!(f, "Outputting public only to {:?}", output_public)?;
} else {
writeln!(f, "Outputting public to {:?}", output_public)?;
}
}
if *private_only {
writeln!(f, "No public output")?;
}
if *verbose {
writeln!(f, "Verbose logging")?;
}
Ok(())
},
Self::KeyGen {
key_type: GenerateKey::Aes,
format,
cycle,
password,
use_password,
output,
verbose,
..
} => {
writeln!(f, "Generate key: AES")?;
writeln!(f, "Output format: {}", format)?;
if let Some(cycle) = cycle {
if output.is_some() {
writeln!(f, "Input: {:?}", cycle)?;
} else {
writeln!(f, "In-place: {:?}", cycle)?;
}
}
if password.is_some() || *use_password {
writeln!(f, "Using password.")?;
}
if let Some(output) = output {
writeln!(f, "Outputting to: {:?}", output)?;
}
if *verbose {
writeln!(f, "Verbose logging.")?;
}
Ok(())
},
}
}
}
impl fmt::Display for KeyOutputFormat
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{}", match self {
Self::PEM => "PEM",
Self::Text => "TEXT",
Self::Binary => "BIN",
})
}
}