From 436b00e3cba09137d6dd53b15202eb5ab0a66dd5 Mon Sep 17 00:00:00 2001 From: iequidoo Date: Thu, 4 Jul 2024 23:42:58 -0300 Subject: [PATCH] feat: Report better error from DcKey::from_asc() (#5539) If no matching key packet was found, report which key is needed to make it clear to the user. --- src/imex.rs | 13 ++++--------- src/key.rs | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/imex.rs b/src/imex.rs index e67241092..0abd979ac 100644 --- a/src/imex.rs +++ b/src/imex.rs @@ -1,6 +1,5 @@ //! # Import/export module. -use std::any::Any; use std::ffi::OsStr; use std::path::{Path, PathBuf}; @@ -731,16 +730,12 @@ async fn export_key_to_asc_file( key: &T, ) -> Result<()> where - T: DcKey + Any, + T: DcKey, { let file_name = { - let any_key = key as &dyn Any; - let kind = if any_key.downcast_ref::().is_some() { - "public" - } else if any_key.downcast_ref::().is_some() { - "private" - } else { - "unknown" + let kind = match T::is_private() { + false => "public", + true => "private", }; let id = id.map_or("default".into(), |i| i.to_string()); dir.join(format!("{}-key-{}.asc", kind, &id)) diff --git a/src/key.rs b/src/key.rs index bb053a95f..b8b9662f0 100644 --- a/src/key.rs +++ b/src/key.rs @@ -4,7 +4,7 @@ use std::collections::BTreeMap; use std::fmt; use std::io::Cursor; -use anyhow::{ensure, Context as _, Result}; +use anyhow::{bail, ensure, Context as _, Result}; use base64::Engine as _; use deltachat_contact_tools::EmailAddress; use num_traits::FromPrimitive; @@ -46,7 +46,14 @@ pub(crate) trait DcKey: Serialize + Deserializable + KeyTrait + Clone { /// the ASCII-armored representation. fn from_asc(data: &str) -> Result<(Self, BTreeMap)> { let bytes = data.as_bytes(); - let (key, headers) = Self::from_armor_single(Cursor::new(bytes)).context("rPGP error")?; + let res = Self::from_armor_single(Cursor::new(bytes)); + let (key, headers) = match res { + Err(pgp::errors::Error::NoMatchingPacket) => match Self::is_private() { + true => bail!("No private key packet found"), + false => bail!("No public key packet found"), + }, + _ => res.context("rPGP error")?, + }; let headers = headers .into_iter() .map(|(key, values)| { @@ -89,6 +96,8 @@ pub(crate) trait DcKey: Serialize + Deserializable + KeyTrait + Clone { fn fingerprint(&self) -> Fingerprint { Fingerprint::new(KeyTrait::fingerprint(self)) } + + fn is_private() -> bool; } pub(crate) async fn load_self_public_key(context: &Context) -> Result { @@ -187,6 +196,10 @@ impl DcKey for SignedPublicKey { .unwrap_or_default(); std::string::String::from_utf8(buf).unwrap_or_default() } + + fn is_private() -> bool { + false + } } impl DcKey for SignedSecretKey { @@ -202,6 +215,10 @@ impl DcKey for SignedSecretKey { .unwrap_or_default(); std::string::String::from_utf8(buf).unwrap_or_default() } + + fn is_private() -> bool { + true + } } /// Deltachat extension trait for secret keys.