#![allow(clippy::expect_used)]
mod arith;
mod data;
mod elgamal;
mod factors;
mod io;
#[cfg(feature = "json")]
mod json;
mod keys;
use clap::{CommandFactory, Parser, Subcommand};
use io::Output;
#[derive(Parser)]
#[command(
name = "peppy",
version,
about = "Polymorphic encryption and pseudonymization from the command line",
long_about = "Operations on PEP pseudonyms and attributes: key setup, encryption, \
transcryption between domains and sessions, and the underlying ElGamal \
primitives.\n\nAny value argument may be `-` to read it from standard input \
or `@path` to read it from a file. Scalars and group elements are hex, \
ciphertexts base64; long values are space-separated (plain) or `|`-separated \
(encrypted) blocks."
)]
struct Cli {
#[arg(long, global = true)]
json: bool,
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
#[command(subcommand)]
Keys(keys::Keys),
#[command(subcommand)]
Factors(factors::Factors),
#[command(subcommand)]
Pseudonym(data::PseudonymCommand),
#[command(subcommand)]
Attribute(data::AttributeCommand),
#[cfg(feature = "json")]
#[command(subcommand)]
Json(json::Json),
#[command(subcommand)]
Elgamal(elgamal::Elgamal),
#[command(subcommand)]
Scalar(arith::Scalar),
#[command(subcommand)]
Point(arith::Point),
Completions { shell: clap_complete::Shell },
Man,
}
fn run(command: Command, out: &mut Output) -> io::Result<()> {
let mut rng = rand::rng();
match command {
Command::Keys(cmd) => keys::run(cmd, &mut rng, out),
Command::Factors(cmd) => factors::run(cmd, out),
Command::Pseudonym(cmd) => data::run_pseudonym(cmd, &mut rng, out),
Command::Attribute(cmd) => data::run_attribute(cmd, &mut rng, out),
#[cfg(feature = "json")]
Command::Json(cmd) => json::run(cmd, &mut rng, out),
Command::Elgamal(cmd) => elgamal::run(cmd, &mut rng, out),
Command::Scalar(cmd) => arith::run_scalar(cmd, &mut rng, out),
Command::Point(cmd) => arith::run_point(cmd, &mut rng, out),
Command::Completions { shell } => {
clap_complete::generate(shell, &mut Cli::command(), "peppy", &mut std::io::stdout());
Ok(())
}
Command::Man => {
let mut buf = Vec::new();
clap_mangen::Man::new(Cli::command()).render(&mut buf)?;
std::io::Write::write_all(&mut std::io::stdout(), &buf)?;
Ok(())
}
}
}
fn main() {
let cli = Cli::parse();
let mut out = Output::new(cli.json);
match run(cli.command, &mut out) {
Ok(()) => out.finish(),
Err(e) => {
eprintln!("peppy: {e}");
std::process::exit(e.code);
}
}
}