1
0
Fork 0
mirror of https://codeberg.org/tyy/aspm synced 2024-12-22 20:39:29 -07:00

Fix pkcs#8 conversion for P-256 keys

This commit is contained in:
Tyler Beckman 2023-08-02 19:30:45 -06:00
parent bb6bed5531
commit ec1b9f3bf9
Signed by: Ty
GPG key ID: 2813440C772555A4
4 changed files with 75 additions and 66 deletions

View file

@ -67,7 +67,7 @@ impl JwtExt for Jwk {
// 4. Convert that Pkey into the PKCS#8 encoded private key (and then base64 encode it) // 4. Convert that Pkey into the PKCS#8 encoded private key (and then base64 encode it)
let key_pair: Box<dyn KeyPair> = match self.key_type() { let key_pair: Box<dyn KeyPair> = match self.key_type() {
"EC" => match self.curve() { "EC" => match self.curve() {
Some("p-256") => Box::new(EcKeyPair::from_jwk(self)?), Some("P-256") => Box::new(EcKeyPair::from_jwk(self)?),
_ => bail!("Unsupported curve type"), _ => bail!("Unsupported curve type"),
}, },
"OKP" => match self.curve() { "OKP" => match self.curve() {

View file

@ -2,72 +2,72 @@ use anstyle::{AnsiColor, Color as AnstyleColor, Reset, Style as Anstyle};
use anyhow::Context; use anyhow::Context;
use asp::keys::AspKeyType; use asp::keys::AspKeyType;
use clap::Parser; use clap::Parser;
use dialoguer::{Confirm, theme::ColorfulTheme, console::Term}; use dialoguer::{console::Term, theme::ColorfulTheme, Confirm};
use indoc::writedoc; use indoc::writedoc;
use sea_orm::ModelTrait; use sea_orm::ModelTrait;
use std::io::Write; use std::io::Write;
use crate::{ use crate::{
entities::keys::{Entity as KeysEntity, Model as KeysModel}, commands::{AspmSubcommand, KeysEntityExt, KeysQueryResult},
commands::{AspmSubcommand, KeysQueryResult, KeysEntityExt} entities::keys::{Entity as KeysEntity, Model as KeysModel},
}; };
/// Deletes a saved key, after asking for confirmation. /// Deletes a saved key, after asking for confirmation.
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
pub struct KeysDeleteCommand { pub struct KeysDeleteCommand {
/// Will disable any confirmation prompts. This is not recommended unless you knowingly give a full fingerprint, as it is easy to accidentally (and permanently) delete wrong keys otherwise. /// Will disable any confirmation prompts. This is not recommended unless you knowingly give a full fingerprint, as it is easy to accidentally (and permanently) delete wrong keys otherwise.
#[arg(long)] #[arg(long)]
no_confirm: bool, no_confirm: bool,
/// The key to export. This can either be a fingerprint obtained with the `keys list` command, or an alias to search for. /// The key to export. This can either be a fingerprint obtained with the `keys list` command, or an alias to search for.
key: String, key: String,
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for KeysDeleteCommand { impl AspmSubcommand for KeysDeleteCommand {
async fn execute(&self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(&self, state: crate::AspmState) -> Result<(), anyhow::Error> {
// Fetch key from db // Fetch key from db
let entry = KeysEntity::query_key(&state.db, &self.key) let entry = KeysEntity::query_key(&state.db, &self.key)
.await .await
.context("Unable to query keys from database")?; .context("Unable to query keys from database")?;
let key: KeysModel = match entry { let key: KeysModel = match entry {
KeysQueryResult::None => { KeysQueryResult::None => {
eprintln!( eprintln!(
"{style}No keys matching the given query were found{reset}", "{style}No keys matching the given query were found{reset}",
style = Anstyle::new() style = Anstyle::new()
.fg_color(Some(AnstyleColor::Ansi(AnsiColor::BrightRed))) .fg_color(Some(AnstyleColor::Ansi(AnsiColor::BrightRed)))
.render(), .render(),
reset = Reset.render() reset = Reset.render()
); );
std::process::exit(1); std::process::exit(1);
} }
KeysQueryResult::One(key) => key, KeysQueryResult::One(key) => key,
KeysQueryResult::Many(mut keys) => { KeysQueryResult::Many(mut keys) => {
eprintln!( eprintln!(
"{style}More than one keys matching the given query were found{reset}", "{style}More than one keys matching the given query were found{reset}",
style = Anstyle::new() style = Anstyle::new()
.fg_color(Some(AnstyleColor::Ansi(AnsiColor::BrightYellow))) .fg_color(Some(AnstyleColor::Ansi(AnsiColor::BrightYellow)))
.render(), .render(),
reset = Reset::default().render() reset = Reset::default().render()
); );
keys.remove(0) keys.remove(0)
} }
}; };
if !self.no_confirm { if !self.no_confirm {
// Construct styles // Construct styles
let reset = Reset::default().render(); let reset = Reset::default().render();
let alias_style = Anstyle::new() let alias_style = Anstyle::new()
.underline() .underline()
.fg_color(Some(anstyle::Color::Ansi(AnsiColor::BrightCyan))) .fg_color(Some(anstyle::Color::Ansi(AnsiColor::BrightCyan)))
.render(); .render();
let key_style = Anstyle::new() let key_style = Anstyle::new()
.fg_color(Some(anstyle::Color::Ansi(AnsiColor::BrightGreen))) .fg_color(Some(anstyle::Color::Ansi(AnsiColor::BrightGreen)))
.render(); .render();
let value_style = Anstyle::new() let value_style = Anstyle::new()
.fg_color(Some(anstyle::Color::Ansi(AnsiColor::BrightYellow))) .fg_color(Some(anstyle::Color::Ansi(AnsiColor::BrightYellow)))
.render(); .render();
let _ = writedoc! { let _ = writedoc! {
std::io::stderr(), std::io::stderr(),
" "
{alias_style}{alias}:{reset} {alias_style}{alias}:{reset}
@ -79,20 +79,22 @@ impl AspmSubcommand for KeysDeleteCommand {
alias = key.alias alias = key.alias
}; };
let confirmation = Confirm::with_theme(&ColorfulTheme::default()) let confirmation = Confirm::with_theme(&ColorfulTheme::default())
.with_prompt("Are you sure you want to delete this key?") .with_prompt("Are you sure you want to delete this key?")
.interact_on(&Term::stderr()) .interact_on(&Term::stderr())
.context("Unable to prompt on stderr")?; .context("Unable to prompt on stderr")?;
if !confirmation { if !confirmation {
std::process::exit(1); std::process::exit(1);
} }
} }
let fingerprint = key.fingerprint.clone(); let fingerprint = key.fingerprint.clone();
key.delete(&state.db).await.context("Unable to delete key")?; key.delete(&state.db)
println!("Successfully deleted key with fingerprint {}", fingerprint); .await
.context("Unable to delete key")?;
println!("Successfully deleted key with fingerprint {}", fingerprint);
Ok(()) Ok(())
} }
} }

View file

@ -1,11 +1,11 @@
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
pub mod delete;
pub mod export; pub mod export;
pub mod generate; pub mod generate;
#[cfg(feature = "gpg-compat")] #[cfg(feature = "gpg-compat")]
pub mod import_gpg; pub mod import_gpg;
pub mod list; pub mod list;
pub mod delete;
/// A subcommand to allow the management of keys, which can then be used to create, modify, or delete profiles. /// A subcommand to allow the management of keys, which can then be used to create, modify, or delete profiles.
#[derive(Parser)] #[derive(Parser)]

View file

@ -87,7 +87,14 @@ fn main() {
if let Err(e) = cli(parsed) { if let Err(e) = cli(parsed) {
match verbose { match verbose {
true => { true => {
eprintln!("An error occurred while running that command:\n{e:?}"); eprintln!(
"An error occurred while running that command:\n{e:?}\nStack:\n{stack}",
stack = e
.chain()
.map(|entry| format!("\t- {entry}"))
.collect::<Vec<_>>()
.join("\n")
);
} }
false => eprintln!("An error occurred while running that command:\n{e}"), false => eprintln!("An error occurred while running that command:\n{e}"),
} }