use ceal::openpgp;
use sequoia_openpgp::{Cert, parse::Parse};
use std::{
ffi::OsStr,
fs,
io::{BufRead as _, Write},
os::unix::ffi::OsStrExt,
path::Path,
process::{Command, Stdio}
};
const MESSAGE: &[u8] = b"From: OpenPGP Test <openpgp@example.org>\r
To: OpenPGP Test <openpgp@example.org>\r
Content-Type: multipart/alternative; boundary=iamaboundary\r
Content-Description: Multipart Message in MIME format\r
Subject: Test Mail\r
MIME-Version: 1.0\r
\r
--iamaboundary\r
Content-Type: text/plain; charset=\"utf-8\"\r
\r
Hello World\r
\r
--iamaboundary\r
Content-Type: text/html; charset=\"utf-8\"\r
\r
<html><body>Hello World</body></html>\r
\r
--iamaboundary--\r
";
const HEADERS: &[u8] = b"From: OpenPGP Test <openpgp@example.org>\r
To: OpenPGP Test <openpgp@example.org>\r
Subject: Test Mail\r
MIME-Version: 1.0\r
";
const BODY: &str = "Content-Type: multipart/alternative; boundary=iamaboundary\r
Content-Description: Multipart Message in MIME format\r
\r
--iamaboundary\r
Content-Type: text/plain; charset=\"utf-8\"\r
\r
Hello World\r
\r
--iamaboundary\r
Content-Type: text/html; charset=\"utf-8\"\r
\r
<html><body>Hello World</body></html>\r
\r
--iamaboundary--\r
";
fn print_cmd(cmd: &Command) {
eprint!("+ '{}'", cmd.get_program().display());
for arg in cmd.get_args() {
eprint!(" '{}'", arg.display());
}
eprintln!();
}
#[test]
fn test_openpgp_encryption() {
let dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests");
let cert = dir.join("openpgp_test_key.cert");
let key = dir.join("openpgp_test_key.pgp");
if !cert.exists() || !key.exists() {
let mut cmd = Command::new(dir.join("openpgp_test_key.sh"));
print_cmd(&cmd);
let status = cmd.status().unwrap();
assert!(status.success());
}
let cert = fs::read(cert).unwrap();
let encrypted = openpgp::encrypt(MESSAGE, vec![Cert::from_bytes(&cert).unwrap()]);
_ = fs::write(dir.join("openpgp_test_mail.eml"), &encrypted);
assert!(encrypted.starts_with(HEADERS));
let pgp_start = "-----BEGIN PGP MESSAGE-----";
let pgp_end = "-----END PGP MESSAGE-----";
let mut pgp_start_idx = 0;
let mut pgp_end_idx = 0;
let mut lines = encrypted.lines();
while let Some(line) = lines.next().map(|line| line.unwrap()) {
assert!(&encrypted[pgp_start_idx ..].starts_with(line.as_bytes()));
if line.starts_with(pgp_start) {
pgp_end_idx = pgp_start_idx + line.len() + 2;
break;
}
pgp_start_idx += line.len() + 2;
}
while let Some(line) = lines.next().map(|line| line.unwrap()) {
pgp_end_idx += line.len() + 2;
if line.starts_with(pgp_end) {
break;
}
}
let pgp = &encrypted[pgp_start_idx ..= pgp_end_idx];
let mut sq = Command::new("sq");
sq.arg("decrypt")
.arg("--recipient-file")
.arg(key)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped());
print_cmd(&sq);
let mut sq = sq.spawn().unwrap();
sq.stdin.take().unwrap().write_all(pgp).unwrap();
let decrypted = sq.wait_with_output().unwrap();
eprint!("{}", OsStr::from_bytes(&decrypted.stderr).display());
assert!(decrypted.status.success());
assert_eq!(str::from_utf8(&decrypted.stdout).unwrap(), BODY);
}