From 0dd5aa59ab4db1d47302a368b636fd58f49978a5 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Sun, 21 Apr 2024 23:24:46 +0800 Subject: [PATCH] feat: v1.9.1, optimize sign/verify file --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/cmd_signfile.rs | 19 ++++++++++++++++++- src/cmd_verifyfile.rs | 20 ++++++++++---------- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bfda6e5..184a444 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -368,7 +368,7 @@ dependencies = [ [[package]] name = "card-cli" -version = "1.9.0" +version = "1.9.1" dependencies = [ "authenticator", "base64 0.21.7", diff --git a/Cargo.toml b/Cargo.toml index 38285a0..da6f8c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "card-cli" -version = "1.9.0" +version = "1.9.1" authors = ["Hatter Jiang "] edition = "2018" diff --git a/src/cmd_signfile.rs b/src/cmd_signfile.rs index da71db3..7b05e82 100644 --- a/src/cmd_signfile.rs +++ b/src/cmd_signfile.rs @@ -1,3 +1,4 @@ +use std::fs; use std::time::SystemTime; use clap::{App, Arg, ArgMatches, SubCommand}; @@ -44,6 +45,7 @@ impl Command for CommandImpl { .takes_value(true).required(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e")) .arg(Arg::with_name("file").short("f").long("file").takes_value(true).required(true).help("Input file")) .arg(Arg::with_name("filename").short("n").long("filename").takes_value(true).help("Filename")) + .arg(Arg::with_name("sign-file").short("S").long("sign-file").takes_value(false).help("Sign file")) .arg(Arg::with_name("comment").short("c").long("comment").takes_value(true).help("Comment")) .arg(Arg::with_name("attributes").short("a").long("attributes").takes_value(true).help("Attributes")) } @@ -94,6 +96,9 @@ impl Command for CommandImpl { } }), }; + let sign_file = sub_arg_matches.value_of("sign-file").map(ToString::to_string).or_else(|| { + filename_opt.clone().map(|f| format!("{}.simple-sig", f)) + }); let sign_file_request = SignFileRequest { filename: filename_opt, @@ -126,7 +131,19 @@ impl Command for CommandImpl { signatures: vec![signature], }; - println!("{}", serde_json::to_string_pretty(&simple_sig).unwrap()); + let sign_file_content = serde_json::to_string_pretty(&simple_sig).unwrap(); + if let Some(sign_file) = sign_file { + if fs::read(&sign_file).is_ok() { + warning!("Simple sign file: {} exists", sign_file); + } else { + match fs::write(&sign_file, &sign_file_content) { + Ok(_) => success!("Write simple sign file: {} succeed", sign_file), + Err(e) => failure!("Write simple sign file: {} failed: {}", sign_file, e), + } + } + } + + println!("{}", sign_file_content); Ok(None) } } diff --git a/src/cmd_verifyfile.rs b/src/cmd_verifyfile.rs index 4dfd24e..69545d6 100644 --- a/src/cmd_verifyfile.rs +++ b/src/cmd_verifyfile.rs @@ -3,7 +3,6 @@ use std::ops::Add; use std::time::{Duration, SystemTime}; use clap::{App, Arg, ArgMatches, SubCommand}; -use p384::ecdsa::signature::hazmat::PrehashVerifier; use rust_util::util_clap::{Command, CommandError}; use rust_util::util_msg; use x509_parser::parse_x509_certificate; @@ -24,18 +23,18 @@ impl Command for CommandImpl { fn subcommand<'a>(&self) -> App<'a, 'a> { SubCommand::with_name(self.name()).about("PIV Verify(with SHA256) subcommand") .arg(Arg::with_name("file").short("f").long("file").takes_value(true).required(false).help("Input file")) - .arg(Arg::with_name("filename").short("n").long("filename").takes_value(true).help("Filename")) + .arg(Arg::with_name("sign-file").short("S").long("sign-file").takes_value(true).help("Sign file")) } fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError { util_msg::set_logger_std_out(false); - let filename = sub_arg_matches.value_of("filename").map(ToString::to_string).unwrap(); - let file_content = opt_result!(fs::read_to_string(&filename), "Read file: {}, failed: {}", filename); - let simple_sign_file: SimpleSignFile = opt_result!(serde_json::from_str(&file_content), "Parse file: {}, failed: {}", filename); + let sign_file = sub_arg_matches.value_of("sign-file").map(ToString::to_string).unwrap(); + let sign_file_content = opt_result!(fs::read_to_string(&sign_file), "Read file: {}, failed: {}", sign_file); + let simple_sign_file: SimpleSignFile = opt_result!(serde_json::from_str(&sign_file_content), "Parse file: {}, failed: {}", sign_file); if SIMPLE_SIG_SCHEMA != simple_sign_file.schema { - return simple_error!("File: {} format error: bad schema", filename); + return simple_error!("File: {} format error: bad schema", sign_file); } information!("File name: {}", simple_sign_file.filename.as_deref().unwrap_or("")); information!("Digest: {}", &simple_sign_file.digest); @@ -111,12 +110,13 @@ impl Command for CommandImpl { // PublicKey::RSA(_) => {} PublicKey::EC(ec_point) => { if ec_point.key_size() != 384 { - return simple_error!("Only support p384"); + return simple_error!("Current only support p384"); } - let p384_verifying_key = opt_result!(p384::ecdsa::VerifyingKey::from_sec1_bytes(ec_point.data()), "Parse public key failed: {}"); - let sig = opt_result!(p384::ecdsa::DerSignature::from_bytes(&signature_bytes), "Parse signature failed: {}"); + use p384::ecdsa::{DerSignature, signature::hazmat::PrehashVerifier, VerifyingKey}; + let p384_verifying_key = opt_result!(VerifyingKey::from_sec1_bytes(ec_point.data()), "Parse public key failed: {}"); + let sig = opt_result!(DerSignature::from_bytes(&signature_bytes), "Parse signature failed: {}"); match p384_verifying_key.verify_prehash(&tobe_signed_digest, &sig) { - Ok(_) => success!("Verify leaf certificate signature succeed."), + Ok(_) => success!("Verify leaf certificate signature success"), Err(e) => return simple_error!("Verify leaf certificate signature failed: {}", e), } }