feat: v1.12.0

This commit is contained in:
2025-05-01 00:22:42 +08:00
parent 3af863762f
commit c270c2e369
14 changed files with 383 additions and 103 deletions

View File

@@ -1,8 +1,15 @@
use crate::util;
use clap::{App, Arg, ArgMatches, SubCommand};
use crate::keyutil::{parse_key_uri, KeyUri, KeyUsage};
use crate::pivutil::slot_equals;
use crate::util::base64_encode;
use crate::{cmdutil, seutil, util};
use clap::{App, ArgMatches, SubCommand};
use ecdsa::elliptic_curve::pkcs8::der::Encode;
use rust_util::util_clap::{Command, CommandError};
use rust_util::XResult;
use serde_json::Value;
use std::collections::BTreeMap;
use x509_parser::parse_x509_certificate;
use yubikey::{Key, YubiKey};
pub struct CommandImpl;
@@ -14,25 +21,54 @@ impl Command for CommandImpl {
fn subcommand<'a>(&self) -> App<'a, 'a> {
SubCommand::with_name(self.name())
.about("External public key subcommand")
.arg(
Arg::with_name("parameter")
.long("parameter")
.takes_value(true)
.required(true)
.help("Parameter"),
)
.arg(cmdutil::build_parameter_arg())
}
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
let _parameter = sub_arg_matches.value_of("parameter").unwrap();
// TODO do get public key
let parameter = sub_arg_matches.value_of("parameter").unwrap();
let mut json = BTreeMap::new();
json.insert("success", Value::Bool(true));
json.insert("public_key_base64", "**".into());
match fetch_public_key(parameter) {
Ok(public_key_bytes) => {
json.insert("success", Value::Bool(true));
json.insert("public_key_base64", base64_encode(&public_key_bytes).into());
}
Err(e) => {
json.insert("success", Value::Bool(false));
json.insert("error", e.to_string().into());
}
}
util::print_pretty_json(&json);
Ok(None)
}
}
fn fetch_public_key(parameter: &str) -> XResult<Vec<u8>> {
let key_uri = parse_key_uri(parameter)?;
match key_uri {
KeyUri::SecureEnclaveKey(key) => {
if key.usage != KeyUsage::Singing {
simple_error!("Not singing key")
} else {
let (_, public_key_der, _) =
seutil::recover_secure_enclave_p256_public_key(&key.private_key, true)?;
Ok(public_key_der)
}
}
KeyUri::YubikeyPivKey(key) => {
let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}");
let keys = opt_result!(Key::list(&mut yk), "List keys failed: {}");
for k in &keys {
let slot_str = format!("{:x}", Into::<u8>::into(k.slot()));
if slot_equals(&key.slot, &slot_str) {
let cert_der = k.certificate().cert.to_der()?;
let x509_certificate = parse_x509_certificate(cert_der.as_slice()).unwrap().1;
let public_key_bytes = x509_certificate.public_key().raw;
return Ok(public_key_bytes.to_vec());
}
}
simple_error!("Slot {} not found", key.slot)
}
}
}