diff --git a/benches/decrypting.rs b/benches/decrypting.rs index 5d233cde5..9a5088fcd 100644 --- a/benches/decrypting.rs +++ b/benches/decrypting.rs @@ -38,7 +38,7 @@ use deltachat::{ internals_for_benches::key_from_asc, internals_for_benches::parse_and_get_text, internals_for_benches::store_self_keypair, - pgp::{KeyPair, SeipdVersion, decrypt, pk_encrypt, symm_encrypt_message}, + pgp::{SeipdVersion, decrypt, pk_encrypt, symm_encrypt_message}, stock_str::StockStrings, }; use rand::{Rng, rng}; @@ -58,9 +58,7 @@ async fn create_context() -> Context { .await .unwrap(); let secret = key_from_asc(include_str!("../test-data/key/bob-secret.asc")).unwrap(); - let public = secret.to_public_key(); - let key_pair = KeyPair { public, secret }; - store_self_keypair(&context, &key_pair) + store_self_keypair(&context, &secret) .await .expect("Failed to save key"); @@ -83,7 +81,7 @@ fn criterion_benchmark(c: &mut Criterion) { let secret = secrets[NUM_SECRETS / 2].clone(); symm_encrypt_message( plain.clone(), - create_dummy_keypair("alice@example.org").unwrap().secret, + create_dummy_keypair("alice@example.org").unwrap(), black_box(&secret), true, ) @@ -107,8 +105,8 @@ fn criterion_benchmark(c: &mut Criterion) { let encrypted = tokio::runtime::Runtime::new().unwrap().block_on(async { pk_encrypt( plain.clone(), - vec![black_box(key_pair.public.clone())], - key_pair.secret.clone(), + vec![black_box(key_pair.clone().to_public_key())], + key_pair.clone(), true, true, SeipdVersion::V2, @@ -120,7 +118,7 @@ fn criterion_benchmark(c: &mut Criterion) { b.iter(|| { let mut msg = decrypt( encrypted.clone().into_bytes(), - std::slice::from_ref(&key_pair.secret), + std::slice::from_ref(&key_pair), black_box(&secrets), ) .unwrap(); diff --git a/src/imex.rs b/src/imex.rs index 33386aa02..166053b52 100644 --- a/src/imex.rs +++ b/src/imex.rs @@ -21,7 +21,6 @@ use crate::e2ee; use crate::events::EventType; use crate::key::{self, DcKey, SignedSecretKey}; use crate::log::{LogExt, warn}; -use crate::pgp; use crate::qr::DCBACKUP_VERSION; use crate::sql; use crate::tools::{ @@ -142,19 +141,13 @@ pub async fn has_backup(_context: &Context, dir_name: &Path) -> Result { } async fn set_self_key(context: &Context, armored: &str) -> Result<()> { - let private_key = SignedSecretKey::from_asc(armored)?; - let public_key = private_key.to_public_key(); - - let keypair = pgp::KeyPair { - public: public_key, - secret: private_key, - }; - key::store_self_keypair(context, &keypair).await?; + let secret_key = SignedSecretKey::from_asc(armored)?; + key::store_self_keypair(context, &secret_key).await?; info!( context, "stored self key: {:?}", - keypair.secret.public_key().legacy_key_id() + secret_key.public_key().legacy_key_id() ); Ok(()) } @@ -825,7 +818,7 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_export_public_key_to_asc_file() { let context = TestContext::new().await; - let key = alice_keypair().public; + let key = alice_keypair().to_public_key(); let blobdir = Path::new("$BLOBDIR"); let filename = export_key_to_asc_file(&context.ctx, blobdir, "a@b", None, &key) .await @@ -842,7 +835,7 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_import_private_key_exported_to_asc_file() { let context = TestContext::new().await; - let key = alice_keypair().secret; + let key = alice_keypair(); let blobdir = Path::new("$BLOBDIR"); let filename = export_key_to_asc_file(&context.ctx, blobdir, "a@b", None, &key) .await diff --git a/src/internals_for_benches.rs b/src/internals_for_benches.rs index 61fc9d7fc..67db0e88e 100644 --- a/src/internals_for_benches.rs +++ b/src/internals_for_benches.rs @@ -10,13 +10,12 @@ use crate::key; use crate::key::DcKey; use crate::mimeparser::MimeMessage; use crate::pgp; -use crate::pgp::KeyPair; pub fn key_from_asc(data: &str) -> Result { key::SignedSecretKey::from_asc(data) } -pub async fn store_self_keypair(context: &Context, keypair: &KeyPair) -> Result<()> { +pub async fn store_self_keypair(context: &Context, keypair: &key::SignedSecretKey) -> Result<()> { key::store_self_keypair(context, keypair).await } @@ -29,7 +28,7 @@ pub async fn save_broadcast_secret(context: &Context, chat_id: ChatId, secret: & crate::chat::save_broadcast_secret(context, chat_id, secret).await } -pub fn create_dummy_keypair(addr: &str) -> Result { +pub fn create_dummy_keypair(addr: &str) -> Result { pgp::create_keypair(EmailAddress::new(addr)?) } diff --git a/src/key.rs b/src/key.rs index 97da1170f..3473aabe1 100644 --- a/src/key.rs +++ b/src/key.rs @@ -16,7 +16,6 @@ use tokio::runtime::Handle; use crate::context::Context; use crate::events::EventType; use crate::log::LogExt; -use crate::pgp::KeyPair; use crate::tools::{self, time_elapsed}; /// Convenience trait for working with keys. @@ -150,8 +149,8 @@ pub(crate) async fn load_self_public_key(context: &Context) -> Result Ok(public_key), None => { - let keypair = generate_keypair(context).await?; - Ok(keypair.public) + let signed_secret_key = generate_keypair(context).await?; + Ok(signed_secret_key.to_public_key()) } } } @@ -216,8 +215,8 @@ pub(crate) async fn load_self_secret_key(context: &Context) -> Result SignedSecretKey::from_slice(&bytes), None => { - let keypair = generate_keypair(context).await?; - Ok(keypair.secret) + let secret = generate_keypair(context).await?; + Ok(secret) } } } @@ -296,7 +295,7 @@ impl DcKey for SignedSecretKey { } } -async fn generate_keypair(context: &Context) -> Result { +async fn generate_keypair(context: &Context) -> Result { let addr = context.get_primary_self_addr().await?; let addr = EmailAddress::new(&addr)?; let _guard = context.generating_key_mutex.lock().await; @@ -322,7 +321,7 @@ async fn generate_keypair(context: &Context) -> Result { } } -pub(crate) async fn load_keypair(context: &Context) -> Result> { +pub(crate) async fn load_keypair(context: &Context) -> Result> { let res = context .sql .query_row_optional( @@ -343,7 +342,7 @@ pub(crate) async fn load_keypair(context: &Context) -> Result> { None }; - Ok(signed_secret_key.map(KeyPair::new)) + Ok(signed_secret_key) } /// Stores own keypair in the database and sets it as a default. @@ -351,13 +350,17 @@ pub(crate) async fn load_keypair(context: &Context) -> Result> { /// Fails if we already have a key, so it is not possible to /// have more than one key for new setups. Existing setups /// may still have more than one key for compatibility. -pub(crate) async fn store_self_keypair(context: &Context, keypair: &KeyPair) -> Result<()> { +pub(crate) async fn store_self_keypair( + context: &Context, + signed_secret_key: &SignedSecretKey, +) -> Result<()> { + let signed_public_key = signed_secret_key.to_public_key(); let mut config_cache_lock = context.sql.config_cache.write().await; let new_key_id = context .sql .transaction(|transaction| { - let public_key = DcKey::to_bytes(&keypair.public); - let secret_key = DcKey::to_bytes(&keypair.secret); + let public_key = DcKey::to_bytes(&signed_public_key); + let secret_key = DcKey::to_bytes(signed_secret_key); // private_key and public_key columns // are UNIQUE since migration 107, @@ -395,9 +398,7 @@ pub(crate) async fn store_self_keypair(context: &Context, keypair: &KeyPair) -> /// Use import/export APIs instead. pub async fn preconfigure_keypair(context: &Context, secret_data: &str) -> Result<()> { let secret = SignedSecretKey::from_asc(secret_data)?; - let public = secret.to_public_key(); - let keypair = KeyPair { public, secret }; - store_self_keypair(context, &keypair).await?; + store_self_keypair(context, &secret).await?; Ok(()) } @@ -476,7 +477,7 @@ mod tests { use crate::config::Config; use crate::test_utils::{TestContext, alice_keypair}; - static KEYPAIR: LazyLock = LazyLock::new(alice_keypair); + static KEYPAIR: LazyLock = LazyLock::new(alice_keypair); #[test] fn test_from_armored_string() { @@ -546,12 +547,12 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD #[test] fn test_asc_roundtrip() { - let key = KEYPAIR.public.clone(); + let key = KEYPAIR.clone().to_public_key(); let asc = key.to_asc(Some(("spam", "ham"))); let key2 = SignedPublicKey::from_asc(&asc).unwrap(); assert_eq!(key, key2); - let key = KEYPAIR.secret.clone(); + let key = KEYPAIR.clone(); let asc = key.to_asc(Some(("spam", "ham"))); let key2 = SignedSecretKey::from_asc(&asc).unwrap(); assert_eq!(key, key2); @@ -559,8 +560,8 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD #[test] fn test_from_slice_roundtrip() { - let public_key = KEYPAIR.public.clone(); - let private_key = KEYPAIR.secret.clone(); + let private_key = KEYPAIR.clone(); + let public_key = KEYPAIR.clone().to_public_key(); let binary = DcKey::to_bytes(&public_key); let public_key2 = SignedPublicKey::from_slice(&binary).expect("invalid public key"); @@ -602,7 +603,7 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD b"\x02\xfc\xaa".as_slice(), b"\x01\x02\x03\x04\x05".as_slice(), ] { - let private_key = KEYPAIR.secret.clone(); + let private_key = KEYPAIR.clone(); let mut binary = DcKey::to_bytes(&private_key); binary.extend(garbage); @@ -616,7 +617,7 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD #[test] fn test_base64_roundtrip() { - let key = KEYPAIR.public.clone(); + let key = KEYPAIR.clone().to_public_key(); let base64 = key.to_base64(); let key2 = SignedPublicKey::from_base64(&base64).unwrap(); assert_eq!(key, key2); diff --git a/src/pgp.rs b/src/pgp.rs index 882d5d040..a72f396ce 100644 --- a/src/pgp.rs +++ b/src/pgp.rs @@ -63,34 +63,11 @@ pub fn split_armored_data(buf: &[u8]) -> Result<(BlockType, BTreeMap Self { - let public = secret.to_public_key(); - Self { public, secret } - } -} - /// Create a new key pair. /// /// Both secret and public key consist of signing primary key and encryption subkey /// as [described in the Autocrypt standard](https://autocrypt.org/level1.html#openpgp-based-key-data). -pub(crate) fn create_keypair(addr: EmailAddress) -> Result { +pub(crate) fn create_keypair(addr: EmailAddress) -> Result { let signing_key_type = PgpKeyType::Ed25519Legacy; let encryption_key_type = PgpKeyType::ECDH(ECCCurve::Curve25519); @@ -135,12 +112,7 @@ pub(crate) fn create_keypair(addr: EmailAddress) -> Result { .verify_bindings() .context("Invalid secret key generated")?; - let key_pair = KeyPair::new(secret_key); - key_pair - .public - .verify_bindings() - .context("Invalid public key generated")?; - Ok(key_pair) + Ok(secret_key) } /// Selects a subkey of the public key to use for encryption. @@ -596,7 +568,7 @@ mod tests { fn test_create_keypair() { let keypair0 = create_keypair(EmailAddress::new("foo@bar.de").unwrap()).unwrap(); let keypair1 = create_keypair(EmailAddress::new("two@zwo.de").unwrap()).unwrap(); - assert_ne!(keypair0.public, keypair1.public); + assert_ne!(keypair0.public_key(), keypair1.public_key()); } /// [SignedSecretKey] and [SignedPublicKey] objects @@ -613,10 +585,10 @@ mod tests { let alice = alice_keypair(); let bob = bob_keypair(); TestKeys { - alice_secret: alice.secret.clone(), - alice_public: alice.public, - bob_secret: bob.secret.clone(), - bob_public: bob.public, + alice_secret: alice.clone(), + alice_public: alice.to_public_key(), + bob_secret: bob.clone(), + bob_public: bob.to_public_key(), } } } diff --git a/src/test_utils.rs b/src/test_utils.rs index bbef12acc..6f86a06d7 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -15,6 +15,7 @@ use async_channel::{self as channel, Receiver, Sender}; use chat::ChatItem; use deltachat_contact_tools::{ContactAddress, EmailAddress}; use nu_ansi_term::Color; +use pgp::composed::SignedSecretKey; use pretty_assertions::assert_eq; use tempfile::{TempDir, tempdir}; use tokio::runtime::Handle; @@ -37,7 +38,6 @@ use crate::log::warn; use crate::login_param::EnteredLoginParam; use crate::message::{Message, MessageState, MsgId, update_msg_state}; use crate::mimeparser::{MimeMessage, SystemMessage}; -use crate::pgp::KeyPair; use crate::receive_imf::receive_imf; use crate::securejoin::{get_securejoin_qr, join_securejoin}; use crate::stock_str::StockStrings; @@ -301,7 +301,7 @@ impl TestContextManager { /// Builder for the [TestContext]. #[derive(Debug, Clone, Default)] pub struct TestContextBuilder { - key_pair: Option, + key_pair: Option, /// Log sink if set. /// @@ -364,11 +364,11 @@ impl TestContextBuilder { self.with_key_pair(fiona_keypair()) } - /// Configures the new [`TestContext`] with the provided [`KeyPair`]. + /// Configures the new [`TestContext`] with the provided [`SignedSecretKey`]. /// /// This will extract the email address from the key and configure the context with the /// given identity. - pub fn with_key_pair(mut self, key_pair: KeyPair) -> Self { + pub fn with_key_pair(mut self, key_pair: SignedSecretKey) -> Self { self.key_pair = Some(key_pair); self } @@ -396,7 +396,7 @@ impl TestContextBuilder { pub async fn build(self, used_names: Option<&mut BTreeSet>) -> TestContext { if let Some(key_pair) = self.key_pair { let userid = { - let public_key = &key_pair.public; + let public_key = key_pair.to_public_key(); let id_bstr = public_key.details.users.first().unwrap().id.id(); String::from_utf8(id_bstr.to_vec()).unwrap() }; @@ -1352,62 +1352,43 @@ impl SentMessage<'_> { /// This saves CPU cycles by avoiding having to generate a key. /// /// The keypair was created using the crate::key::tests::gen_key test. -pub fn alice_keypair() -> KeyPair { - let secret = - key::SignedSecretKey::from_asc(include_str!("../test-data/key/alice-secret.asc")).unwrap(); - let public = secret.to_public_key(); - KeyPair { public, secret } +pub fn alice_keypair() -> SignedSecretKey { + key::SignedSecretKey::from_asc(include_str!("../test-data/key/alice-secret.asc")).unwrap() } /// Load a pre-generated keypair for bob@example.net from disk. /// /// Like [alice_keypair] but a different key and identity. -pub fn bob_keypair() -> KeyPair { - let secret = - key::SignedSecretKey::from_asc(include_str!("../test-data/key/bob-secret.asc")).unwrap(); - let public = secret.to_public_key(); - KeyPair { public, secret } +pub fn bob_keypair() -> SignedSecretKey { + key::SignedSecretKey::from_asc(include_str!("../test-data/key/bob-secret.asc")).unwrap() } /// Load a pre-generated keypair for charlie@example.net from disk. /// /// Like [alice_keypair] but a different key and identity. -pub fn charlie_keypair() -> KeyPair { - let secret = - key::SignedSecretKey::from_asc(include_str!("../test-data/key/charlie-secret.asc")) - .unwrap(); - let public = secret.to_public_key(); - KeyPair { public, secret } +pub fn charlie_keypair() -> SignedSecretKey { + key::SignedSecretKey::from_asc(include_str!("../test-data/key/charlie-secret.asc")).unwrap() } /// Load a pre-generated keypair for dom@example.net from disk. /// /// Like [alice_keypair] but a different key and identity. -pub fn dom_keypair() -> KeyPair { - let secret = - key::SignedSecretKey::from_asc(include_str!("../test-data/key/dom-secret.asc")).unwrap(); - let public = secret.to_public_key(); - KeyPair { public, secret } +pub fn dom_keypair() -> SignedSecretKey { + key::SignedSecretKey::from_asc(include_str!("../test-data/key/dom-secret.asc")).unwrap() } /// Load a pre-generated keypair for elena@example.net from disk. /// /// Like [alice_keypair] but a different key and identity. -pub fn elena_keypair() -> KeyPair { - let secret = - key::SignedSecretKey::from_asc(include_str!("../test-data/key/elena-secret.asc")).unwrap(); - let public = secret.to_public_key(); - KeyPair { public, secret } +pub fn elena_keypair() -> SignedSecretKey { + key::SignedSecretKey::from_asc(include_str!("../test-data/key/elena-secret.asc")).unwrap() } /// Load a pre-generated keypair for fiona@example.net from disk. /// /// Like [alice_keypair] but a different key and identity. -pub fn fiona_keypair() -> KeyPair { - let secret = - key::SignedSecretKey::from_asc(include_str!("../test-data/key/fiona-secret.asc")).unwrap(); - let public = secret.to_public_key(); - KeyPair { public, secret } +pub fn fiona_keypair() -> SignedSecretKey { + key::SignedSecretKey::from_asc(include_str!("../test-data/key/fiona-secret.asc")).unwrap() } /// Utility to help wait for and retrieve events.