use anyhow::{Result, bail};
use bc_components::{
PrivateKeyBase, PublicKeys, SigningPrivateKey, SigningPublicKey, Verifier,
};
use bc_envelope::prelude::*;
use clap::Args;
use crate::{EnvelopeArgs, EnvelopeArgsLike};
#[derive(Debug, Args)]
#[group(skip)]
pub struct CommandArgs {
#[arg(long, short, default_value = "false")]
silent: bool,
#[arg(long, short, default_value = "1")]
threshold: usize,
#[arg(long, short)]
verifier: Vec<String>,
#[command(flatten)]
envelope_args: EnvelopeArgs,
}
impl EnvelopeArgsLike for CommandArgs {
fn envelope(&self) -> Option<&str> { self.envelope_args.envelope() }
}
impl crate::Exec for CommandArgs {
fn exec(&self) -> Result<String> {
let envelope = self.read_envelope()?;
if self.verifier.is_empty() {
bail!("at least one verifier must be provided");
}
let mut private_key_bases: Vec<PrivateKeyBase> = Vec::new();
let mut public_keys_vec: Vec<PublicKeys> = Vec::new();
let mut signing_private_keys: Vec<SigningPrivateKey> = Vec::new();
let mut signing_public_keys: Vec<SigningPublicKey> = Vec::new();
for v in &self.verifier {
if let Ok(key) = PrivateKeyBase::from_ur_string(v) {
private_key_bases.push(key);
} else if let Ok(key) = PublicKeys::from_ur_string(v) {
public_keys_vec.push(key);
} else if let Ok(key) = SigningPrivateKey::from_ur_string(v) {
signing_private_keys.push(key);
} else if let Ok(key) = SigningPublicKey::from_ur_string(v) {
signing_public_keys.push(key);
} else if v.starts_with("ur:envelope") {
let key_envelope = Envelope::from_ur_string(v)?;
if let Ok(key) =
key_envelope.extract_subject::<PrivateKeyBase>()
{
private_key_bases.push(key);
} else if let Ok(key) =
key_envelope.extract_subject::<PublicKeys>()
{
public_keys_vec.push(key);
} else if let Ok(key) =
key_envelope.extract_subject::<SigningPrivateKey>()
{
signing_private_keys.push(key);
} else if let Ok(key) =
key_envelope.extract_subject::<SigningPublicKey>()
{
signing_public_keys.push(key);
} else {
bail!(
"envelope does not contain a valid verifier key: {}",
v
);
}
} else {
bail!("invalid verifier: {}", v);
}
}
let mut verifiers: Vec<&dyn Verifier> = Vec::new();
for key in private_key_bases.iter() {
verifiers.push(key as &dyn Verifier);
}
for key in public_keys_vec.iter() {
verifiers.push(key as &dyn Verifier);
}
for key in signing_private_keys.iter() {
verifiers.push(key as &dyn Verifier);
}
for key in signing_public_keys.iter() {
verifiers.push(key as &dyn Verifier);
}
envelope.clone().verify_signatures_from_threshold(
&verifiers,
Some(self.threshold),
)?;
Ok(if self.silent {
"".to_string()
} else {
envelope.ur_string()
})
}
}