mirror of
https://github.com/chatmail/core.git
synced 2026-05-04 05:46:29 +03:00
feat: use v2 SEIPD when sending messages to self
This commit is contained in:
@@ -38,7 +38,7 @@ use deltachat::{
|
|||||||
internals_for_benches::key_from_asc,
|
internals_for_benches::key_from_asc,
|
||||||
internals_for_benches::parse_and_get_text,
|
internals_for_benches::parse_and_get_text,
|
||||||
internals_for_benches::store_self_keypair,
|
internals_for_benches::store_self_keypair,
|
||||||
pgp::{KeyPair, decrypt, pk_encrypt, symm_encrypt_message},
|
pgp::{KeyPair, SeipdVersion, decrypt, pk_encrypt, symm_encrypt_message},
|
||||||
stock_str::StockStrings,
|
stock_str::StockStrings,
|
||||||
};
|
};
|
||||||
use rand::{Rng, rng};
|
use rand::{Rng, rng};
|
||||||
@@ -111,6 +111,7 @@ fn criterion_benchmark(c: &mut Criterion) {
|
|||||||
key_pair.secret.clone(),
|
key_pair.secret.clone(),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
SeipdVersion::V2,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use mail_builder::mime::MimePart;
|
|||||||
use crate::aheader::{Aheader, EncryptPreference};
|
use crate::aheader::{Aheader, EncryptPreference};
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::key::{SignedPublicKey, load_self_public_key, load_self_secret_key};
|
use crate::key::{SignedPublicKey, load_self_public_key, load_self_secret_key};
|
||||||
use crate::pgp;
|
use crate::pgp::{self, SeipdVersion};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EncryptHelper {
|
pub struct EncryptHelper {
|
||||||
@@ -47,6 +47,7 @@ impl EncryptHelper {
|
|||||||
mail_to_encrypt: MimePart<'static>,
|
mail_to_encrypt: MimePart<'static>,
|
||||||
compress: bool,
|
compress: bool,
|
||||||
anonymous_recipients: bool,
|
anonymous_recipients: bool,
|
||||||
|
seipd_version: SeipdVersion,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let sign_key = load_self_secret_key(context).await?;
|
let sign_key = load_self_secret_key(context).await?;
|
||||||
|
|
||||||
@@ -60,6 +61,7 @@ impl EncryptHelper {
|
|||||||
sign_key,
|
sign_key,
|
||||||
compress,
|
compress,
|
||||||
anonymous_recipients,
|
anonymous_recipients,
|
||||||
|
seipd_version,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ use crate::message::{Message, MsgId, Viewtype};
|
|||||||
use crate::mimeparser::{SystemMessage, is_hidden};
|
use crate::mimeparser::{SystemMessage, is_hidden};
|
||||||
use crate::param::Param;
|
use crate::param::Param;
|
||||||
use crate::peer_channels::{create_iroh_header, get_iroh_topic_for_msg};
|
use crate::peer_channels::{create_iroh_header, get_iroh_topic_for_msg};
|
||||||
|
use crate::pgp::SeipdVersion;
|
||||||
use crate::simplify::escape_message_footer_marks;
|
use crate::simplify::escape_message_footer_marks;
|
||||||
use crate::stock_str;
|
use crate::stock_str;
|
||||||
use crate::tools::{
|
use crate::tools::{
|
||||||
@@ -1258,6 +1259,17 @@ impl MimeFactory {
|
|||||||
} else {
|
} else {
|
||||||
// Asymmetric encryption
|
// Asymmetric encryption
|
||||||
|
|
||||||
|
let seipd_version = if encryption_pubkeys.is_empty() {
|
||||||
|
// If message is sent only to self,
|
||||||
|
// use v2 SEIPD.
|
||||||
|
SeipdVersion::V2
|
||||||
|
} else {
|
||||||
|
// If message is sent to others,
|
||||||
|
// they may not support v2 SEIPD yet,
|
||||||
|
// so use v1 SEIPD.
|
||||||
|
SeipdVersion::V1
|
||||||
|
};
|
||||||
|
|
||||||
// Encrypt to self unconditionally,
|
// Encrypt to self unconditionally,
|
||||||
// even for a single-device setup.
|
// even for a single-device setup.
|
||||||
let mut encryption_keyring = vec![encrypt_helper.public_key.clone()];
|
let mut encryption_keyring = vec![encrypt_helper.public_key.clone()];
|
||||||
@@ -1271,6 +1283,7 @@ impl MimeFactory {
|
|||||||
message,
|
message,
|
||||||
compress,
|
compress,
|
||||||
anonymous_recipients,
|
anonymous_recipients,
|
||||||
|
seipd_version,
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
};
|
};
|
||||||
|
|||||||
69
src/pgp.rs
69
src/pgp.rs
@@ -160,6 +160,20 @@ fn select_pk_for_encryption(key: &SignedPublicKey) -> Option<&SignedPublicSubKey
|
|||||||
.find(|subkey| subkey.is_encryption_key())
|
.find(|subkey| subkey.is_encryption_key())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Version of SEIPD packet to use.
|
||||||
|
///
|
||||||
|
/// See
|
||||||
|
/// <https://www.rfc-editor.org/rfc/rfc9580#name-avoiding-ciphertext-malleab>
|
||||||
|
/// for the discussion on when v2 SEIPD should be used.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SeipdVersion {
|
||||||
|
/// Use v1 SEIPD, for compatibility.
|
||||||
|
V1,
|
||||||
|
|
||||||
|
/// Use v2 SEIPD when we know that v2 SEIPD is supported.
|
||||||
|
V2,
|
||||||
|
}
|
||||||
|
|
||||||
/// Encrypts `plain` text using `public_keys_for_encryption`
|
/// Encrypts `plain` text using `public_keys_for_encryption`
|
||||||
/// and signs it using `private_key_for_signing`.
|
/// and signs it using `private_key_for_signing`.
|
||||||
pub async fn pk_encrypt(
|
pub async fn pk_encrypt(
|
||||||
@@ -168,6 +182,7 @@ pub async fn pk_encrypt(
|
|||||||
private_key_for_signing: SignedSecretKey,
|
private_key_for_signing: SignedSecretKey,
|
||||||
compress: bool,
|
compress: bool,
|
||||||
anonymous_recipients: bool,
|
anonymous_recipients: bool,
|
||||||
|
seipd_version: SeipdVersion,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
Handle::current()
|
Handle::current()
|
||||||
.spawn_blocking(move || {
|
.spawn_blocking(move || {
|
||||||
@@ -178,21 +193,49 @@ pub async fn pk_encrypt(
|
|||||||
.filter_map(select_pk_for_encryption);
|
.filter_map(select_pk_for_encryption);
|
||||||
|
|
||||||
let msg = MessageBuilder::from_bytes("", plain);
|
let msg = MessageBuilder::from_bytes("", plain);
|
||||||
let mut msg = msg.seipd_v1(&mut rng, SYMMETRIC_KEY_ALGORITHM);
|
let encoded_msg = match seipd_version {
|
||||||
for pkey in pkeys {
|
SeipdVersion::V1 => {
|
||||||
if anonymous_recipients {
|
let mut msg = msg.seipd_v1(&mut rng, SYMMETRIC_KEY_ALGORITHM);
|
||||||
msg.encrypt_to_key_anonymous(&mut rng, &pkey)?;
|
|
||||||
} else {
|
for pkey in pkeys {
|
||||||
msg.encrypt_to_key(&mut rng, &pkey)?;
|
if anonymous_recipients {
|
||||||
|
msg.encrypt_to_key_anonymous(&mut rng, &pkey)?;
|
||||||
|
} else {
|
||||||
|
msg.encrypt_to_key(&mut rng, &pkey)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.sign(&*private_key_for_signing, Password::empty(), HASH_ALGORITHM);
|
||||||
|
if compress {
|
||||||
|
msg.compression(CompressionAlgorithm::ZLIB);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.to_armored_string(&mut rng, Default::default())?
|
||||||
}
|
}
|
||||||
}
|
SeipdVersion::V2 => {
|
||||||
|
let mut msg = msg.seipd_v2(
|
||||||
|
&mut rng,
|
||||||
|
SYMMETRIC_KEY_ALGORITHM,
|
||||||
|
AeadAlgorithm::Ocb,
|
||||||
|
ChunkSize::C8KiB,
|
||||||
|
);
|
||||||
|
|
||||||
msg.sign(&*private_key_for_signing, Password::empty(), HASH_ALGORITHM);
|
for pkey in pkeys {
|
||||||
if compress {
|
if anonymous_recipients {
|
||||||
msg.compression(CompressionAlgorithm::ZLIB);
|
msg.encrypt_to_key_anonymous(&mut rng, &pkey)?;
|
||||||
}
|
} else {
|
||||||
|
msg.encrypt_to_key(&mut rng, &pkey)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let encoded_msg = msg.to_armored_string(&mut rng, Default::default())?;
|
msg.sign(&*private_key_for_signing, Password::empty(), HASH_ALGORITHM);
|
||||||
|
if compress {
|
||||||
|
msg.compression(CompressionAlgorithm::ZLIB);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.to_armored_string(&mut rng, Default::default())?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(encoded_msg)
|
Ok(encoded_msg)
|
||||||
})
|
})
|
||||||
@@ -547,6 +590,7 @@ mod tests {
|
|||||||
KEYS.alice_secret.clone(),
|
KEYS.alice_secret.clone(),
|
||||||
compress,
|
compress,
|
||||||
anonymous_recipients,
|
anonymous_recipients,
|
||||||
|
SeipdVersion::V2,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -716,6 +760,7 @@ mod tests {
|
|||||||
KEYS.alice_secret.clone(),
|
KEYS.alice_secret.clone(),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
SeipdVersion::V2,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user