feat(cli): add AES to cli app

This commit is contained in:
Kristofers Solo 2025-11-24 11:23:37 +02:00
parent 5b3ca7eacf
commit 051bba33a8
Signed by: kristoferssolo
GPG Key ID: 74FF8144483D82C8
6 changed files with 47 additions and 35 deletions

View File

@ -107,7 +107,7 @@ fn parse_radix(s: &str, radix: u32) -> Result<u128, BlockError> {
} }
fn ascii_string_to_u128(s: &str) -> Result<u128, BlockError> { fn ascii_string_to_u128(s: &str) -> Result<u128, BlockError> {
if s.len() > 8 { if s.len() > 16 {
return Err(BlockError::InvalidByteStringLength(s.len())); return Err(BlockError::InvalidByteStringLength(s.len()));
} }

View File

@ -5,7 +5,7 @@ use crate::{CipherAction, CipherError, CipherResult, Output};
/// Implements the standard encrypt/decrypt interface for block ciphers. /// Implements the standard encrypt/decrypt interface for block ciphers.
/// Implementers define `transform_impl` to handle the core algorithm, /// Implementers define `transform_impl` to handle the core algorithm,
/// while `transform` provides validation and convenience wrappers. /// while `transform` provides validation and convenience wrappers.
pub trait BlockCipher: Sized { pub trait BlockCipher {
const BLOCK_SIZE: usize; const BLOCK_SIZE: usize;
fn from_key(key: &[u8]) -> Self; fn from_key(key: &[u8]) -> Self;

View File

@ -1,5 +1,3 @@
use cipher_core::{BlockCipher, InputBlock};
use des::Des;
use std::fmt::Display; use std::fmt::Display;
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))] #[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
@ -9,16 +7,6 @@ pub enum Algorithm {
Aes, Aes,
} }
impl Algorithm {
#[must_use]
pub fn get_cipher(&self, key: &impl InputBlock) -> impl BlockCipher {
match self {
Self::Des => Des::from_key(key.as_bytes()),
Self::Aes => todo!("Must implement AES first"),
}
}
}
impl Display for Algorithm { impl Display for Algorithm {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self { let s = match self {

View File

@ -18,9 +18,9 @@ impl OutputFormat {
#[must_use] #[must_use]
pub fn to_string(&self, value: &Output) -> String { pub fn to_string(&self, value: &Output) -> String {
match self { match self {
Self::Binary => format!("{value:064b}"), Self::Binary => format!("{value:b}"),
Self::Octal => format!("{value:022o}"), Self::Octal => format!("{value:o}"),
Self::Hex => format!("{value:016X}"), Self::Hex => format!("{value:X}"),
Self::Text => format!("{value}"), Self::Text => format!("{value}"),
} }
} }

View File

@ -1,7 +1,5 @@
use cipher_factory::{Algorithm, OperationChoice, OutputFormat}; use cipher_factory::{Algorithm, OperationChoice, OutputFormat};
use clap::Parser; use clap::Parser;
use des::Block64;
use std::str::FromStr;
#[derive(Debug, Clone, Parser)] #[derive(Debug, Clone, Parser)]
#[command(version, about, long_about = None)] #[command(version, about, long_about = None)]
@ -15,12 +13,12 @@ pub struct Args {
pub algorithm: Algorithm, pub algorithm: Algorithm,
/// Key used for encryption/decryption. Can be a string or a path to a file /// Key used for encryption/decryption. Can be a string or a path to a file
#[arg(short, long, value_parser = Block64::from_str, required = true)] #[arg(short, long, required = true)]
pub key: Block64, pub key: String,
/// The text to encrypt/decrypt. Can be a string or a path to a file /// The text to encrypt/decrypt. Can be a string or a path to a file
#[arg(value_name = "TEXT", value_parser = Block64::from_str, required = true)] #[arg(value_name = "TEXT", required = true)]
pub text: Block64, pub text: String,
/// Output format for decrypted data /// Output format for decrypted data
#[arg(short = 'f', long)] #[arg(short = 'f', long)]

View File

@ -1,11 +1,15 @@
mod args; mod args;
use crate::args::Args; use crate::args::Args;
use aes::{Aes, Block128};
use cipher_core::BlockCipher; use cipher_core::BlockCipher;
use cipher_factory::OperationChoice; use cipher_factory::{Algorithm, OperationChoice, OutputFormat};
use clap::Parser; use clap::Parser;
use color_eyre::eyre::{Ok, Result};
use des::{Block64, Des};
use std::str::FromStr;
fn main() -> color_eyre::Result<()> { fn main() -> Result<()> {
color_eyre::install()?; color_eyre::install()?;
let Args { let Args {
operation, operation,
@ -15,18 +19,40 @@ fn main() -> color_eyre::Result<()> {
output_format, output_format,
} = Args::parse(); } = Args::parse();
match operation { match algorithm {
OperationChoice::Encrypt => { Algorithm::Des => {
let cipher = algorithm.get_cipher(&key); let key = Block64::from_str(&key)?;
let ciphertext = cipher.encrypt(&text.to_be_bytes())?; let text = Block64::from_str(&text)?;
println!("{ciphertext:016X}"); let cipher = Des::from_key(&key.to_be_bytes());
execute_cipher(operation, &cipher, &text.to_be_bytes(), output_format)?;
} }
OperationChoice::Decrypt => { Algorithm::Aes => {
let cipher = algorithm.get_cipher(&key); let key = Block128::from_str(&key)?;
let plaintext = cipher.decrypt(&text.to_be_bytes())?; let text = Block128::from_str(&text)?;
let output = output_format.unwrap_or_default().to_string(&plaintext); let cipher = Aes::from_key(&key.to_be_bytes());
println!("{output}"); execute_cipher(operation, &cipher, &text.to_be_bytes(), output_format)?;
} }
} }
Ok(()) Ok(())
} }
fn execute_cipher(
operation: OperationChoice,
cipher: &impl BlockCipher,
text_bytes: &[u8],
output_format: Option<OutputFormat>,
) -> Result<()> {
match operation {
OperationChoice::Encrypt => {
let ciphertext = cipher.encrypt(text_bytes)?;
println!("{ciphertext:X}");
}
OperationChoice::Decrypt => {
let plaintext = cipher.decrypt(text_bytes)?;
let output = output_format.unwrap_or_default().to_string(&plaintext);
println!("{output}");
}
}
Ok(())
}