1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
/// Generates a key, then encrypts and decrypts a message.
use std::io::{self, Write};
use sequoia_openpgp as openpgp;
use crate::openpgp::cert::prelude::*;
use crate::openpgp::crypto::SessionKey;
use crate::openpgp::types::SymmetricAlgorithm;
use crate::openpgp::serialize::stream::*;
use crate::openpgp::parse::{Parse, stream::*};
use crate::openpgp::policy::Policy;
use crate::openpgp::policy::StandardPolicy as P;
const MESSAGE: &str = "дружба";
fn main() -> openpgp::Result<()> {
let p = &P::new();
// Generate a key.
let key = generate()?;
// Encrypt the message.
let mut ciphertext = Vec::new();
encrypt(p, &mut ciphertext, MESSAGE, &key)?;
// Decrypt the message.
let mut plaintext = Vec::new();
decrypt(p, &mut plaintext, &ciphertext, &key)?;
assert_eq!(MESSAGE.as_bytes(), &plaintext[..]);
Ok(())
}
/// Generates an encryption-capable key.
fn generate() -> openpgp::Result<openpgp::Cert> {
let (cert, _revocation) = CertBuilder::new()
.add_userid("someone@example.org")
.add_transport_encryption_subkey()
.generate()?;
// Save the revocation certificate somewhere.
Ok(cert)
}
/// Encrypts the given message.
fn encrypt(p: &dyn Policy, sink: &mut (dyn Write + Send + Sync),
plaintext: &str, recipient: &openpgp::Cert)
-> openpgp::Result<()>
{
let recipients =
recipient.keys().with_policy(p, None).supported().alive().revoked(false)
.for_transport_encryption();
// Start streaming an OpenPGP message.
let message = Message::new(sink);
// We want to encrypt a literal data packet.
let message = Encryptor::for_recipients(message, recipients)
.build()?;
// Emit a literal data packet.
let mut message = LiteralWriter::new(message).build()?;
// Encrypt the data.
message.write_all(plaintext.as_bytes())?;
// Finalize the OpenPGP message to make sure that all data is
// written.
message.finalize()?;
Ok(())
}
/// Decrypts the given message.
fn decrypt(p: &dyn Policy,
sink: &mut dyn Write, ciphertext: &[u8], recipient: &openpgp::Cert)
-> openpgp::Result<()> {
// Make a helper that that feeds the recipient's secret key to the
// decryptor.
let helper = Helper {
secret: recipient,
policy: p,
};
// Now, create a decryptor with a helper using the given Certs.
let mut decryptor = DecryptorBuilder::from_bytes(ciphertext)?
.with_policy(p, None, helper)?;
// Decrypt the data.
io::copy(&mut decryptor, sink)?;
Ok(())
}
struct Helper<'a> {
secret: &'a openpgp::Cert,
policy: &'a dyn Policy,
}
impl<'a> VerificationHelper for Helper<'a> {
fn get_certs(&mut self, _ids: &[openpgp::KeyHandle])
-> openpgp::Result<Vec<openpgp::Cert>> {
// Return public keys for signature verification here.
Ok(Vec::new())
}
fn check(&mut self, _structure: MessageStructure)
-> openpgp::Result<()> {
// Implement your signature verification policy here.
Ok(())
}
}
impl<'a> DecryptionHelper for Helper<'a> {
fn decrypt(&mut self,
pkesks: &[openpgp::packet::PKESK],
_skesks: &[openpgp::packet::SKESK],
sym_algo: Option<SymmetricAlgorithm>,
decrypt: &mut dyn FnMut(Option<SymmetricAlgorithm>, &SessionKey) -> bool)
-> openpgp::Result<Option<Cert>>
{
let key = self.secret.keys().unencrypted_secret()
.with_policy(self.policy, None)
.for_transport_encryption().next().unwrap().key().clone();
// The secret key is not encrypted.
let mut pair = key.into_keypair()?;
pkesks[0].decrypt(&mut pair, sym_algo)
.map(|(algo, session_key)| decrypt(algo, &session_key));
// XXX: In production code, return the Fingerprint of the
// recipient's Cert here
Ok(None)
}
}
|