Skip to content

Commit 23d95df

Browse files
committed
feat: use v2 SEIPD when sending messages to self
1 parent 6db2cf6 commit 23d95df

File tree

4 files changed

+77
-16
lines changed

4 files changed

+77
-16
lines changed

benches/decrypting.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use deltachat::{
3838
internals_for_benches::key_from_asc,
3939
internals_for_benches::parse_and_get_text,
4040
internals_for_benches::store_self_keypair,
41-
pgp::{KeyPair, decrypt, pk_encrypt, symm_encrypt_message},
41+
pgp::{KeyPair, SeipdVersion, decrypt, pk_encrypt, symm_encrypt_message},
4242
stock_str::StockStrings,
4343
};
4444
use rand::{Rng, rng};
@@ -111,6 +111,7 @@ fn criterion_benchmark(c: &mut Criterion) {
111111
key_pair.secret.clone(),
112112
true,
113113
true,
114+
SeipdVersion::V2,
114115
)
115116
.await
116117
.unwrap()

src/e2ee.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use mail_builder::mime::MimePart;
88
use crate::aheader::{Aheader, EncryptPreference};
99
use crate::context::Context;
1010
use crate::key::{SignedPublicKey, load_self_public_key, load_self_secret_key};
11-
use crate::pgp;
11+
use crate::pgp::{self, SeipdVersion};
1212

1313
#[derive(Debug)]
1414
pub struct EncryptHelper {
@@ -47,6 +47,7 @@ impl EncryptHelper {
4747
mail_to_encrypt: MimePart<'static>,
4848
compress: bool,
4949
anonymous_recipients: bool,
50+
seipd_version: SeipdVersion,
5051
) -> Result<String> {
5152
let sign_key = load_self_secret_key(context).await?;
5253

@@ -60,6 +61,7 @@ impl EncryptHelper {
6061
sign_key,
6162
compress,
6263
anonymous_recipients,
64+
seipd_version,
6365
)
6466
.await?;
6567

src/mimefactory.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use crate::message::{Message, MsgId, Viewtype};
3232
use crate::mimeparser::{SystemMessage, is_hidden};
3333
use crate::param::Param;
3434
use crate::peer_channels::{create_iroh_header, get_iroh_topic_for_msg};
35+
use crate::pgp::SeipdVersion;
3536
use crate::simplify::escape_message_footer_marks;
3637
use crate::stock_str;
3738
use crate::tools::{
@@ -1258,6 +1259,17 @@ impl MimeFactory {
12581259
} else {
12591260
// Asymmetric encryption
12601261

1262+
let seipd_version = if encryption_pubkeys.is_empty() {
1263+
// If message is sent only to self,
1264+
// use v2 SEIPD.
1265+
SeipdVersion::V2
1266+
} else {
1267+
// If message is sent to others,
1268+
// they may not support v2 SEIPD yet,
1269+
// so use v1 SEIPD.
1270+
SeipdVersion::V1
1271+
};
1272+
12611273
// Encrypt to self unconditionally,
12621274
// even for a single-device setup.
12631275
let mut encryption_keyring = vec![encrypt_helper.public_key.clone()];
@@ -1271,6 +1283,7 @@ impl MimeFactory {
12711283
message,
12721284
compress,
12731285
anonymous_recipients,
1286+
seipd_version,
12741287
)
12751288
.await?
12761289
};

src/pgp.rs

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,20 @@ fn select_pk_for_encryption(key: &SignedPublicKey) -> Option<&SignedPublicSubKey
160160
.find(|subkey| subkey.is_encryption_key())
161161
}
162162

163+
/// Version of SEIPD packet to use.
164+
///
165+
/// See
166+
/// <https://www.rfc-editor.org/rfc/rfc9580#name-avoiding-ciphertext-malleab>
167+
/// for the discussion on when v2 SEIPD should be used.
168+
#[derive(Debug)]
169+
pub enum SeipdVersion {
170+
/// Use v1 SEIPD, for compatibility.
171+
V1,
172+
173+
/// Use v2 SEIPD when we know that v2 SEIPD is supported.
174+
V2,
175+
}
176+
163177
/// Encrypts `plain` text using `public_keys_for_encryption`
164178
/// and signs it using `private_key_for_signing`.
165179
pub async fn pk_encrypt(
@@ -168,6 +182,7 @@ pub async fn pk_encrypt(
168182
private_key_for_signing: SignedSecretKey,
169183
compress: bool,
170184
anonymous_recipients: bool,
185+
seipd_version: SeipdVersion,
171186
) -> Result<String> {
172187
Handle::current()
173188
.spawn_blocking(move || {
@@ -178,21 +193,49 @@ pub async fn pk_encrypt(
178193
.filter_map(select_pk_for_encryption);
179194

180195
let msg = MessageBuilder::from_bytes("", plain);
181-
let mut msg = msg.seipd_v1(&mut rng, SYMMETRIC_KEY_ALGORITHM);
182-
for pkey in pkeys {
183-
if anonymous_recipients {
184-
msg.encrypt_to_key_anonymous(&mut rng, &pkey)?;
185-
} else {
186-
msg.encrypt_to_key(&mut rng, &pkey)?;
196+
let encoded_msg = match seipd_version {
197+
SeipdVersion::V1 => {
198+
let mut msg = msg.seipd_v1(&mut rng, SYMMETRIC_KEY_ALGORITHM);
199+
200+
for pkey in pkeys {
201+
if anonymous_recipients {
202+
msg.encrypt_to_key_anonymous(&mut rng, &pkey)?;
203+
} else {
204+
msg.encrypt_to_key(&mut rng, &pkey)?;
205+
}
206+
}
207+
208+
msg.sign(&*private_key_for_signing, Password::empty(), HASH_ALGORITHM);
209+
if compress {
210+
msg.compression(CompressionAlgorithm::ZLIB);
211+
}
212+
213+
msg.to_armored_string(&mut rng, Default::default())?
187214
}
188-
}
189-
190-
msg.sign(&*private_key_for_signing, Password::empty(), HASH_ALGORITHM);
191-
if compress {
192-
msg.compression(CompressionAlgorithm::ZLIB);
193-
}
194-
195-
let encoded_msg = msg.to_armored_string(&mut rng, Default::default())?;
215+
SeipdVersion::V2 => {
216+
let mut msg = msg.seipd_v2(
217+
&mut rng,
218+
SYMMETRIC_KEY_ALGORITHM,
219+
AeadAlgorithm::Ocb,
220+
ChunkSize::C8KiB,
221+
);
222+
223+
for pkey in pkeys {
224+
if anonymous_recipients {
225+
msg.encrypt_to_key_anonymous(&mut rng, &pkey)?;
226+
} else {
227+
msg.encrypt_to_key(&mut rng, &pkey)?;
228+
}
229+
}
230+
231+
msg.sign(&*private_key_for_signing, Password::empty(), HASH_ALGORITHM);
232+
if compress {
233+
msg.compression(CompressionAlgorithm::ZLIB);
234+
}
235+
236+
msg.to_armored_string(&mut rng, Default::default())?
237+
}
238+
};
196239

197240
Ok(encoded_msg)
198241
})
@@ -547,6 +590,7 @@ mod tests {
547590
KEYS.alice_secret.clone(),
548591
compress,
549592
anonymous_recipients,
593+
SeipdVersion::V2,
550594
)
551595
.await
552596
.unwrap()
@@ -716,6 +760,7 @@ mod tests {
716760
KEYS.alice_secret.clone(),
717761
true,
718762
true,
763+
SeipdVersion::V2,
719764
)
720765
.await?;
721766

0 commit comments

Comments
 (0)