summaryrefslogtreecommitdiffstats
path: root/guide
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-03-15 13:45:49 +0100
committerJustus Winter <justus@sequoia-pgp.org>2019-03-15 13:48:22 +0100
commitb95bc8181893d14ac3b692157471d1736a3a6fd4 (patch)
tree3779ea4cc4ea481475c86607d815578d75ea17d8 /guide
parent2a170e370fc371994ceed4134fbb10fcadd05810 (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.md541
-rw-r--r--guide/src/chapter_02.md716
-rw-r--r--guide/src/chapter_03.md221
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(())
-