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
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",
|
|
})
|
|
}
|
|
}
|