Skip to content

Commit

Permalink
Addition of ergonomic options
Browse files Browse the repository at this point in the history
=== ADDITIONS ===

- Added the possibility to add for each post to a remailer of the
headers.

- The PGP backend "back-gpg" now uses a unique keyring and no longer
pollutes the user's keyring.

- The path to the config can now be set via the CLI.

=== CHANGES ===

- License change : Switching from GPLv3 to CeCILL v2.1. No major change
since the CeCILL license is fully compatible with the GPL licenses.

- Change of the Github Actions setup, artifactes will only be built on
Linux (Windows failed because not supported by
softprops/action-gh-release).

- Disabling some remailers (because they don't respond to MX requests).
  • Loading branch information
tim54000 committed Feb 20, 2020
1 parent a741918 commit 1b38c58
Show file tree
Hide file tree
Showing 9 changed files with 621 additions and 718 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
run: ${{ format('cargo build --verbose --release --no-default-features --features {0}', matrix.backend) }}
- name: Release
uses: docker://softprops/action-gh-release
if: startsWith(github.ref, 'refs/tags/')
if: runner.os == 'Linux' && startsWith(github.ref, 'refs/tags/')
with:
draft: true
files: "/target/release/cypherpunk-cli.exe, /target/release/cypherpunk-cli"
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "cypherpunk-cli"
description = "CLI tool to encrypt your messages between different remailers easily"
version = "2.0.0-beta"
version = "2.0.0-beta.2"
authors = ["Tim54000"]
edition = "2018"

Expand Down
1,192 changes: 518 additions & 674 deletions LICENSE

Large diffs are not rendered by default.

59 changes: 41 additions & 18 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,30 +106,53 @@ $ cypherpunk-cli --input ./message.txt --chain austria --format eml
```

##### cypherpunk --help
```SHELL
cypherpunk x.x.x
```
cypherpunk 2.0.0-beta
Tim54000
CLI tool to encrypt your messages between different remailers easily
USAGE:
cypherpunk-cli [FLAGS] [OPTIONS]
FLAGS:
-h, --help Prints help information
-q, --quiet The quiet flag to make the PGP backend quiet and soon more...
-V, --version Prints version information
-h, --help
Prints help information
OPTIONS:
-c, --chain <chain>... The remailer chain through which your message will pass. [required] Tips: you can
use a joker "*" to randomly choose one remailer in the config. It will change with
each redundant message
-f, --format <format> The output message format, by default it will be in Cypherpunk format [default:
cypherpunk] [possible values: Cypherpunk, Mailto, EML]
-i, --input <input> Messsage input file, stdin if not present; the message must be readable by the last
Cypherpunk remailer in the chain
-o, --output <output> Output dir, stdout if not present; all the encrypted message for remailer will be
there
-r, --redundancy <redundancy> Number of redundancy message to encrypted because Cypherpunk may forgot your
message. If you use a "*" for remailer it will be randomly choose for each
redundancy message [default: 1]
-q, --quiet
The quiet flag to make the PGP backend quiet and soon more...
-V, --version
Prints version information
OPTIONS:
-c, --chain <chain>...
The remailer chain through which your message will pass. [required]
Tips: You can use a joker "*" to randomly choose one remailer in the config. It will change with each
redundant message.
--config <config>
The path to the remailer config, useful if you have install this tool [default: ./remailers.json]
-f, --format <format>
The output message format [default: cypherpunk] [possible values: Cypherpunk, Mailto, EML]
-H, --header <headers>...
Remailer headers to add for each remailer message. Only one key-value per string.
This can be useful to add `Inflate` header to each message.
Examples: `--header "Key: Value"` `--header "Key1: Value1" "Key2: Value2"`
-i, --input <input>
Messsage input file, stdin if not present; the message must be readable by the last Cypherpunk remailer in
the chain
-o, --output <output>
Output dir, stdout if not present; all the encrypted message for remailer will be there
-r, --redundancy <redundancy>
Number of redundancy message to encrypted
Because the Cypherpunk remailers can forget messages, it's a good idea to send several messages to different
remailers to avoid the loss of the message. Tips: If you use a "*" for remailer it will be randomly choose
for each redundancy message. [default: 1]
```
6 changes: 3 additions & 3 deletions remailers.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"brabus"
],
"email": "brabus@remailer.org.uk",
"enable": true,
"enable": false,
"key": "base64:mQGiBFaQLIMRBADp6GnvokWnNhEEhiOlIF7JRabdaXGUWP6oworgjcYDoWUWWtynfnaAXbgHMllNtOlI4sOePMOzzqDdKkk88B3ETaogS12tZFsgICkjmwztB1RitEYeW/adKrwzw4u5jFUd3SIsLGdtw7fY1XWooYKwJfaYdUQNZjD7wb5pld1tWwCgy3c9F6FgjNkgB3f7H/pvAqh3DysD/jHNrt7ZauthNEUJhJebpvhwaZj5DzmE1wBAle+7G2grRHDLi5aS3kJMVBRNL9AkkAg08K7TnEK4qhWwk775hE1kPy63wiUchapbvttUdvEUygDT/pFXiVa5vgWrnepGBc2GqKjj7SKfMCkDL0IMzd+S/kpNu3LGUNe6i1B0tazCA/9+FQiOTtbay56bRvhI5pCyDdOuhpPdiRo0aQEhYadlliNhIG3ubfDPhhLD+5ymeGUILzXpEIweYVhzimvAfmkesYxjZ50YSEranbOL1HZR9h4oj9MzcgO7MnURO4v9KRnTMdxhHJL+AWDoeh4vAzoGBwso3Ev+FL5fPN1kbn/S67QoQnJhYnVzIFJlbWFpbGVyIDxicmFidXNAcmVtYWlsZXIub3JnLnVrPohOBBARAgAOBQJWkCyDBAsDBwICHgEACgkQvbVaeiXiZsUSnQCeI9xEGcSG1m+KduLD5dAdwDkQOOQAoI6lEXz7fakqwwyXlJ274mBFuAO9uQENBFaQLIMQBADeLsSB95sDw0xJHbizzjT7P3asycM77yI2VMELyajzwqrzNX0glm6mQdxGXD9tp7hL8ROyYPWcIBMbkyz4lLadXYdU3mnpZ8r7LeF/pMxiIBcbnJYMRIEdqlSXLjqgyNCXKmAVSUXuEK3+QXoFrIiQCgd576SYl0MNZcyHA1Co4wADBQQAiCy75ySmGUSteveO35Or3dgJ/ha7vId+qk/3zW+fh5U6iQUjwXDRR3fjVOK3Gf2en94A+NvulImSIf5AOYIjboD0ryUGWgu7bSOYEKhwgH7H7fGrunUt2tfduXIYWq9I4P3T+uGJsZm/bl73q6jFNB4Y3XMNMiuCvcBMMPA6RU+IRgQYEQIABgUCVpAsgwAKCRC9tVp6JeJmxZVQAKCZgRujXAI2bUr4RBxnesO6ofsLOQCdFp6yQ+JcFeeqv3Xq801mw+QNHhU="
},
{
Expand All @@ -90,7 +90,7 @@
"holland"
],
"email": "mix@holland.remailer.nl",
"enable": true,
"enable": false,
"key": "base64:mQGiBFbjULwRBADRVp03RmxjiB/0CPuGn69g9ZuM2pVaHhd1W7WDcFeVB5+0o8+POFT8hcp5BXdjgh30Dhh4wtpCKZ+qjSsva09cjc9nqLMB3Rxzo8Yt6kRS89NPTD320CVoDy3aWcX/75ZBRCuWGx0mQga8aDZoX/1l6JNvwHCDckwPEEhkuKRmXwCgnQvco6DTBZD5LFcZXvxs2PZvR4kEAKZdcLqtyOLuCSFbGDx20yUUvRjlMM1gLDTcsfkE8hQ4a6Q1G2XQ8qOw5xeI0sqvBLh+YE14ejPtG7QEysAou87MrWD+qAEoqydakrE+qhCXuq4bEQeQgfSTIjuWUBKVow4QFtvp3V1stpkEAte2zw5nkYR3iK6eGrtBbUdYKo1BBACyDEQqE3wofDC3ulSTE9fK55gjMQbOmN8in80Rem/jH4ZhvKk4LX9KjV59p5sPFUtQmeOEpsajlxG5FjZkUX7RwLozwG/6LHhWD0i/tMpIv2mw8pRtfQiSbVCzTdeXvVYX9lbcZMBUJ0onjeRYewdcDVHIkDCGcQJ7+iLgjbS+F7QqSG9sbGFuZCBSZW1haWxlciA8bWl4QGhvbGxhbmQucmVtYWlsZXIubmw+iE4EEBECAA4FAlbjULwECwMHAgIeAQAKCRAXUVfb0SYdQDIiAJ47M+7andgGnd2vYNq/20ZxwDwCTACfajkMWDJt4ONIqqcf2bate87DMFy5AQ0EVuNQvBAEAKEHa2PwMmoG4z/Wu2+xd6K0x8x3kpPuDe8kVQR9eOPtwi5GueYmkavTP/sqg3PDDCLy6yTdjrymGB5PZHUC7CpBycXvBLMPi19iXzh6oYKDrmtAD0MyEGYpAZsozgvwzmWuyb/4Y27wdao1bgDQGV5HTX35MF2BjUMKxKzFZZjHAAMFA/0YVexnDBkLJYBkjR7AW7rvVzpqgK6dhhiJeUGypy2w8Fa/ioU6sbhvQpAcodxXCADWzGnpc0Wxo30faVQ2RZLw7wfHIv19yDOaMBiMMqtNrHIlew2niyBrMo3ydRcw0B0kEXRg5BD3ot6bFrfB8Z6y2kmFRVjCc5Go9IiqIJPwb4hGBBgRAgAGBQJW41C8AAoJEBdRV9vRJh1AJyAAoIzsokdK4xkYRpeZ1nUP0XhhnxAXAJ0SiPwuAvdPfpsc+LNFEx89EZuxuA=="
},
{
Expand All @@ -107,7 +107,7 @@
"loadmx"
],
"email": "mix@loadmx.net",
"enable": true,
"enable": false,
"key": "base64:mQGiBFkpmsARBADDQlTTR/M60/neYcQ2bf48KNHBhzb+eN3/opWM3GSN8rmWggRE07/nhz1X0DZ2PenF4DNdNVe1BsOhyvAma1yOz/dRiogF/75KDkTZCpgMUTRX5tuYxiq2/uzKgAfkOW6epbsalQCpLn8KDVKqkPtg8e5M35lzobg9PGbOnLjvAwCgiLAVUoKd1pXv52PVzWgHgHl9gfMD/1KQGT7Pjp+d3WYZy0q47G9AseTVFtp22I+MeDhWF1F5QFwNisPwNfUBeFax29hB9RG0/KNwkgBMdON4wwcpVZGdgWZgpzZeb4MtBIZzqmAX7AaBccsWrLUvl9TfR/3YYcePXjhLh69wsV82oIknFUwwKc7+EdEB0mPC9yCjm2WwA/9jH3Tc+wN5LxK/1tH9oQLqoLW+E/HrDBQx4Vl4SxLUgDdkPcbv+gWroQrqWPVqxhXfuJADa2Qd+l6/eXjUPZkDcJuhAEy/5qtDHWG+V0VFySRjoNt+gMTal/FUKkTe7ykPsJrBcTvEug6c5e97ICZCVESJxhobTkIhoz1A8GRL/LQqTGlzYmV0aCBTYWxhbmRlciBSZW1haWxlciA8bWl4QGxvYWRteC5uZXQ+iE4EEBECAA4FAlkpmsAECwMHAgIeAQAKCRDZUeenDs1LXLLFAJ949f7bIiApN0P3OHOoRrDsiLjZpwCfdXqShVFLxpkWQeo5zYTBi3G8ZLi5AQ0EWSmawBAEAITheJdRtrRB+tfoFzFU4eUjqhYQ1U2yWQPNKL+6ygYbXSZbQNREJPwmSQlkUlSYR1u2FH3W4NCsJwDc4K83RXkZ5pA2MEjPzQvNIOF2BslklslPDZDGuIWiVu4xe3zTuUlN4lqO98PFtm2IyAadSgze2ZeZDdZ009RBH+fem5r/AAMFA/wMbOXdRFshGR6VGu5GmBTgB0iNl5C6PiCC+NHx2kRPzOP4wUUZq3P18bTb8wyzVuLMwrYh/1nBk0QnzJQZUFi1HIACTSErnPukA4UC4iiiHX6oKb0EOVInHEnm9KndlGOYtr4omOKpikX+sViJnyiPs1UQqiJ7HV38okizZTbyMohGBBgRAgAGBQJZKZrAAAoJENlR56cOzUtcOHAAni5RZHcdVwISvO6hNPwHzNshfVkMAKCAPUjYvUQtK3sWDFweKYe8OpM0Vw=="
},
{
Expand Down
8 changes: 4 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use failure::ResultExt;

pub trait Cypherpunk {
fn import_keys(&self, keys: Vec<Vec<u8>>) -> Fallible<()>;
fn encrypt_message(&self, chain: Vec<String>, message: Vec<u8>) -> Fallible<Vec<u8>>;
fn encrypt_message(&self, chain: &Vec<String>, headers: &Vec<String>, message: Vec<u8>) -> Fallible<Vec<u8>>;
}

pub trait PGPBackend {
Expand Down Expand Up @@ -37,13 +37,13 @@ impl Cypherpunk for CypherpunkCore {
Ok(())
}

fn encrypt_message(&self, chain: Vec<String>, message: Vec<u8>) -> Fallible<Vec<u8>> {
fn encrypt_message(&self, chain: &Vec<String>, headers: &Vec<String>, message: Vec<u8>) -> Fallible<Vec<u8>> {
let pgp = self.pgp.as_ref();
chain.iter().fold(Ok(message), |input, remailer| {
let recipients = vec![remailer.clone()];
let mut readin = Cursor::new(input?);

let headers = format!("\n::\nAnon-To: {}\n\n::\nEncrypted: PGP\n\n", remailer);
let addheaders : String = headers.join("\n");
let headers = format!("\n::\nAnon-To: {}\n{}\n\n::\nEncrypted: PGP\n\n", remailer, addheaders);
let mut writeout: Cursor<Vec<u8>> = Cursor::new(Vec::new());

pgp.encrypt(&mut readin, &mut writeout, recipients)
Expand Down
37 changes: 30 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,28 +49,48 @@ impl OutputFormat {
about = "CLI tool to encrypt your messages between different remailers easily"
)]
struct Opt {
/// Messsage input file, stdin if not present; the message must be readable by the last Cypherpunk remailer in the chain.
/// Messsage input file, stdin if not present; the message must be readable by the last Cypherpunk
/// remailer in the chain.
#[structopt(short, long, parse(from_os_str))]
input: Option<PathBuf>,

/// Output dir, stdout if not present; all the encrypted message for remailer will be there.
#[structopt(short, long, parse(from_os_str))]
output: Option<PathBuf>,

/// Number of redundancy message to encrypted because Cypherpunk may forgot your message.
/// If you use a "*" for remailer it will be randomly choose for each redundancy message.
/// Number of redundancy message to encrypted
///
/// Because the Cypherpunk remailers can forget messages, it's a good idea to send several messages
/// to different remailers to avoid the loss of the message.
/// Tips: If you use a "*" for remailer it will be randomly choose for each redundancy message.
#[structopt(short, long, default_value = "1")]
redundancy: u8,

/// The remailer chain through which your message will pass. [required]
/// You can use a joker "*" to randomly choose one remailer in the config. It will change with each redundant message.
///
/// Tips: You can use a joker "*" to randomly choose one remailer in the config. It will change
/// with each redundant message.
#[structopt(short, long)]
chain: Vec<String>,

/// Remailer headers to add for each remailer message. Only one key-value per string.
///
/// This can be useful to add `Inflate` header to each message.
///
/// Examples:
/// `--header "Key: Value"`
/// `--header "Key1: Value1" "Key2: Value2"`
#[structopt(short="H", long="header")]
headers: Vec<String>,

/// The output message format.
#[structopt(short, long, possible_values = & OutputFormat::variants(), case_insensitive = true, default_value = "cypherpunk")]
format: OutputFormat,

/// The path to the remailer config, useful if you have install this tool.
#[structopt(long, default_value="./remailers.json")]
config: PathBuf,

/// The quiet flag to make the PGP backend quiet and soon more...
#[structopt(short, long)]
quiet: bool,
Expand All @@ -89,7 +109,7 @@ fn main() {
println!("Config loading...");

// Load config and run all
load_config("./remailers.json")
load_config(&opts.config)
.and_then(|config| {
let mut rng = thread_rng();
let remmap = remailer_map(config.remailers.clone());
Expand Down Expand Up @@ -139,12 +159,15 @@ fn main() {

println!("Encrypting...");

let mut chain = (&opts.chain).clone();
chain.reverse();

red.map(|index| {
println!("Encrypting message n°{}...", index + 1);
let chain =
make_chain(&opts.chain, &remmap, &mut rng).context("Can't select a chain!")?;
make_chain(&chain, &remmap, &mut rng).context("Can't select a chain!")?;
println!("Selected chain: {}", chain.join(", "));
Ok(core.encrypt_message(chain, message.clone())?)
Ok(core.encrypt_message(&chain, &opts.headers,message.clone())?)
})
.enumerate()
.map(|(index, res): (_, Fallible<Vec<u8>>)| -> Fallible<()> {
Expand Down
31 changes: 22 additions & 9 deletions src/pgp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,38 @@ pub mod gpg {
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GPGBackend {
temp_dir: PathBuf,
keyring: PathBuf,
quiet: bool,
}

impl GPGBackend {
pub fn new(temp: Option<PathBuf>, quiet: bool) -> Self {
let tmp = temp.unwrap_or(temp_dir());
let keyring = match tempdir_in(tmp.clone()) {
Ok(dir) => dir.into_path().clone().join("keyring.gpg"),
Err(_err) => {
eprintln!("Keyring temp dir is unwrittable... Switch to fallback keyring");
tmp.clone().join("cypherpunk-cli_keyring.gpg")
}
};
return Self {
quiet,
temp_dir: temp.unwrap_or(temp_dir()),
temp_dir: tmp,
keyring,
};
}
}

impl Default for GPGBackend {
fn default() -> Self {
return Self {
quiet: false,
temp_dir: temp_dir(),
};
Self::new(None, false)
}
}

impl PGPBackend for GPGBackend {
fn import_key(&self, key: Vec<u8>) -> Fallible<()> {
let quiet = if self.quiet { "-q" } else { "" };
let keyring = &self.keyring;

let tmp_path = tempdir_in(self.temp_dir.clone())
.context("Cannot create a temporary directory to import the key!")?
Expand All @@ -60,7 +68,8 @@ pub mod gpg {
.args(&[
"/C",
format!(
"gpg --import --yes {} {}",
"gpg --no-default-keyring --keyring={} --import --yes {} {}",
keyring.to_string_lossy(),
quiet,
key_path.to_string_lossy()
)
Expand All @@ -73,7 +82,8 @@ pub mod gpg {
.arg("-c")
.arg(
format!(
"gpg --import --yes {} {}",
"gpg --no-default-keyring --keyring={} --import --yes {} {}",
keyring.to_string_lossy(),
quiet,
key_path.to_string_lossy()
)
Expand All @@ -100,6 +110,7 @@ pub mod gpg {
recipients: Vec<String>,
) -> Fallible<()> {
let quiet = if self.quiet { "-q" } else { "" };
let keyring = &self.keyring;

let tmp_path = tempdir_in(self.temp_dir.clone())
.context("Cannot create a temporary directory to encrypt your message!")?
Expand All @@ -123,7 +134,8 @@ pub mod gpg {
Command::new("cmd")
.arg("/C")
.arg(format!(
r#"gpg -R "{}" -a -o {} {} --always-trust -e {}"#,
r#"gpg --no-default-keyring --keyring={} -R "{}" -a -o {} {} --always-trust -e {}"#,
keyring.to_string_lossy(),
recipients,
out_path.to_string_lossy(),
quiet,
Expand All @@ -135,7 +147,8 @@ pub mod gpg {
Command::new("sh")
.arg("-c")
.arg(format!(
r#"gpg -R "{}" -a -o {} {} --always-trust -e {}"#,
r#"gpg --no-default-keyring --keyring={} -R "{}" -a -o {} {} --always-trust -e {}"#,
keyring.to_string_lossy(),
recipients,
out_path.to_string_lossy(),
quiet,
Expand Down

0 comments on commit 1b38c58

Please sign in to comment.