diff --git a/Cargo.lock b/Cargo.lock index 0aae23a..3142407 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -384,7 +384,7 @@ dependencies = [ [[package]] name = "card-cli" -version = "1.1.11" +version = "1.1.12" dependencies = [ "authenticator", "base64 0.13.0", diff --git a/Cargo.toml b/Cargo.toml index cfdbd2c..a0fd7d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "card-cli" -version = "1.1.11" +version = "1.1.12" authors = ["Hatter Jiang "] edition = "2018" diff --git a/src/cmd_pivsign.rs b/src/cmd_pivsign.rs index 509e983..86def5b 100644 --- a/src/cmd_pivsign.rs +++ b/src/cmd_pivsign.rs @@ -15,42 +15,51 @@ impl Command for CommandImpl { fn subcommand<'a>(&self) -> App<'a, 'a> { SubCommand::with_name(self.name()).about("PIV Sign subcommand") .arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("123456").help("OpenPGP card user pin")) - .arg(Arg::with_name("pass").long("pass").takes_value(true).help("[deprecated] now OpenPGP card user pin")) + .arg(Arg::with_name("sha256").short("2").long("sha256").takes_value(true).help("Digest SHA256 HEX")) .arg(Arg::with_name("json").long("json").help("JSON output")) } fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError { let json_output = sub_arg_matches.is_present("json"); - if json_output { - rust_util::util_msg::set_logger_std_out(false); - } - warning!("This feature is not complete"); - let pin_opt = sub_arg_matches.value_of("pass").or_else(|| sub_arg_matches.value_of("pin")); + if json_output { rust_util::util_msg::set_logger_std_out(false); } + + let pin_opt = sub_arg_matches.value_of("pin"); let pin = opt_value_result!(pin_opt, "User pin must be assigned"); + let sha256_hex_opt = sub_arg_matches.value_of("sha256").map(|s| s.to_string()); + let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}"); opt_result!(yk.verify_pin(pin.as_bytes()), "YubiKey verify pin failed: {}"); - let hash = hex::decode( - "3031300d060960864801650304020105000420".to_string() + - "66d8dff9cbf819183700ff6d08349d9472af54031e8e297f8ab341e307f5387c").unwrap(); - rust_util::util_msg::when(MessageType::DEBUG, || debugging!("Hash: {}", hex::encode(&hash))); - let hash_padding = pkcs1_padding_for_sign(&hash, 2048).unwrap(); - rust_util::util_msg::when(MessageType::DEBUG, || debugging!("PKCS1 padding: {}", hex::encode(&hash_padding))); - let raw_in = crate::digest::copy_rsa2048(&hash_padding).unwrap(); - let sign_result = yubikey::piv::sign_data(&mut yk, &raw_in, AlgorithmId::Rsa2048, SlotId::Signature); - let sign = opt_result!(sign_result, "Sign data failed: {}"); - let sign_bytes = sign.as_slice(); + let sha256_prefix = hex::decode("3031300d060960864801650304020105000420").unwrap(); - if json_output { - let mut json = BTreeMap::<&'_ str, String>::new(); - json.insert("hash_hex", hex::encode(&hash)); - json.insert("sign_hex", hex::encode(&sign_bytes)); - json.insert("sign_base64", base64::encode(&sign_bytes)); - println!("{}", serde_json::to_string_pretty(&json).unwrap()); - } else { - success!("Signature HEX: {}", hex::encode(sign_bytes)); - success!("Signature base64: {}", base64::encode(sign_bytes)); + if let Some(sha256_hex) = sha256_hex_opt { + let hash = opt_result!(hex::decode(sha256_hex), "Decode sha256 failed: {}"); + + let mut hash_with_oid = Vec::with_capacity(128); + hash_with_oid.extend_from_slice(&sha256_prefix); + hash_with_oid.extend_from_slice(&hash); + let hash_padding = pkcs1_padding_for_sign(&hash_with_oid, 2048).unwrap(); + rust_util::util_msg::when(MessageType::DEBUG, || { + debugging!("Hash: {}", hex::encode(&hash)); + debugging!("Hash with OID: {}", hex::encode(&hash_with_oid)); + debugging!("PKCS1 padding: {}", hex::encode(&hash_padding)); + }); + let raw_in = crate::digest::copy_rsa2048(&hash_padding).unwrap(); + let sign_result = yubikey::piv::sign_data(&mut yk, &raw_in, AlgorithmId::Rsa2048, SlotId::Signature); + let sign = opt_result!(sign_result, "Sign data failed: {}"); + let sign_bytes = sign.as_slice(); + + if json_output { + let mut json = BTreeMap::<&'_ str, String>::new(); + json.insert("hash_hex", hex::encode(&hash)); + json.insert("sign_hex", hex::encode(&sign_bytes)); + json.insert("sign_base64", base64::encode(&sign_bytes)); + println!("{}", serde_json::to_string_pretty(&json).unwrap()); + } else { + success!("Signature HEX: {}", hex::encode(sign_bytes)); + success!("Signature base64: {}", base64::encode(sign_bytes)); + } } Ok(None) }