summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNora Widdecke <nora@sequoia-pgp.org>2021-02-09 14:58:46 +0100
committerNora Widdecke <nora@sequoia-pgp.org>2021-04-13 12:38:16 +0200
commitd9c64350e210b3d9fde378029285bbdb6848a475 (patch)
tree83163f26a42804f995840a4c5d853a2285e2c15e
parentf8bbf6f27f259662bbb9bfca6b399445d44019c0 (diff)
bench: Add encrypt+sign and decrypt+verify.
-rw-r--r--openpgp/Cargo.toml8
-rw-r--r--openpgp/benches/common/decrypt.rs114
-rw-r--r--openpgp/benches/common/encrypt.rs44
-rw-r--r--openpgp/benches/decrypt_message.rs5
-rw-r--r--openpgp/benches/decrypt_verify_message.rs51
-rw-r--r--openpgp/benches/encrypt_sign_message.rs47
-rw-r--r--openpgp/tests/data/keys/recipient.pgp34
-rw-r--r--openpgp/tests/data/keys/sender.pgp34
8 files changed, 309 insertions, 28 deletions
diff --git a/openpgp/Cargo.toml b/openpgp/Cargo.toml
index 1710ba31..e8851369 100644
--- a/openpgp/Cargo.toml
+++ b/openpgp/Cargo.toml
@@ -100,3 +100,11 @@ harness = false
[[bench]]
name = "decrypt_message"
harness = false
+
+[[bench]]
+name = "encrypt_sign_message"
+harness = false
+
+[[bench]]
+name = "decrypt_verify_message"
+harness = false
diff --git a/openpgp/benches/common/decrypt.rs b/openpgp/benches/common/decrypt.rs
index 48f157c5..fa507aa7 100644
--- a/openpgp/benches/common/decrypt.rs
+++ b/openpgp/benches/common/decrypt.rs
@@ -1,20 +1,22 @@
-use sequoia_openpgp::cert::Cert;
-use sequoia_openpgp::crypto::{Password, SessionKey};
-use sequoia_openpgp::packet::prelude::*;
-use sequoia_openpgp::packet::{PKESK, SKESK};
-use sequoia_openpgp::parse::stream::{
- DecryptionHelper, DecryptorBuilder, MessageStructure, VerificationHelper,
+use sequoia_openpgp as openpgp;
+use openpgp::cert::Cert;
+use openpgp::crypto::{Password, SessionKey};
+use openpgp::packet::prelude::*;
+use openpgp::packet::{PKESK, SKESK};
+use openpgp::parse::stream::{
+ DecryptionHelper, DecryptorBuilder, MessageLayer, MessageStructure,
+ VerificationHelper, VerificationError
};
-use sequoia_openpgp::parse::Parse;
-use sequoia_openpgp::policy::StandardPolicy;
-use sequoia_openpgp::types::SymmetricAlgorithm;
-use sequoia_openpgp::{Fingerprint, KeyHandle, Result};
+use openpgp::parse::Parse;
+use openpgp::policy::StandardPolicy;
+use openpgp::types::SymmetricAlgorithm;
+use openpgp::{Fingerprint, KeyHandle, Result};
use std::io::Write;
// Borrowed from the examples at
-// sequoia_openpgp::parse::stream::DecryptionHelper
-// sequoia_openpgp::parse::stream::Decryptor
+// openpgp::parse::stream::DecryptionHelper
+// openpgp::parse::stream::Decryptor
struct PasswordHelper {
password: Password,
}
@@ -62,7 +64,7 @@ pub fn decrypt_with_password(
sink: &mut dyn Write,
ciphertext: &[u8],
password: &str,
-) -> sequoia_openpgp::Result<()> {
+) -> openpgp::Result<()> {
let password = password.into();
// Make a helper that that feeds the password to the decryptor.
let helper = PasswordHelper { password };
@@ -79,17 +81,49 @@ pub fn decrypt_with_password(
}
// Borrowed from the examples at
-// sequoia_openpgp::parse::stream::DecryptionHelper
-// sequoia_openpgp::parse::stream::Decryptor
+// openpgp::parse::stream::DecryptionHelper
+// openpgp::parse::stream::Decryptor
struct CertHelper<'a> {
- cert: &'a Cert,
+ sender: Option<&'a Cert>,
+ recipient: &'a Cert,
}
impl VerificationHelper for CertHelper<'_> {
+ // get candidates for having created the signature
fn get_certs(&mut self, _ids: &[KeyHandle]) -> Result<Vec<Cert>> {
- Ok(Vec::new())
+ let mut certs = Vec::new();
+ // maybe check that the cert matches (one of the) ids
+ if let Some(sender) = self.sender {
+ certs.push(sender.clone());
+ }
+ Ok(certs)
}
- fn check(&mut self, _structure: MessageStructure) -> Result<()> {
+ // does the signature match the policy
+ // e.g. am I the intended recipient
+ fn check(&mut self, structure: MessageStructure) -> Result<()> {
+ for (i, layer) in structure.into_iter().enumerate() {
+ match layer {
+ MessageLayer::Encryption { .. } if i == 0 => (),
+ MessageLayer::Compression { .. } if i == 1 => (),
+ MessageLayer::SignatureGroup { ref results }
+ if i == 1 || i == 2 =>
+ {
+ if !results.iter().any(|r| r.is_ok()) {
+ for result in results {
+ let error = result.as_ref().err().unwrap();
+ println!("{:?}", error);
+ }
+ return Err(anyhow::anyhow!("No valid signature"));
+ }
+ }
+ _ => {
+ return Err(anyhow::anyhow!(
+ "Unexpected message structure {:?}",
+ layer
+ ))
+ }
+ }
+ }
Ok(())
}
}
@@ -107,10 +141,8 @@ impl DecryptionHelper for CertHelper<'_> {
{
let p = &StandardPolicy::new();
- // check that pkesk has right recipient
- // if yes, use decrypt function
- let keys: Vec<Key<key::SecretParts, key::UnspecifiedRole>> = self
- .cert
+ let cand_secret_keys: Vec<Key<key::SecretParts, key::UnspecifiedRole>> = self
+ .recipient
.keys()
.with_policy(p, None)
.for_transport_encryption()
@@ -119,7 +151,9 @@ impl DecryptionHelper for CertHelper<'_> {
.map(|amalgamation| amalgamation.key().clone().into())
.collect();
- let successful_key = keys
+ // check that pkesk has right recipient
+ // if yes, use decrypt function
+ let successful_key = cand_secret_keys
.iter()
.cloned()
.filter_map(|key| {
@@ -152,9 +186,39 @@ pub fn decrypt_with_cert(
sink: &mut dyn Write,
ciphertext: &[u8],
cert: &Cert,
-) -> sequoia_openpgp::Result<()> {
+) -> openpgp::Result<()> {
+ // Make a helper that that feeds the password to the decryptor.
+ let helper = CertHelper {
+ sender: None,
+ recipient: cert,
+ };
+
+ // Now, create a decryptor with a helper using the given Certs.
+ let p = &StandardPolicy::new();
+ let mut decryptor = DecryptorBuilder::from_bytes(ciphertext)?
+ .with_policy(p, None, helper)?;
+
+ // Decrypt the data.
+ std::io::copy(&mut decryptor, sink)?;
+
+ Ok(())
+}
+
+// This is marked as dead_code. Seems that using a function only from within
+// a benchmark loop hides it from the compiler.
+#[allow(dead_code)]
+// Decrypts the given message using the given password.
+pub fn decrypt_and_verify(
+ sink: &mut dyn Write,
+ ciphertext: &[u8],
+ sender: &Cert,
+ recipient: &Cert,
+) -> openpgp::Result<()> {
// Make a helper that that feeds the password to the decryptor.
- let helper = CertHelper { cert };
+ let helper = CertHelper {
+ sender: Some(sender),
+ recipient,
+ };
// Now, create a decryptor with a helper using the given Certs.
let p = &StandardPolicy::new();
diff --git a/openpgp/benches/common/encrypt.rs b/openpgp/benches/common/encrypt.rs
index 0b5c94d7..edd898b5 100644
--- a/openpgp/benches/common/encrypt.rs
+++ b/openpgp/benches/common/encrypt.rs
@@ -1,7 +1,9 @@
use sequoia_openpgp as openpgp;
use openpgp::cert::Cert;
use openpgp::policy::StandardPolicy;
-use openpgp::serialize::stream::{Encryptor, LiteralWriter, Message};
+use openpgp::serialize::stream::{
+ padding::Padder, Armorer, Encryptor, LiteralWriter, Message, Signer,
+};
use std::io::Write;
@@ -27,6 +29,46 @@ pub fn encrypt_to_cert(
Ok(sink)
}
+// naively encrypt and sign, without caring for revocation or expiration
+pub fn encrypt_to_cert_and_sign(
+ bytes: &[u8],
+ sender: &Cert,
+ recipient: &Cert,
+) -> openpgp::Result<Vec<u8>> {
+ let mut sink = vec![];
+
+ let p = &StandardPolicy::new();
+ let signing_keypair = sender
+ .keys()
+ .with_policy(p, None)
+ .secret()
+ .for_signing()
+ .nth(0)
+ .unwrap()
+ .key()
+ .clone()
+ .into_keypair()?;
+
+ let recipients = recipient
+ .keys()
+ .with_policy(p, None)
+ .supported()
+ .for_transport_encryption()
+ .for_storage_encryption();
+
+ let message = Message::new(&mut sink);
+ let message = Armorer::new(message).build()?;
+ let message = Encryptor::for_recipients(message, recipients).build()?;
+ let message = Padder::new(message).build()?;
+ let message = Signer::new(message, signing_keypair)
+ //.add_intended_recipient(&recipient)
+ .build()?;
+ let mut w = LiteralWriter::new(message).build()?;
+ w.write_all(bytes)?;
+ w.finalize()?;
+ Ok(sink)
+}
+
pub fn encrypt_with_password(
bytes: &[u8],
password: &str,
diff --git a/openpgp/benches/decrypt_message.rs b/openpgp/benches/decrypt_message.rs
index b59fb550..23987fc3 100644
--- a/openpgp/benches/decrypt_message.rs
+++ b/openpgp/benches/decrypt_message.rs
@@ -2,8 +2,9 @@ use criterion::{
criterion_group, criterion_main, BenchmarkId, Criterion, Throughput,
};
-use sequoia_openpgp::cert::Cert;
-use sequoia_openpgp::parse::Parse;
+use sequoia_openpgp as openpgp;
+use openpgp::cert::Cert;
+use openpgp::parse::Parse;
mod common;
use common::decrypt;
diff --git a/openpgp/benches/decrypt_verify_message.rs b/openpgp/benches/decrypt_verify_message.rs
new file mode 100644
index 00000000..33f15c3e
--- /dev/null
+++ b/openpgp/benches/decrypt_verify_message.rs
@@ -0,0 +1,51 @@
+use criterion::{
+ criterion_group, criterion_main, BenchmarkId, Criterion, Throughput,
+};
+
+use sequoia_openpgp as openpgp;
+use openpgp::cert::Cert;
+use openpgp::parse::Parse;
+
+mod common;
+use common::decrypt;
+use common::encrypt;
+
+lazy_static::lazy_static! {
+ static ref SENDER: Cert =
+ Cert::from_bytes(&include_bytes!("../tests/data/keys/sender.pgp")[..])
+ .unwrap();
+ static ref RECIPIENT: Cert =
+ Cert::from_bytes(&include_bytes!("../tests/data/keys/recipient.pgp")[..])
+ .unwrap();
+ static ref ZEROS_1_MB: Vec<u8> = vec![0; 1 * 1024 * 1024];
+ static ref ZEROS_10_MB: Vec<u8> = vec![0; 10 * 1024 * 1024];
+}
+
+fn decrypt_and_verify(bytes: &[u8], sender: &Cert, recipient: &Cert) {
+ let mut sink = Vec::new();
+ decrypt::decrypt_and_verify(&mut sink, &bytes, sender, recipient).unwrap();
+}
+
+fn bench_decrypt_verify(c: &mut Criterion) {
+ let mut group = c.benchmark_group("decrypt and verify message");
+
+ // Encrypt a very short, medium and very long message,
+ // and then benchmark decryption.
+ let messages = &[b"Hello world.", &ZEROS_1_MB[..], &ZEROS_10_MB[..]];
+
+ messages.iter().for_each(|m| {
+ let encrypted =
+ encrypt::encrypt_to_cert_and_sign(m, &SENDER, &RECIPIENT).unwrap();
+ group.throughput(Throughput::Bytes(encrypted.len() as u64));
+ group.bench_with_input(
+ BenchmarkId::new("decrypt and verify", m.len()),
+ &encrypted,
+ |b, e| b.iter(|| decrypt_and_verify(&e, &SENDER, &RECIPIENT)),
+ );
+ });
+
+ group.finish();
+}
+
+criterion_group!(benches, bench_decrypt_verify);
+criterion_main!(benches);
diff --git a/openpgp/benches/encrypt_sign_message.rs b/openpgp/benches/encrypt_sign_message.rs
new file mode 100644
index 00000000..03916f71
--- /dev/null
+++ b/openpgp/benches/encrypt_sign_message.rs
@@ -0,0 +1,47 @@
+use criterion::{
+ criterion_group, criterion_main, BenchmarkId, Criterion, Throughput,
+};
+
+use sequoia_openpgp as openpgp;
+use openpgp::cert::Cert;
+use openpgp::parse::Parse;
+
+mod common;
+use common::encrypt;
+
+lazy_static::lazy_static! {
+ static ref ZEROS_1_MB: Vec<u8> = vec![0; 1 * 1024 * 1024];
+ static ref ZEROS_10_MB: Vec<u8> = vec![0; 10 * 1024 * 1024];
+}
+
+pub fn encrypt_to_donald_sign_by_ivanka(bytes: &[u8]) {
+ let sender = Cert::from_bytes(
+ &include_bytes!("../tests/data/keys/ivanka-private.gpg")[..],
+ )
+ .unwrap();
+ let recipient = Cert::from_bytes(
+ &include_bytes!("../tests/data/keys/the-donald-private.gpg")[..],
+ )
+ .unwrap();
+ encrypt::encrypt_to_cert_and_sign(bytes, &sender, &recipient).unwrap();
+}
+
+fn bench_encrypt_sign(c: &mut Criterion) {
+ let mut group = c.benchmark_group("encrypt and sign message");
+
+ // Encrypt a very short, medium and very long message.
+ let messages = &[b"Hello world.", &ZEROS_1_MB[..], &ZEROS_10_MB[..]];
+
+ for message in messages {
+ group.throughput(Throughput::Bytes(message.len() as u64));
+ group.bench_with_input(
+ BenchmarkId::new("encrypt and sign", message.len()),
+ &message,
+ |b, m| b.iter(|| encrypt_to_donald_sign_by_ivanka(&m)),
+ );
+ }
+ group.finish();
+}
+
+criterion_group!(benches, bench_encrypt_sign);
+criterion_main!(benches);
diff --git a/openpgp/tests/data/keys/recipient.pgp b/openpgp/tests/data/keys/recipient.pgp
new file mode 100644
index 00000000..6ca9c75d
--- /dev/null
+++ b/openpgp/tests/data/keys/recipient.pgp
@@ -0,0 +1,34 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Comment: 5CF6 06BD 495F 956D FCB2 7ECC F1AB A7B5 80AC CEA4
+Comment: <recipient@example.com>
+
+xVgEYCPsqRYJKwYBBAHaRw8BAQdAyl+b2R+JeEfZ31BuDWeGiFAy8eY94qCVc7qF
+u/rvtXYAAQCfwQXpLpl+IfcV3ZUEihbhMA9asAGJi2j4FoVBRxI9VA08wsALBB8W
+CgB9BYJgI+ypAwsJBwkQ8auntYCszqRHFAAAAAAAHgAgc2FsdEBub3RhdGlvbnMu
+c2VxdW9pYS1wZ3Aub3JnkBdVl2KuiH68rzSswYrKhIrUqWqGvVdRyRV6f733btID
+FQoIApsBAh4BFiEEXPYGvUlflW38sn7M8auntYCszqQAAAvPAP9lC6JGGFXKWov6
+p+SZKq6qL83meOZQ54dBCq38h/zuTwD/eYjBNeNwSazSI+Qu9YD5YuJRgONTmUNP
+Sgz5swMj5gTNFzxyZWNpcGllbnRAZXhhbXBsZS5jb20+wsAOBBMWCgCABYJgI+yp
+AwsJBwkQ8auntYCszqRHFAAAAAAAHgAgc2FsdEBub3RhdGlvbnMuc2VxdW9pYS1w
+Z3Aub3JnofcsAmtPZEK1hy0wdsSoSFFyB77Z0hCce9ntDVvoLuUDFQoIApkBApsB
+Ah4BFiEEXPYGvUlflW38sn7M8auntYCszqQAAG6vAP43PGtJlVZFx/Mjk+VLK8Y2
+rHeEslPPI0QbmQweIY7+igD/RkJU2WpL8TS2bhEk4gGD93cr+Yx9d34rzcDuRDI/
+3gjHWARgI+ypFgkrBgEEAdpHDwEBB0BVlAiKHOzhsAh9R4bdzayASc1xCQg6iRpS
+9CEGgxrJmAABAIXd7slG2jRbHTdrsCIP4FUqaC3XLOXBVNOMRF40nx8hDm7CwMIE
+GBYKATQFgmAj7KkJEPGrp7WArM6kRxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNl
+cXVvaWEtcGdwLm9yZ5QTcp0kytebTq8hEkY+lzYH9XFHfcIgOCRKKBBJKq14ApsC
+Ah4BvqAEGRYKAG8FgmAj7KkJEBpj51UNI+Y4RxQAAAAAAB4AIHNhbHRAbm90YXRp
+b25zLnNlcXVvaWEtcGdwLm9yZ6EvXHFWkX0SxwyNW4IA/fjYbP1OtH9FKOZ8fyOs
+hrLYFiEEF4/e0UMm/i0EBI7GGmPnVQ0j5jgAANGlAP0UiVrwDe9hpJqkvzSCuWZ3
+dcRFN99oDr6wxmori3zUdQD+MSglK7p0HadqwWAKBXsXYWxDNXOb7shyl4fP8DCU
+jQ4WIQRc9ga9SV+Vbfyyfszxq6e1gKzOpAAALosBAI+CEzGmb+RowPzQX8GmpJsU
+cpdCHOs7m0oVMq93Yh/WAP9l20ZKarqyqqh4ce5c/ElSMwEAOzp1EOoiTQzCJM2S
+DMddBGAj7KkSCisGAQQBl1UBBQEBB0BZC7zH6V3bbQ3egHS/Jq/cWV2vkoswpt1A
+qzEwRC/CDQMBCAkAAP9rIgacMmlwbILiWz0gOkdk7rzPBVgLh4+IYaYBq2ZbEA2p
+wsADBBgWCgB1BYJgI+ypCRDxq6e1gKzOpEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u
+cy5zZXF1b2lhLXBncC5vcmf3RzS0xBiVO+HAWnEH6SGYc5MRgyAO1bNr1SYwEWLL
+egKbDAIeARYhBFz2Br1JX5Vt/LJ+zPGrp7WArM6kAADRRQD+P4o3cQP72K1Zj3F1
+OTmQZK5gbokA6pRlL+cXND1kX8wBAL9aVpcPIEictRneZHT9xytDwjW9LRKEteSi
+vjF27ooN
+=EzWF
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/openpgp/tests/data/keys/sender.pgp b/openpgp/tests/data/keys/sender.pgp
new file mode 100644
index 00000000..d6189f58
--- /dev/null
+++ b/openpgp/tests/data/keys/sender.pgp
@@ -0,0 +1,34 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Comment: C9CE CC00 2086 58E6 183D A1C6 AB27 F577 2E0E 7843
+Comment: <sender@example.com>
+
+xVgEYCPsxRYJKwYBBAHaRw8BAQdAUYZaTFKQNbjjRYLzTwy3Q8bB0NTFtgvf+XCA
+IrCGlmQAAQC+mWrY1zkvlOUzTM86YCXHVv+17ANSxcQWcdRT06O8XhE4wsALBB8W
+CgB9BYJgI+zFAwsJBwkQqyf1dy4OeENHFAAAAAAAHgAgc2FsdEBub3RhdGlvbnMu
+c2VxdW9pYS1wZ3Aub3JnWXvgQQecnMWO/fYncaPEbcZfKx4gDAexicJP7jqTYroD
+FQoIApsBAh4BFiEEyc7MACCGWOYYPaHGqyf1dy4OeEMAAL/kAQCphI/dOFGLoyM8
+nylwNNsR4eMwY2R+FQeg5/fa2hVw2QEA4bQLA3NV7ipe/NjhTr2Jg7VJOMTRRkz6
+8mN/x6QGxgTNFDxzZW5kZXJAZXhhbXBsZS5jb20+wsAOBBMWCgCABYJgI+zFAwsJ
+BwkQqyf1dy4OeENHFAAAAAAAHgAgc2FsdEBub3RhdGlvbnMuc2VxdW9pYS1wZ3Au
+b3JnIXF3QU6P6+GXFwbQEECgzntsyO8gvXlLepy/ucn+vYoDFQoIApkBApsBAh4B
+FiEEyc7MACCGWOYYPaHGqyf1dy4OeEMAAEjUAQCFIkopGT8XtynPC8EK8xGUUDIQ
+r2iMHo8hWUj54P05dwEAz21A3Zsfri2aJCFm6PF/PI1lgveOhIkmymPHn4u0HgDH
+WARgI+zFFgkrBgEEAdpHDwEBB0CVc1gpEwyJwcfrKthXOf8Etrbyu5PYowQ4VjCf
+USIWsAABAP3mLXdK97WvUtw4EB3C7Eco9W++7tlz6qvJg+qwW4YVEqrCwMIEGBYK
+ATQFgmAj7MUJEKsn9XcuDnhDRxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVv
+aWEtcGdwLm9yZyztCZP7RO0A16UDnaBGz5INoSUHpMfKK1qxNjliywEMApsCAh4B
+vqAEGRYKAG8FgmAj7MUJEJmUVZwG7s2BRxQAAAAAAB4AIHNhbHRAbm90YXRpb25z
+LnNlcXVvaWEtcGdwLm9yZ7S9NDPI3eUn/BpxSx/4hVGWIZw4lOcQK2Kh9jrhC6WD
+FiEEN7I0OVSvcntqZncCmZRVnAbuzYEAAML+AQCIcsXZ2eFMp29lZXubgWhu/A6+
+9s31IuaoxlfTq+mLJQEAhRkzX14wAInsjW0mU/ZOWYjgtqvQNv+MI0CjQdpEAwcW
+IQTJzswAIIZY5hg9ocarJ/V3Lg54QwAAU6YBAOOBEW6s61h+PJ1uai5tdPuAf0Zv
+YxG3MIYDolq5lXeGAQDyV6bwplTWAQycLo1X5+41Bt83NtxVOE4beqsV+/9TBcdd
+BGAj7MUSCisGAQQBl1UBBQEBB0AbjB79xZ0YRFyoiGFHC4dFWbGy4V+SfwsFl/fD
+vLhTRQMBCAkAAP9h4mp41OcmJVpHhX7aBdWBMYwnrDklRBRBkMgY3qcMYA7rwsAD
+BBgWCgB1BYJgI+zFCRCrJ/V3Lg54Q0cUAAAAAAAeACBzYWx0QG5vdGF0aW9ucy5z
+ZXF1b2lhLXBncC5vcmf1V+e7SqWcmY8cvjM69asiI1ja4oZDZ3OV4r8Wkqs2dgKb
+DAIeARYhBMnOzAAghljmGD2hxqsn9XcuDnhDAADlYwD+P3oMVWOsWhKkWrutqbgW
+Ozik7yeh1H90w5I2XHNFtVIA/1dW/azFsqrNHf8ZFmmfGsJ3h/MePsz/ao4BJ69v
+CsAI
+=lNEM
+-----END PGP PRIVATE KEY BLOCK-----