diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2019-03-15 13:45:49 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-03-15 13:48:22 +0100 |
commit | b95bc8181893d14ac3b692157471d1736a3a6fd4 (patch) | |
tree | 3779ea4cc4ea481475c86607d815578d75ea17d8 /guide | |
parent | 2a170e370fc371994ceed4134fbb10fcadd05810 (diff) |
guide: New chapter about message signing and verification.
- Also add a new example about message signing and verification.
- Fixes #217.
Diffstat (limited to 'guide')
-rw-r--r-- | guide/src/chapter_01.md | 541 | ||||
-rw-r--r-- | guide/src/chapter_02.md | 716 | ||||
-rw-r--r-- | guide/src/chapter_03.md | 221 |
3 files changed, 1010 insertions, 468 deletions
diff --git a/guide/src/chapter_01.md b/guide/src/chapter_01.md index 5db1cbdc..ec980998 100644 --- a/guide/src/chapter_01.md +++ b/guide/src/chapter_01.md @@ -1,20 +1,20 @@ -Describes key creation, encryption, and decryption. +Describes key creation, signing and verification. In this chapter, we will see how to use Sequoia's [low-level API] to -generate an OpenPGP key, and use it to encrypt and decrypt some data. -We will construct this program from top to bottom, concatenating the -fragments yields the [`openpgp/examples/generate-encrypt-decrypt.rs`]. +generate an OpenPGP key, and use it to sign and verify some data. We +will construct this program from top to bottom, concatenating the +fragments yields the [`openpgp/examples/generate-sign-verify.rs`]. [low-level API]: ../../sequoia_openpgp/index.html -[`openpgp/examples/generate-encrypt-decrypt.rs`]: https://gitlab.com/sequoia-pgp/sequoia/blob/master/openpgp/examples/generate-encrypt-decrypt.rs +[`openpgp/examples/generate-sign-verify.rs`]: https://gitlab.com/sequoia-pgp/sequoia/blob/master/openpgp/examples/generate-sign-verify.rs ```rust use std::io::{self, Write}; +extern crate failure; extern crate sequoia_openpgp as openpgp; use openpgp::serialize::stream::*; use openpgp::parse::stream::*; -use openpgp::packet::key::SecretKey; const MESSAGE: &'static str = "дружба"; @@ -22,22 +22,22 @@ fn main() { // Generate a key. let key = generate().unwrap(); - // Encrypt the message. - let mut ciphertext = Vec::new(); - encrypt(&mut ciphertext, MESSAGE, &key).unwrap(); + // Sign the message. + let mut signed_message = Vec::new(); + sign(&mut signed_message, MESSAGE, &key).unwrap(); - // Decrypt the message. + // Verify the message. let mut plaintext = Vec::new(); - decrypt(&mut plaintext, &ciphertext, &key).unwrap(); + verify(&mut plaintext, &signed_message, &key).unwrap(); assert_eq!(MESSAGE.as_bytes(), &plaintext[..]); } # -# /// Generates an encryption-capable key. +# /// Generates an signing-capable key. # fn generate() -> openpgp::Result<openpgp::TPK> { # let (tpk, _revocation) = openpgp::tpk::TPKBuilder::default() # .add_userid("someone@example.org") -# .add_encryption_subkey() +# .add_signing_subkey() # .generate()?; # # // Save the revocation certificate somewhere. @@ -45,23 +45,24 @@ fn main() { # Ok(tpk) # } # -# /// Encrypts the given message. -# fn encrypt(sink: &mut Write, plaintext: &str, recipient: &openpgp::TPK) +# /// Signs the given message. +# fn sign(sink: &mut Write, plaintext: &str, tsk: &openpgp::TPK) # -> openpgp::Result<()> { +# // Get the keypair to do the signing from the TPK. +# let mut keypair = tsk.keys_valid().signing_capable().nth(0).unwrap().2 +# .clone().into_keypair()?; +# # // Start streaming an OpenPGP message. # let message = Message::new(sink); # -# // We want to encrypt a literal data packet. -# let encryptor = Encryptor::new(message, -# &[], // No symmetric encryption. -# &[recipient], -# EncryptionMode::ForTransport)?; +# // We want to sign a literal data packet. +# let signer = Signer::new(message, vec![&mut keypair])?; # # // Emit a literal data packet. # let mut literal_writer = LiteralWriter::new( -# encryptor, openpgp::constants::DataFormat::Binary, None, None)?; +# signer, openpgp::constants::DataFormat::Binary, None, None)?; # -# // Encrypt the data. +# // Sign the data. # literal_writer.write_all(plaintext.as_bytes())?; # # // Finalize the OpenPGP message to make sure that all data is @@ -71,68 +72,60 @@ fn main() { # Ok(()) # } # -# /// Decrypts the given message. -# fn decrypt(sink: &mut Write, ciphertext: &[u8], recipient: &openpgp::TPK) -# -> openpgp::Result<()> { -# // Make a helper that that feeds the recipient's secret key to the -# // decryptor. +# /// Verifies the given message. +# fn verify(sink: &mut Write, signed_message: &[u8], sender: &openpgp::TPK) +# -> openpgp::Result<()> { +# // Make a helper that that feeds the sender's public key to the +# // verifier. # let helper = Helper { -# secret: recipient, +# tpk: sender, # }; # -# // Now, create a decryptor with a helper using the given TPKs. -# let mut decryptor = Decryptor::from_bytes(ciphertext, helper)?; +# // Now, create a verifier with a helper using the given TPKs. +# let mut verifier = Verifier::from_bytes(signed_message, helper)?; # -# // Decrypt the data. -# io::copy(&mut decryptor, sink)?; +# // Verify the data. +# io::copy(&mut verifier, sink)?; # # Ok(()) # } # # struct Helper<'a> { -# secret: &'a openpgp::TPK, +# tpk: &'a openpgp::TPK, # } # # impl<'a> VerificationHelper for Helper<'a> { # fn get_public_keys(&mut self, _ids: &[openpgp::KeyID]) # -> openpgp::Result<Vec<openpgp::TPK>> { # // Return public keys for signature verification here. -# Ok(Vec::new()) +# Ok(vec![self.tpk.clone()]) # } # -# fn check(&mut self, _sigs: Vec<Vec<VerificationResult>>) +# fn check(&mut self, sigs: Vec<Vec<VerificationResult>>) # -> openpgp::Result<()> { -# // Implement your signature verification policy here. -# Ok(()) -# } -# } -# -# impl<'a> DecryptionHelper for Helper<'a> { -# fn get_secret(&mut self, -# _pkesks: &[&openpgp::packet::PKESK], -# _skesks: &[&openpgp::packet::SKESK]) -# -> openpgp::Result<Option<Secret>> -# { -# // The encryption key is the first and only subkey. -# let key = self.secret.subkeys().nth(0) -# .map(|binding| binding.subkey().clone()) -# .unwrap(); -# -# // The secret key is not encrypted. -# let secret = -# if let Some(SecretKey::Unencrypted { -# ref mpis, -# }) = key.secret() { -# mpis.clone() -# } else { -# unreachable!() -# }; -# -# Ok(Some(Secret::Asymmetric { -# identity: self.secret.fingerprint(), -# key: key, -# secret: secret, -# })) +# // In this function, we implement our signature verification +# // policy. +# +# // First, we are interested in signatures over the data, +# // i.e. level 0 signatures. +# let sigs_over_data = sigs.get(0) +# .ok_or_else(|| failure::err_msg("No level 0 signatures found"))?; +# +# // Now, let's see if there is a signature on that level. +# let sig_result = sigs_over_data.get(0) +# .ok_or_else(|| failure::err_msg("No signature found"))?; +# +# // Finally, given a VerificationResult, which only says +# // whether the signature checks out mathematically, we apply +# // our policy. +# match sig_result { +# VerificationResult::GoodChecksum(_) => +# Ok(()), // Good signature +# VerificationResult::MissingKey(_) => +# Err(failure::err_msg("Missing key to verify signature")), +# VerificationResult::BadChecksum(_) => +# Err(failure::err_msg("Bad signature")), +# } # } # } ``` @@ -140,7 +133,7 @@ fn main() { # Key generation First, we need to generate a new key. This key shall have one user -id, and one encryption-capable subkey. We use the [`TPKBuilder`] to +id, and one signing-capable subkey. We use the [`TPKBuilder`] to create it: [`TPKBuilder`]: ../../sequoia_openpgp/tpk/struct.TPKBuilder.html @@ -148,10 +141,10 @@ create it: ```rust # use std::io::{self, Write}; # +# extern crate failure; # extern crate sequoia_openpgp as openpgp; # use openpgp::serialize::stream::*; # use openpgp::parse::stream::*; -# use openpgp::packet::key::SecretKey; # # const MESSAGE: &'static str = "дружба"; # @@ -159,22 +152,22 @@ create it: # // Generate a key. # let key = generate().unwrap(); # -# // Encrypt the message. -# let mut ciphertext = Vec::new(); -# encrypt(&mut ciphertext, MESSAGE, &key).unwrap(); +# // Sign the message. +# let mut signed_message = Vec::new(); +# sign(&mut signed_message, MESSAGE, &key).unwrap(); # -# // Decrypt the message. +# // Verify the message. # let mut plaintext = Vec::new(); -# decrypt(&mut plaintext, &ciphertext, &key).unwrap(); +# verify(&mut plaintext, &signed_message, &key).unwrap(); # # assert_eq!(MESSAGE.as_bytes(), &plaintext[..]); # } # -/// Generates an encryption-capable key. +/// Generates an signing-capable key. fn generate() -> openpgp::Result<openpgp::TPK> { let (tpk, _revocation) = openpgp::tpk::TPKBuilder::default() .add_userid("someone@example.org") - .add_encryption_subkey() + .add_signing_subkey() .generate()?; // Save the revocation certificate somewhere. @@ -182,23 +175,24 @@ fn generate() -> openpgp::Result<openpgp::TPK> { Ok(tpk) } # -# /// Encrypts the given message. -# fn encrypt(sink: &mut Write, plaintext: &str, recipient: &openpgp::TPK) +# /// Signs the given message. +# fn sign(sink: &mut Write, plaintext: &str, tsk: &openpgp::TPK) # -> openpgp::Result<()> { +# // Get the keypair to do the signing from the TPK. +# let mut keypair = tsk.keys_valid().signing_capable().nth(0).unwrap().2 +# .clone().into_keypair()?; +# # // Start streaming an OpenPGP message. # let message = Message::new(sink); # -# // We want to encrypt a literal data packet. -# let encryptor = Encryptor::new(message, -# &[], // No symmetric encryption. -# &[recipient], -# EncryptionMode::ForTransport)?; +# // We want to sign a literal data packet. +# let signer = Signer::new(message, vec![&mut keypair])?; # # // Emit a literal data packet. # let mut literal_writer = LiteralWriter::new( -# encryptor, openpgp::constants::DataFormat::Binary, None, None)?; +# signer, openpgp::constants::DataFormat::Binary, None, None)?; # -# // Encrypt the data. +# // Sign the data. # literal_writer.write_all(plaintext.as_bytes())?; # # // Finalize the OpenPGP message to make sure that all data is @@ -208,75 +202,67 @@ fn generate() -> openpgp::Result<openpgp::TPK> { # Ok(()) # } # -# /// Decrypts the given message. -# fn decrypt(sink: &mut Write, ciphertext: &[u8], recipient: &openpgp::TPK) -# -> openpgp::Result<()> { -# // Make a helper that that feeds the recipient's secret key to the -# // decryptor. +# /// Verifies the given message. +# fn verify(sink: &mut Write, signed_message: &[u8], sender: &openpgp::TPK) +# -> openpgp::Result<()> { +# // Make a helper that that feeds the sender's public key to the +# // verifier. # let helper = Helper { -# secret: recipient, +# tpk: sender, # }; # -# // Now, create a decryptor with a helper using the given TPKs. -# let mut decryptor = Decryptor::from_bytes(ciphertext, helper)?; +# // Now, create a verifier with a helper using the given TPKs. +# let mut verifier = Verifier::from_bytes(signed_message, helper)?; # -# // Decrypt the data. -# io::copy(&mut decryptor, sink)?; +# // Verify the data. +# io::copy(&mut verifier, sink)?; # # Ok(()) # } # # struct Helper<'a> { -# secret: &'a openpgp::TPK, +# tpk: &'a openpgp::TPK, # } # # impl<'a> VerificationHelper for Helper<'a> { # fn get_public_keys(&mut self, _ids: &[openpgp::KeyID]) # -> openpgp::Result<Vec<openpgp::TPK>> { # // Return public keys for signature verification here. -# Ok(Vec::new()) +# Ok(vec![self.tpk.clone()]) # } # -# fn check(&mut self, _sigs: Vec<Vec<VerificationResult>>) +# fn check(&mut self, sigs: Vec<Vec<VerificationResult>>) # -> openpgp::Result<()> { -# // Implement your signature verification policy here. -# Ok(()) -# } -# } -# -# impl<'a> DecryptionHelper for Helper<'a> { -# fn get_secret(&mut self, -# _pkesks: &[&openpgp::packet::PKESK], -# _skesks: &[&openpgp::packet::SKESK]) -# -> openpgp::Result<Option<Secret>> -# { -# // The encryption key is the first and only subkey. -# let key = self.secret.subkeys().nth(0) -# .map(|binding| binding.subkey().clone()) -# .unwrap(); -# -# // The secret key is not encrypted. -# let secret = -# if let Some(SecretKey::Unencrypted { -# ref mpis, -# }) = key.secret() { -# mpis.clone() -# } else { -# unreachable!() -# }; -# -# Ok(Some(Secret::Asymmetric { -# identity: self.secret.fingerprint(), -# key: key, -# secret: secret, -# })) +# // In this function, we implement our signature verification +# // policy. +# +# // First, we are interested in signatures over the data, +# // i.e. level 0 signatures. +# let sigs_over_data = sigs.get(0) +# .ok_or_else(|| failure::err_msg("No level 0 signatures found"))?; +# +# // Now, let's see if there is a signature on that level. +# let sig_result = sigs_over_data.get(0) +# .ok_or_else(|| failure::err_msg("No signature found"))?; +# +# // Finally, given a VerificationResult, which only says +# // whether the signature checks out mathematically, we apply +# // our policy. +# match sig_result { +# VerificationResult::GoodChecksum(_) => +# Ok(()), // Good signature +# VerificationResult::MissingKey(_) => +# Err(failure::err_msg("Missing key to verify signature")), +# VerificationResult::BadChecksum(_) => +# Err(failure::err_msg("Bad signature")), +# } # } # } ``` -# Encryption +# Signing -To encrypt a message, we first compose a writer stack corresponding to +To sign a message, we first compose a writer stack corresponding to the desired output format and packet structure. The resulting object implements [`io::Write`], and we simply write the plaintext to it. @@ -285,10 +271,10 @@ implements [`io::Write`], and we simply write the plaintext to it. ```rust # use std::io::{self, Write}; # +# extern crate failure; # extern crate sequoia_openpgp as openpgp; # use openpgp::serialize::stream::*; # use openpgp::parse::stream::*; -# use openpgp::packet::key::SecretKey; # # const MESSAGE: &'static str = "дружба"; # @@ -296,22 +282,22 @@ implements [`io::Write`], and we simply write the plaintext to it. # // Generate a key. # let key = generate().unwrap(); # -# // Encrypt the message. -# let mut ciphertext = Vec::new(); -# encrypt(&mut ciphertext, MESSAGE, &key).unwrap(); +# // Sign the message. +# let mut signed_message = Vec::new(); +# sign(&mut signed_message, MESSAGE, &key).unwrap(); # -# // Decrypt the message. +# // Verify the message. # let mut plaintext = Vec::new(); -# decrypt(&mut plaintext, &ciphertext, &key).unwrap(); +# verify(&mut plaintext, &signed_message, &key).unwrap(); # # assert_eq!(MESSAGE.as_bytes(), &plaintext[..]); # } # -# /// Generates an encryption-capable key. +# /// Generates an signing-capable key. # fn generate() -> openpgp::Result<openpgp::TPK> { # let (tpk, _revocation) = openpgp::tpk::TPKBuilder::default() # .add_userid("someone@example.org") -# .add_encryption_subkey() +# .add_signing_subkey() # .generate()?; # # // Save the revocation certificate somewhere. @@ -319,23 +305,24 @@ implements [`io::Write`], and we simply write the plaintext to it. # Ok(tpk) # } # -/// Encrypts the given message. -fn encrypt(sink: &mut Write, plaintext: &str, recipient: &openpgp::TPK) +/// Signs the given message. +fn sign(sink: &mut Write, plaintext: &str, tsk: &openpgp::TPK) -> openpgp::Result<()> { + // Get the keypair to do the signing from the TPK. + let mut keypair = tsk.keys_valid().signing_capable().nth(0).unwrap().2 + .clone().into_keypair()?; + // Start streaming an OpenPGP message. let message = Message::new(sink); - // We want to encrypt a literal data packet. - let encryptor = Encryptor::new(message, - &[], // No symmetric encryption. - &[recipient], - EncryptionMode::ForTransport)?; + // We want to sign a literal data packet. + let signer = Signer::new(message, vec![&mut keypair])?; // Emit a literal data packet. let mut literal_writer = LiteralWriter::new( - encryptor, openpgp::constants::DataFormat::Binary, None, None)?; + signer, openpgp::constants::DataFormat::Binary, None, None)?; - // Encrypt the data. + // Sign the data. literal_writer.write_all(plaintext.as_bytes())?; // Finalize the OpenPGP message to make sure that all data is @@ -345,219 +332,201 @@ fn encrypt(sink: &mut Write, plaintext: &str, recipient: &openpgp::TPK) Ok(()) } # -# /// Decrypts the given message. -# fn decrypt(sink: &mut Write, ciphertext: &[u8], recipient: &openpgp::TPK) -# -> openpgp::Result<()> { -# // Make a helper that that feeds the recipient's secret key to the -# // decryptor. +# /// Verifies the given message. +# fn verify(sink: &mut Write, signed_message: &[u8], sender: &openpgp::TPK) +# -> openpgp::Result<()> { +# // Make a helper that that feeds the sender's public key to the +# // verifier. # let helper = Helper { -# secret: recipient, +# tpk: sender, # }; # -# // Now, create a decryptor with a helper using the given TPKs. -# let mut decryptor = Decryptor::from_bytes(ciphertext, helper)?; +# // Now, create a verifier with a helper using the given TPKs. +# let mut verifier = Verifier::from_bytes(signed_message, helper)?; # -# // Decrypt the data. -# io::copy(&mut decryptor, sink)?; +# // Verify the data. +# io::copy(&mut verifier, sink)?; # # Ok(()) # } # # struct Helper<'a> { -# secret: &'a openpgp::TPK, +# tpk: &'a openpgp::TPK, # } # # impl<'a> VerificationHelper for Helper<'a> { # fn get_public_keys(&mut self, _ids: &[openpgp::KeyID]) # -> openpgp::Result<Vec<openpgp::TPK>> { # // Return public keys for signature verification here. -# Ok(Vec::new()) +# Ok(vec![self.tpk.clone()]) # } # -# fn check(&mut self, _sigs: Vec<Vec<VerificationResult>>) +# fn check(&mut self, sigs: Vec<Vec<VerificationResult>>) # -> openpgp::Result<()> { -# // Implement your signature verification policy here. -# Ok(()) -# } -# } -# -# impl<'a> DecryptionHelper for Helper<'a> { -# fn get_secret(&mut self, -# _pkesks: &[&openpgp::packet::PKESK], -# _skesks: &[&openpgp::packet::SKESK]) -# -> openpgp::Result<Option<Secret>> -# { -# // The encryption key is the first and only subkey. -# let key = self.secret.subkeys().nth(0) -# .map(|binding| binding.subkey().clone()) -# .unwrap(); -# -# // The secret key is not encrypted. -# let secret = -# if let Some(SecretKey::Unencrypted { -# ref mpis, -# }) = key.secret() { -# mpis.clone() -# } else { -# unreachable!() -# }; -# -# Ok(Some(Secret::Asymmetric { -# identity: self.secret.fingerprint(), -# key: key, -# secret: secret, -# })) +# // In this function, we implement our signature verification +# // policy. +# +# // First, we are interested in signatures over the data, +# // i.e. level 0 signatures. +# let sigs_over_data = sigs.get(0) +# .ok_or_else(|| failure::err_msg("No level 0 signatures found"))?; +# +# // Now, let's see if there is a signature on that level. +# let sig_result = sigs_over_data.get(0) +# .ok_or_else(|| failure::err_msg("No signature found"))?; +# +# // Finally, given a VerificationResult, which only says +# // whether the signature checks out mathematically, we apply +# // our policy. +# match sig_result { +# VerificationResult::GoodChecksum(_) => +# Ok(()), // Good signature +# VerificationResult::MissingKey(_) => +# Err(failure::err_msg("Missing key to verify signature")), +# VerificationResult::BadChecksum(_) => +# Err(failure::err_msg("Bad signature")), +# } # } # } ``` -# Decryption +# Verification -Decryption is more difficult than encryption. When we encrypt, we -control the packet structure being generated. However, when we -decrypt, the control flow is determined by the message being -processed. +Verification is more difficult than signing. When we sign, we control +the packet structure being generated. However, when we verify, the +control flow is determined by the message being processed. -To use Sequoia's low-level streaming decryptor, we need to provide an -object that implements [`VerificationHelper`] and -[`DecryptionHelper`]. This object provides public and secret keys for -the signature verification and decryption, and implements the +To use Sequoia's low-level streaming verifier, we need to provide an +object that implements [`VerificationHelper`]. This object provides +public and for the signature verification, and implements the signature verification policy. [`VerificationHelper`]: ../../sequoia_openpgp/parse/stream/trait.VerificationHelper.html -[`DecryptionHelper`]: ../../sequoia_openpgp/parse/stream/trait.DecryptionHelper.html -To decrypt messages, we create a [`Decryptor`] with our helper. -Decrypted data can be read from this using [`io::Read`]. +To decrypt messages, we create a [`Verifier`] with our helper. +Verified data can be read from this using [`io::Read`]. -[`Decryptor`]: ../../sequoia_openpgp/parse/stream/struct.Decryptor.html +[`Verifier`]: ../../sequoia_openpgp/parse/stream/struct.Verifier.html [`io::Read`]: https://doc.rust-lang.org/std/io/trait.Read.html ```rust # use std::io::{self, Write}; -# +# +# extern crate failure; # extern crate sequoia_openpgp as openpgp; # use openpgp::serialize::stream::*; # use openpgp::parse::stream::*; -# use openpgp::packet::key::SecretKey; -# +# # const MESSAGE: &'static str = "дружба"; -# +# # fn main() { # // Generate a key. # let key = generate().unwrap(); -# -# // Encrypt the message. -# let mut ciphertext = Vec::new(); -# encrypt(&mut ciphertext, MESSAGE, &key).unwrap(); -# -# // Decrypt the message. +# +# // Sign the message. +# let mut signed_message = Vec::new(); +# sign(&mut signed_message, MESSAGE, &key).unwrap(); +# +# // Verify the message. # let mut plaintext = Vec::new(); -# decrypt(&mut plaintext, &ciphertext, &key).unwrap(); -# +# verify(&mut plaintext, &signed_message, &key).unwrap(); +# # assert_eq!(MESSAGE.as_bytes(), &plaintext[..]); # } -# -# /// Generates an encryption-capable key. +# +# /// Generates an signing-capable key. # fn generate() -> openpgp::Result<openpgp::TPK> { # let (tpk, _revocation) = openpgp::tpk::TPKBuilder::default() # .add_userid("someone@example.org") -# .add_encryption_subkey() +# .add_signing_subkey() # .generate()?; -# +# # // Save the revocation certificate somewhere. -# +# # Ok(tpk) # } -# -# /// Encrypts the given message. -# fn encrypt(sink: &mut Write, plaintext: &str, recipient: &openpgp::TPK) +# +# /// Signs the given message. +# fn sign(sink: &mut Write, plaintext: &str, tsk: &openpgp::TPK) # -> openpgp::Result<()> { +# // Get the keypair to do the signing from the TPK. +# let mut keypair = tsk.keys_valid().signing_capable().nth(0).unwrap().2 +# .clone().into_keypair()?; +# # // Start streaming an OpenPGP message. # let message = Message::new(sink); -# -# // We want to encrypt a literal data packet. -# let encryptor = Encryptor::new(message, -# &[], // No symmetric encryption. -# &[recipient], -# EncryptionMode::ForTransport)?; -# +# +# // We want to sign a literal data packet. +# let signer = Signer::new(message, vec![&mut keypair])?; +# # // Emit a literal data packet. # let mut literal_writer = LiteralWriter::new( -# encryptor, openpgp::constants::DataFormat::Binary, None, None)?; -# -# // Encrypt the data. +# signer, openpgp::constants::DataFormat::Binary, None, None)?; +# +# // Sign the data. # literal_writer.write_all(plaintext.as_bytes())?; -# +# # // Finalize the OpenPGP message to make sure that all data is # // written. # literal_writer.finalize()?; -# +# # Ok(()) # } -# -/// Decrypts the given message. -fn decrypt(sink: &mut Write, ciphertext: &[u8], recipient: &openpgp::TPK) - -> openpgp::Result<()> { - // Make a helper that that feeds the recipient's secret key to the - // decryptor. +# +/// Verifies the given message. +fn verify(sink: &mut Write, signed_message: &[u8], sender: &openpgp::TPK) + -> openpgp::Result<()> { + // Make a helper that that feeds the sender's public key to the + // verifier. let helper = Helper { - secret: recipient, + tpk: sender, }; - // Now, create a decryptor with a helper using the given TPKs. - let mut decryptor = Decryptor::from_bytes(ciphertext, helper)?; + // Now, create a verifier with a helper using the given TPKs. + let mut verifier = Verifier::from_bytes(signed_message, helper)?; - // Decrypt the data. - io::copy(&mut decryptor, sink)?; + // Verify the data. + io::copy(&mut verifier, sink)?; Ok(()) } struct Helper<'a> { - secret: &'a openpgp::TPK, + tpk: &'a openpgp::TPK, } impl<'a> VerificationHelper for Helper<'a> { fn get_public_keys(&mut self, _ids: &[openpgp::KeyID]) -> openpgp::Result<Vec<openpgp::TPK>> { // Return public keys for signature verification here. - Ok(Vec::new()) + Ok(vec![self.tpk.clone()]) } - fn check(&mut self, _sigs: Vec<Vec<VerificationResult>>) + fn check(&mut self, sigs: Vec<Vec<VerificationResult>>) -> openpgp::Result<()> { - // Implement your signature verification policy here. - Ok(()) - } -} - -impl<'a> DecryptionHelper for Helper<'a> { - fn get_secret(&mut self, - _pkesks: &[&openpgp::packet::PKESK], - _skesks: &[&openpgp::packet::SKESK]) - -> openpgp::Result<Option<Secret>> |