Skip to content

Commit

Permalink
Merge pull request #6998 from freedomofpress/sequoia-fixes
Browse files Browse the repository at this point in the history
Assorted redwood/Sequoia fixes from Neal's review
  • Loading branch information
zenmonkeykstop committed Oct 13, 2023
2 parents e255538 + 814a37c commit f3adeba
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 14 deletions.
3 changes: 1 addition & 2 deletions redwood/src/decryption.rs
Expand Up @@ -7,7 +7,6 @@ use sequoia_openpgp::crypto::{Password, SessionKey};
use sequoia_openpgp::parse::stream::*;
use sequoia_openpgp::policy::Policy;
use sequoia_openpgp::types::SymmetricAlgorithm;
use sequoia_openpgp::KeyID;

pub(crate) struct Helper<'a> {
pub(crate) policy: &'a dyn Policy,
Expand Down Expand Up @@ -51,7 +50,7 @@ impl<'a> DecryptionHelper for Helper<'a> {
for pkesk in pkesks {
// Note: this check won't work for messages encrypted with --throw-keyids,
// but we don't generate any messages that use it.
if pkesk.recipient() == &KeyID::from(key.fingerprint()) {
if pkesk.recipient() == &key.keyid() {
// Decrypt the secret key with the specified passphrase.
let mut pair = key
.clone()
Expand Down
33 changes: 21 additions & 12 deletions redwood/src/lib.rs
Expand Up @@ -14,7 +14,7 @@ use sequoia_openpgp::serialize::{
use sequoia_openpgp::Cert;
use std::borrow::Cow;
use std::fs::File;
use std::io::{self, Read};
use std::io::{self, BufWriter, Read, Write};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::string::FromUtf8Error;
Expand Down Expand Up @@ -105,7 +105,7 @@ pub fn is_valid_public_key(input: &str) -> Result<String> {
// We don't need the keys, just need to check there's at least one and no error
keys::keys_from_cert(POLICY, &cert)?;
// And there is no secret key material
if cert.keys().secret().next().is_some() {
if cert.is_tsk() {
return Err(Error::HasSecretKeyMaterial);
}
Ok(cert.fingerprint().to_string())
Expand Down Expand Up @@ -157,8 +157,14 @@ fn encrypt(

// In reverse order, we set up a writer that will write an encrypted and
// armored message to a newly-created file at `destination`.
let mut sink = File::create(destination)?;
let message = Message::new(&mut sink);
// TODO: Use `File::create_new()` once it's stabilized: https://github.com/rust-lang/rust/issues/105135
let sink = File::options()
.read(true)
.write(true)
.create_new(true)
.open(destination)?;
let mut writer = BufWriter::new(sink);
let message = Message::new(&mut writer);
let message = Armorer::new(message).build()?;
let message = Encryptor::for_recipients(message, recipient_keys).build()?;
let mut message = LiteralWriter::new(message).build()?;
Expand All @@ -168,6 +174,7 @@ fn encrypt(

// Flush any remaining buffers
message.finalize()?;
writer.flush()?;

Ok(())
}
Expand Down Expand Up @@ -204,7 +211,7 @@ pub fn decrypt(
mod tests {
use super::*;
use sequoia_openpgp::Cert;
use tempfile::NamedTempFile;
use tempfile::TempDir;

const PASSPHRASE: &str = "correcthorsebatterystaple";
const SECRET_MESSAGE: &str = "Rust is great 🦀";
Expand Down Expand Up @@ -261,7 +268,7 @@ mod tests {

// Attempting to encrypt to multiple recipients should fail if any one of them
// has no supported keys
let tmp = NamedTempFile::new().unwrap();
let tmp_dir = TempDir::new().unwrap();
let expected_err_msg = format!(
"No supported keys for certificate {}",
BAD_KEY_FINGERPRINT
Expand All @@ -270,7 +277,7 @@ mod tests {
let err = encrypt_message(
vec![good_key, BAD_KEY.to_string()],
SECRET_MESSAGE.to_string(),
tmp.path().to_path_buf(),
tmp_dir.path().join("message.asc"),
)
.unwrap_err();
assert_eq!(err.to_string(), expected_err_msg);
Expand Down Expand Up @@ -310,15 +317,17 @@ mod tests {
let (_public_key3, secret_key3, _) =
generate_source_key_pair(PASSPHRASE, "foo3@example.org").unwrap();

let tmp = NamedTempFile::new().unwrap();
let tmp_dir = TempDir::new().unwrap();
let tmp = tmp_dir.path().join("message.asc");
println!("{}", tmp.to_string_lossy());
// Encrypt a message to keys 1 and 2 but not 3
encrypt_message(
vec![public_key1, public_key2],
SECRET_MESSAGE.to_string(),
tmp.path().to_path_buf(),
tmp.clone(),
)
.unwrap();
let ciphertext = std::fs::read_to_string(tmp.path()).unwrap();
let ciphertext = std::fs::read_to_string(tmp).unwrap();
// Verify ciphertext looks like an encrypted message
assert!(ciphertext.starts_with("-----BEGIN PGP MESSAGE-----\n"));
// Decrypt as key 1
Expand Down Expand Up @@ -376,12 +385,12 @@ mod tests {
"OpenPGP error: unexpected EOF",
),
];
let tmp: NamedTempFile = NamedTempFile::new().unwrap();
let tmp_dir = TempDir::new().unwrap();
for (key, error) in bad_keys {
let err = encrypt_message(
key, // missing or malformed recipient key
"Look ma, no key".to_string(),
tmp.path().to_path_buf(),
tmp_dir.path().join("message.asc"),
)
.unwrap_err();
assert_eq!(err.to_string(), error);
Expand Down

0 comments on commit f3adeba

Please sign in to comment.