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.
This commit is contained in:
iequidoo
2024-07-04 23:42:58 -03:00
committed by iequidoo
parent 4d52aa8b7f
commit 436b00e3cb
2 changed files with 23 additions and 11 deletions

View File

@@ -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<T>(
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::<SignedPublicKey>().is_some() {
"public"
} else if any_key.downcast_ref::<SignedSecretKey>().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))

View File

@@ -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<String, String>)> {
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<SignedPublicKey> {
@@ -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.