80 lines
1.8 KiB
Rust
80 lines
1.8 KiB
Rust
use std::fs;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use anyhow::Result;
|
|
use clap::{Parser, Subcommand};
|
|
|
|
use crate::crypto;
|
|
|
|
#[derive(Parser)]
|
|
pub struct Cli {
|
|
#[clap(subcommand)]
|
|
pub commands: Commands,
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
pub enum Commands {
|
|
/// Generate key pair
|
|
Generate,
|
|
/// Sign
|
|
Sign { file: PathBuf, private_key: PathBuf },
|
|
/// Sign
|
|
Verify { file: PathBuf, public_key: PathBuf },
|
|
}
|
|
|
|
impl Cli {
|
|
pub fn call(self) -> Result<()> {
|
|
self.commands.call()
|
|
}
|
|
}
|
|
|
|
impl Commands {
|
|
pub fn call(self) -> Result<()> {
|
|
match self {
|
|
Commands::Generate => generate(),
|
|
Commands::Sign { file, private_key } => sign(&file, &private_key),
|
|
Commands::Verify { file, public_key } => verify(&file, &public_key),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn generate() -> Result<()> {
|
|
let key_pair = crypto::generate_key();
|
|
|
|
fs::write("public_key.pem", key_pair.pk.to_pem())?;
|
|
fs::write("private_key.pem", key_pair.sk.to_pem())?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn sign(file: &Path, private_key: &Path) -> Result<()> {
|
|
let message = fs::read(file)?;
|
|
let private_key = fs::read_to_string(private_key)?;
|
|
|
|
let signature = crypto::sign(&message, &private_key)?;
|
|
|
|
let file_path = with_extension(file, ".sig");
|
|
fs::write(file_path, signature.as_slice())?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn verify(file: &Path, public_key: &Path) -> Result<()> {
|
|
let message = fs::read(file)?;
|
|
|
|
let signature_path = with_extension(file, ".sig");
|
|
let signature = fs::read(signature_path)?;
|
|
|
|
let public_key = fs::read_to_string(public_key)?;
|
|
|
|
crypto::verify(&message, &signature, &public_key)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn with_extension(path: &Path, extension: &str) -> PathBuf {
|
|
let mut file_path = path.to_path_buf().into_os_string();
|
|
file_path.push(extension);
|
|
PathBuf::from(file_path)
|
|
}
|