refactor: replace DcKey.load_self trait method with functions

This commit is contained in:
link2xt
2023-07-27 18:23:56 +00:00
parent c55a3d3873
commit 9b9703a48e
8 changed files with 77 additions and 97 deletions

View File

@@ -25,7 +25,7 @@ use crate::config::Config;
use crate::constants::{Blocked, Chattype, DC_GCL_ADD_SELF, DC_GCL_VERIFIED_ONLY}; use crate::constants::{Blocked, Chattype, DC_GCL_ADD_SELF, DC_GCL_VERIFIED_ONLY};
use crate::context::Context; use crate::context::Context;
use crate::events::EventType; use crate::events::EventType;
use crate::key::{DcKey, SignedPublicKey}; use crate::key::{load_self_public_key, DcKey};
use crate::login_param::LoginParam; use crate::login_param::LoginParam;
use crate::message::MessageState; use crate::message::MessageState;
use crate::mimeparser::AvatarAction; use crate::mimeparser::AvatarAction;
@@ -1009,7 +1009,7 @@ impl Contact {
let finger_prints = stock_str::finger_prints(context).await; let finger_prints = stock_str::finger_prints(context).await;
ret += &format!("{stock_message}.\n{finger_prints}:"); ret += &format!("{stock_message}.\n{finger_prints}:");
let fingerprint_self = SignedPublicKey::load_self(context) let fingerprint_self = load_self_public_key(context)
.await? .await?
.fingerprint() .fingerprint()
.to_string(); .to_string();

View File

@@ -19,7 +19,7 @@ use crate::constants::DC_VERSION_STR;
use crate::contact::Contact; use crate::contact::Contact;
use crate::debug_logging::DebugLogging; use crate::debug_logging::DebugLogging;
use crate::events::{Event, EventEmitter, EventType, Events}; use crate::events::{Event, EventEmitter, EventType, Events};
use crate::key::{DcKey, SignedPublicKey}; use crate::key::{load_self_public_key, DcKey as _};
use crate::login_param::LoginParam; use crate::login_param::LoginParam;
use crate::message::{self, MessageState, MsgId}; use crate::message::{self, MessageState, MsgId};
use crate::quota::QuotaInfo; use crate::quota::QuotaInfo;
@@ -580,7 +580,7 @@ impl Context {
.sql .sql
.count("SELECT COUNT(*) FROM acpeerstates;", ()) .count("SELECT COUNT(*) FROM acpeerstates;", ())
.await?; .await?;
let fingerprint_str = match SignedPublicKey::load_self(self).await { let fingerprint_str = match load_self_public_key(self).await {
Ok(key) => key.fingerprint().hex(), Ok(key) => key.fingerprint().hex(),
Err(err) => format!("<key failure: {err}>"), Err(err) => format!("<key failure: {err}>"),
}; };

View File

@@ -6,7 +6,7 @@ use num_traits::FromPrimitive;
use crate::aheader::{Aheader, EncryptPreference}; use crate::aheader::{Aheader, EncryptPreference};
use crate::config::Config; use crate::config::Config;
use crate::context::Context; use crate::context::Context;
use crate::key::{DcKey, SignedPublicKey, SignedSecretKey}; use crate::key::{load_self_public_key, load_self_secret_key, SignedPublicKey};
use crate::peerstate::{Peerstate, PeerstateVerifiedStatus}; use crate::peerstate::{Peerstate, PeerstateVerifiedStatus};
use crate::pgp; use crate::pgp;
@@ -23,7 +23,7 @@ impl EncryptHelper {
EncryptPreference::from_i32(context.get_config_int(Config::E2eeEnabled).await?) EncryptPreference::from_i32(context.get_config_int(Config::E2eeEnabled).await?)
.unwrap_or_default(); .unwrap_or_default();
let addr = context.get_primary_self_addr().await?; let addr = context.get_primary_self_addr().await?;
let public_key = SignedPublicKey::load_self(context).await?; let public_key = load_self_public_key(context).await?;
Ok(EncryptHelper { Ok(EncryptHelper {
prefer_encrypt, prefer_encrypt,
@@ -115,7 +115,7 @@ impl EncryptHelper {
keyring.push(key); keyring.push(key);
} }
keyring.push(self.public_key.clone()); keyring.push(self.public_key.clone());
let sign_key = SignedSecretKey::load_self(context).await?; let sign_key = load_self_secret_key(context).await?;
let raw_message = mail_to_encrypt.build().as_string().into_bytes(); let raw_message = mail_to_encrypt.build().as_string().into_bytes();
@@ -131,7 +131,7 @@ impl EncryptHelper {
context: &Context, context: &Context,
mail: lettre_email::PartBuilder, mail: lettre_email::PartBuilder,
) -> Result<(lettre_email::MimeMessage, String)> { ) -> Result<(lettre_email::MimeMessage, String)> {
let sign_key = SignedSecretKey::load_self(context).await?; let sign_key = load_self_secret_key(context).await?;
let mime_message = mail.build(); let mime_message = mail.build();
let signature = pgp::pk_calc_signature(mime_message.as_string().as_bytes(), &sign_key)?; let signature = pgp::pk_calc_signature(mime_message.as_string().as_bytes(), &sign_key)?;
Ok((mime_message, signature)) Ok((mime_message, signature))
@@ -146,7 +146,7 @@ impl EncryptHelper {
/// private key will be present. /// private key will be present.
// TODO, remove this once deltachat::key::Key no longer exists. // TODO, remove this once deltachat::key::Key no longer exists.
pub async fn ensure_secret_key_exists(context: &Context) -> Result<()> { pub async fn ensure_secret_key_exists(context: &Context) -> Result<()> {
SignedPublicKey::load_self(context).await?; load_self_public_key(context).await?;
Ok(()) Ok(())
} }
@@ -154,6 +154,7 @@ pub async fn ensure_secret_key_exists(context: &Context) -> Result<()> {
mod tests { mod tests {
use super::*; use super::*;
use crate::chat; use crate::chat;
use crate::key::DcKey;
use crate::message::{Message, Viewtype}; use crate::message::{Message, Viewtype};
use crate::param::Param; use crate::param::Param;
use crate::test_utils::{bob_keypair, TestContext}; use crate::test_utils::{bob_keypair, TestContext};

View File

@@ -19,7 +19,9 @@ use crate::contact::ContactId;
use crate::context::Context; use crate::context::Context;
use crate::e2ee; use crate::e2ee;
use crate::events::EventType; use crate::events::EventType;
use crate::key::{self, DcKey, DcSecretKey, SignedPublicKey, SignedSecretKey}; use crate::key::{
self, load_self_secret_key, DcKey, DcSecretKey, SignedPublicKey, SignedSecretKey,
};
use crate::log::LogExt; use crate::log::LogExt;
use crate::message::{Message, MsgId, Viewtype}; use crate::message::{Message, MsgId, Viewtype};
use crate::mimeparser::SystemMessage; use crate::mimeparser::SystemMessage;
@@ -186,7 +188,7 @@ pub async fn render_setup_file(context: &Context, passphrase: &str) -> Result<St
} else { } else {
bail!("Passphrase must be at least 2 chars long."); bail!("Passphrase must be at least 2 chars long.");
}; };
let private_key = SignedSecretKey::load_self(context).await?; let private_key = load_self_secret_key(context).await?;
let ac_headers = match context.get_config_bool(Config::E2eeEnabled).await? { let ac_headers = match context.get_config_bool(Config::E2eeEnabled).await? {
false => None, false => None,
true => Some(("Autocrypt-Prefer-Encrypt", "mutual")), true => Some(("Autocrypt-Prefer-Encrypt", "mutual")),

View File

@@ -3,11 +3,9 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fmt; use std::fmt;
use std::io::Cursor; use std::io::Cursor;
use std::pin::Pin;
use anyhow::{ensure, Context as _, Result}; use anyhow::{ensure, Context as _, Result};
use base64::Engine as _; use base64::Engine as _;
use futures::Future;
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
use pgp::composed::Deserializable; use pgp::composed::Deserializable;
pub use pgp::composed::{SignedPublicKey, SignedSecretKey}; pub use pgp::composed::{SignedPublicKey, SignedSecretKey};
@@ -49,11 +47,6 @@ pub trait DcKey: Serialize + Deserializable + KeyTrait + Clone {
Self::from_armor_single(Cursor::new(bytes)).context("rPGP error") Self::from_armor_single(Cursor::new(bytes)).context("rPGP error")
} }
/// Load the users' default key from the database.
fn load_self<'a>(
context: &'a Context,
) -> Pin<Box<dyn Future<Output = Result<Self>> + 'a + Send>>;
/// Serialise the key as bytes. /// Serialise the key as bytes.
fn to_bytes(&self) -> Vec<u8> { fn to_bytes(&self) -> Vec<u8> {
// Not using Serialize::to_bytes() to make clear *why* it is // Not using Serialize::to_bytes() to make clear *why* it is
@@ -84,22 +77,15 @@ pub trait DcKey: Serialize + Deserializable + KeyTrait + Clone {
} }
} }
impl DcKey for SignedPublicKey { pub(crate) async fn load_self_public_key(context: &Context) -> Result<SignedPublicKey> {
fn load_self<'a>(
context: &'a Context,
) -> Pin<Box<dyn Future<Output = Result<Self>> + 'a + Send>> {
Box::pin(async move {
let addr = context.get_primary_self_addr().await?;
match context match context
.sql .sql
.query_row_optional( .query_row_optional(
r#" r#"SELECT public_key
SELECT public_key
FROM keypairs FROM keypairs
WHERE addr=? WHERE addr=(SELECT value FROM config WHERE keyname="configured_addr")
AND is_default=1; AND is_default=1"#,
"#, (),
(addr,),
|row| { |row| {
let bytes: Vec<u8> = row.get(0)?; let bytes: Vec<u8> = row.get(0)?;
Ok(bytes) Ok(bytes)
@@ -107,15 +93,39 @@ impl DcKey for SignedPublicKey {
) )
.await? .await?
{ {
Some(bytes) => Self::from_slice(&bytes), Some(bytes) => SignedPublicKey::from_slice(&bytes),
None => { None => {
let keypair = generate_keypair(context).await?; let keypair = generate_keypair(context).await?;
Ok(keypair.public) Ok(keypair.public)
} }
} }
}) }
}
pub(crate) async fn load_self_secret_key(context: &Context) -> Result<SignedSecretKey> {
match context
.sql
.query_row_optional(
r#"SELECT private_key
FROM keypairs
WHERE addr=(SELECT value FROM config WHERE keyname="configured_addr")
AND is_default=1"#,
(),
|row| {
let bytes: Vec<u8> = row.get(0)?;
Ok(bytes)
},
)
.await?
{
Some(bytes) => SignedSecretKey::from_slice(&bytes),
None => {
let keypair = generate_keypair(context).await?;
Ok(keypair.secret)
}
}
}
impl DcKey for SignedPublicKey {
fn to_asc(&self, header: Option<(&str, &str)>) -> String { fn to_asc(&self, header: Option<(&str, &str)>) -> String {
// Not using .to_armored_string() to make clear *why* it is // Not using .to_armored_string() to make clear *why* it is
// safe to ignore this error. // safe to ignore this error.
@@ -134,36 +144,6 @@ impl DcKey for SignedPublicKey {
} }
impl DcKey for SignedSecretKey { impl DcKey for SignedSecretKey {
fn load_self<'a>(
context: &'a Context,
) -> Pin<Box<dyn Future<Output = Result<Self>> + 'a + Send>> {
Box::pin(async move {
match context
.sql
.query_row_optional(
r#"
SELECT private_key
FROM keypairs
WHERE addr=(SELECT value FROM config WHERE keyname="configured_addr")
AND is_default=1;
"#,
(),
|row| {
let bytes: Vec<u8> = row.get(0)?;
Ok(bytes)
},
)
.await?
{
Some(bytes) => Self::from_slice(&bytes),
None => {
let keypair = generate_keypair(context).await?;
Ok(keypair.secret)
}
}
})
}
fn to_asc(&self, header: Option<(&str, &str)>) -> String { fn to_asc(&self, header: Option<(&str, &str)>) -> String {
// Not using .to_armored_string() to make clear *why* it is // Not using .to_armored_string() to make clear *why* it is
// safe to do these unwraps. // safe to do these unwraps.
@@ -521,9 +501,9 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD
async fn test_load_self_existing() { async fn test_load_self_existing() {
let alice = alice_keypair(); let alice = alice_keypair();
let t = TestContext::new_alice().await; let t = TestContext::new_alice().await;
let pubkey = SignedPublicKey::load_self(&t).await.unwrap(); let pubkey = load_self_public_key(&t).await.unwrap();
assert_eq!(alice.public, pubkey); assert_eq!(alice.public, pubkey);
let seckey = SignedSecretKey::load_self(&t).await.unwrap(); let seckey = load_self_secret_key(&t).await.unwrap();
assert_eq!(alice.secret, seckey); assert_eq!(alice.secret, seckey);
} }
@@ -533,7 +513,7 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD
t.set_config(Config::ConfiguredAddr, Some("alice@example.org")) t.set_config(Config::ConfiguredAddr, Some("alice@example.org"))
.await .await
.unwrap(); .unwrap();
let key = SignedPublicKey::load_self(&t).await; let key = load_self_public_key(&t).await;
assert!(key.is_ok()); assert!(key.is_ok());
} }
@@ -543,7 +523,7 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD
t.set_config(Config::ConfiguredAddr, Some("alice@example.org")) t.set_config(Config::ConfiguredAddr, Some("alice@example.org"))
.await .await
.unwrap(); .unwrap();
let key = SignedSecretKey::load_self(&t).await; let key = load_self_secret_key(&t).await;
assert!(key.is_ok()); assert!(key.is_ok());
} }
@@ -560,7 +540,7 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD
thread::spawn(move || { thread::spawn(move || {
tokio::runtime::Runtime::new() tokio::runtime::Runtime::new()
.unwrap() .unwrap()
.block_on(SignedPublicKey::load_self(&ctx)) .block_on(load_self_public_key(&ctx))
}) })
}; };
let thr1 = { let thr1 = {
@@ -568,7 +548,7 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD
thread::spawn(move || { thread::spawn(move || {
tokio::runtime::Runtime::new() tokio::runtime::Runtime::new()
.unwrap() .unwrap()
.block_on(SignedPublicKey::load_self(&ctx)) .block_on(load_self_public_key(&ctx))
}) })
}; };
let res0 = thr0.join().unwrap(); let res0 = thr0.join().unwrap();

View File

@@ -27,7 +27,7 @@ use crate::decrypt::{
use crate::dehtml::dehtml; use crate::dehtml::dehtml;
use crate::events::EventType; use crate::events::EventType;
use crate::headerdef::{HeaderDef, HeaderDefMap}; use crate::headerdef::{HeaderDef, HeaderDefMap};
use crate::key::{DcKey, Fingerprint, SignedPublicKey, SignedSecretKey}; use crate::key::{load_self_secret_key, DcKey, Fingerprint, SignedPublicKey};
use crate::message::{self, set_msg_failed, update_msg_state, MessageState, MsgId, Viewtype}; use crate::message::{self, set_msg_failed, update_msg_state, MessageState, MsgId, Viewtype};
use crate::param::{Param, Params}; use crate::param::{Param, Params};
use crate::peerstate::Peerstate; use crate::peerstate::Peerstate;
@@ -275,7 +275,7 @@ impl MimeMessage {
headers.remove("chat-verified"); headers.remove("chat-verified");
let from = from.context("No from in message")?; let from = from.context("No from in message")?;
let private_keyring = vec![SignedSecretKey::load_self(context) let private_keyring = vec![load_self_secret_key(context)
.await .await
.context("Failed to get own key")?]; .context("Failed to get own key")?];

View File

@@ -14,7 +14,7 @@ use crate::context::Context;
use crate::e2ee::ensure_secret_key_exists; use crate::e2ee::ensure_secret_key_exists;
use crate::events::EventType; use crate::events::EventType;
use crate::headerdef::HeaderDef; use crate::headerdef::HeaderDef;
use crate::key::{DcKey, Fingerprint, SignedPublicKey}; use crate::key::{load_self_public_key, DcKey, Fingerprint};
use crate::message::{Message, Viewtype}; use crate::message::{Message, Viewtype};
use crate::mimeparser::{MimeMessage, SystemMessage}; use crate::mimeparser::{MimeMessage, SystemMessage};
use crate::param::Param; use crate::param::Param;
@@ -130,7 +130,7 @@ pub async fn get_securejoin_qr(context: &Context, group: Option<ChatId>) -> Resu
} }
async fn get_self_fingerprint(context: &Context) -> Option<Fingerprint> { async fn get_self_fingerprint(context: &Context) -> Option<Fingerprint> {
match SignedPublicKey::load_self(context).await { match load_self_public_key(context).await {
Ok(key) => Some(key.fingerprint()), Ok(key) => Some(key.fingerprint()),
Err(_) => { Err(_) => {
warn!(context, "get_self_fingerprint(): failed to load key"); warn!(context, "get_self_fingerprint(): failed to load key");
@@ -884,10 +884,7 @@ mod tests {
"vc-request-with-auth" "vc-request-with-auth"
); );
assert!(msg.get_header(HeaderDef::SecureJoinAuth).is_some()); assert!(msg.get_header(HeaderDef::SecureJoinAuth).is_some());
let bob_fp = SignedPublicKey::load_self(&bob.ctx) let bob_fp = load_self_public_key(&bob.ctx).await.unwrap().fingerprint();
.await
.unwrap()
.fingerprint();
assert_eq!( assert_eq!(
*msg.get_header(HeaderDef::SecureJoinFingerprint).unwrap(), *msg.get_header(HeaderDef::SecureJoinFingerprint).unwrap(),
bob_fp.hex() bob_fp.hex()
@@ -1029,7 +1026,7 @@ mod tests {
let bob = tcm.bob().await; let bob = tcm.bob().await;
// Ensure Bob knows Alice_FP // Ensure Bob knows Alice_FP
let alice_pubkey = SignedPublicKey::load_self(&alice.ctx).await?; let alice_pubkey = load_self_public_key(&alice.ctx).await?;
let peerstate = Peerstate { let peerstate = Peerstate {
addr: "alice@example.org".into(), addr: "alice@example.org".into(),
last_seen: 10, last_seen: 10,
@@ -1083,7 +1080,7 @@ mod tests {
"vc-request-with-auth" "vc-request-with-auth"
); );
assert!(msg.get_header(HeaderDef::SecureJoinAuth).is_some()); assert!(msg.get_header(HeaderDef::SecureJoinAuth).is_some());
let bob_fp = SignedPublicKey::load_self(&bob.ctx).await?.fingerprint(); let bob_fp = load_self_public_key(&bob.ctx).await?.fingerprint();
assert_eq!( assert_eq!(
*msg.get_header(HeaderDef::SecureJoinFingerprint).unwrap(), *msg.get_header(HeaderDef::SecureJoinFingerprint).unwrap(),
bob_fp.hex() bob_fp.hex()
@@ -1254,7 +1251,7 @@ mod tests {
"vg-request-with-auth" "vg-request-with-auth"
); );
assert!(msg.get_header(HeaderDef::SecureJoinAuth).is_some()); assert!(msg.get_header(HeaderDef::SecureJoinAuth).is_some());
let bob_fp = SignedPublicKey::load_self(&bob.ctx).await?.fingerprint(); let bob_fp = load_self_public_key(&bob.ctx).await?.fingerprint();
assert_eq!( assert_eq!(
*msg.get_header(HeaderDef::SecureJoinFingerprint).unwrap(), *msg.get_header(HeaderDef::SecureJoinFingerprint).unwrap(),
bob_fp.hex() bob_fp.hex()

View File

@@ -17,7 +17,7 @@ use crate::contact::{Contact, Origin};
use crate::context::Context; use crate::context::Context;
use crate::events::EventType; use crate::events::EventType;
use crate::headerdef::HeaderDef; use crate::headerdef::HeaderDef;
use crate::key::{DcKey, SignedPublicKey}; use crate::key::{load_self_public_key, DcKey};
use crate::message::{Message, Viewtype}; use crate::message::{Message, Viewtype};
use crate::mimeparser::{MimeMessage, SystemMessage}; use crate::mimeparser::{MimeMessage, SystemMessage};
use crate::param::Param; use crate::param::Param;
@@ -448,7 +448,7 @@ async fn send_handshake_message(
}; };
// Sends our own fingerprint in the Secure-Join-Fingerprint header. // Sends our own fingerprint in the Secure-Join-Fingerprint header.
let bob_fp = SignedPublicKey::load_self(context).await?.fingerprint(); let bob_fp = load_self_public_key(context).await?.fingerprint();
msg.param.set(Param::Arg3, bob_fp.hex()); msg.param.set(Param::Arg3, bob_fp.hex());
// Sends the grpid in the Secure-Join-Group header. // Sends the grpid in the Secure-Join-Group header.