feat: v1.12.0
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user