use abscissa::Callable;
use std::process;
use signatory::ed25519;
use tendermint::public_keys::ConsensusKey;
use yubihsm;
#[derive(Debug, Default, Options)]
pub struct ListCommand {
#[options(short = "c", long = "config")]
pub config: Option<String>,
}
impl Callable for ListCommand {
fn call(&self) {
let hsm_connector = yubihsm::create_hsm_connector();
let serial_number = hsm_connector.serial_number().unwrap_or_else(|e| {
status_err!("couldn't get YubiHSM serial number: {}", e);
process::exit(1);
});
let credentials = yubihsm::get_config().auth.credentials();
let mut hsm = yubihsm::Client::open(hsm_connector, credentials, true).unwrap_or_else(|e| {
status_err!("error connecting to YubiHSM2: {}", e);
process::exit(1);
});
let objects = hsm.list_objects(&[]).unwrap_or_else(|e| {
status_err!("couldn't list YubiHSM objects: {}", e);
process::exit(1);
});
let mut keys = objects
.iter()
.filter(|o| o.object_type == yubihsm::ObjectType::AsymmetricKey)
.collect::<Vec<_>>();
keys.sort_by(|k1, k2| k1.object_id.cmp(&k2.object_id));
if keys.is_empty() {
status_err!("no keys in this YubiHSM (#{})", serial_number);
process::exit(0);
}
println!("Listing keys in YubiHSM #{}:", serial_number);
for key in &keys {
let public_key = hsm.get_pubkey(key.object_id).unwrap_or_else(|e| {
status_err!(
"couldn't get public key for asymmetric key #{}: {}",
key.object_id,
e
);
process::exit(1);
});
let key_id = format!("- #{}", key.object_id);
if public_key.algorithm == yubihsm::AsymmetricAlg::Ed25519 {
status_attr_ok!(
key_id,
ConsensusKey::from(
ed25519::PublicKey::from_bytes(&public_key.as_ref()).unwrap()
)
);
} else {
status_attr_err!(key_id, "unsupported algorithm: {:?}", public_key.algorithm);
}
}
}
}
impl_command!(ListCommand);