use abscissa::Callable;
use std::process;
use super::*;
use signatory::ed25519;
use tendermint::public_keys::ConsensusKey;
use yubihsm;
#[derive(Debug, Default, Options)]
pub struct GenerateCommand {
#[options(short = "c", long = "config")]
pub config: Option<String>,
#[options(short = "l", long = "label")]
pub label: Option<String>,
#[options(short = "t")]
pub key_type: Option<String>,
#[options(free)]
key_ids: Vec<u16>,
}
impl Callable for GenerateCommand {
fn call(&self) {
if self.key_ids.is_empty() {
status_err!("must provide at least one key ID to generate");
process::exit(1);
}
match &self.key_type {
Some(ref key_type) => if key_type != DEFAULT_KEY_TYPE {
status_err!(
"only supported key type is: ed25519 (given: \"{}\")",
key_type
);
process::exit(1);
},
None => (),
}
let mut hsm = yubihsm::get_hsm_client();
for key_id in &self.key_ids {
let label =
yubihsm::ObjectLabel::from(self.label.as_ref().map(|l| l.as_ref()).unwrap_or(""));
if let Err(e) = hsm.generate_asymmetric_key(
*key_id,
label,
DEFAULT_DOMAINS,
DEFAULT_CAPABILITIES,
yubihsm::AsymmetricAlg::Ed25519,
) {
status_err!("couldn't generate key #{}: {}", key_id, e);
process::exit(1);
}
let public_key =
ed25519::PublicKey::from_bytes(hsm.get_pubkey(*key_id).unwrap_or_else(|e| {
status_err!("couldn't get public key for key #{}: {}", key_id, e);
process::exit(1);
})).unwrap();
status_ok!(
"Generated",
"key #{}: {}",
key_id,
ConsensusKey::from(public_key)
);
}
}
}
impl_command!(GenerateCommand);