cli encrypt, decrypt, asym

This commit is contained in:
2025-05-19 20:39:33 +02:00
parent f1f59dcec6
commit e46076355d
2 changed files with 89 additions and 30 deletions

View File

@ -7,6 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
clap = { version = "4.5.38", features = ["derive"] } clap = { version = "4.5.38", features = ["derive"] }
hex = "0.4.3"
rand = "0.9.1" rand = "0.9.1"
rug = "1.27.0" rug = "1.27.0"

View File

@ -1,12 +1,13 @@
mod bootstrapping; mod bootstrapping;
mod dghv; mod dghv;
mod dghv_asym; mod dghv_asym;
mod fileutils;
mod utils; mod utils;
use crate::dghv::{decrypt_bit, encrypt_bit, generate_secret_key}; use crate::dghv::{decrypt_bit, encrypt_bit, generate_secret_key};
use std::path::{Path, PathBuf}; use crate::dghv_asym::{encrypt_bit_asym, generate_keys};
use crate::fileutils::{read_privkey, read_pubkey, write_privkey, write_pubkey};
use clap::{ArgGroup, Args, Parser, Subcommand};
use rug::Integer; use rug::Integer;
use clap::{Parser, Subcommand};
#[derive(Parser)] #[derive(Parser)]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
@ -25,26 +26,58 @@ enum Commands {
size: u32, size: u32,
}, },
/// Encrypt a single bit /// Encrypt a single bit
Encrypt { Encrypt(EncryptArgs),
/// bit to encrypt (0 or 1) /// Decrypt a single bit
#[clap(short = 'b', long)] Decrypt(DecryptArgs),
bit: u8, /// Generate pair (pubkey, privkey)
/// secret key (hex) KeygenPair {
#[clap(short = 'k', long)] /// output path prefix for keys
key: String, #[arg(short = 'o', long)]
path: String,
/// security parameter eta (p bit-length)
#[clap(short = 's', long, default_value_t = 6400)]
size: u32,
/// noise parameter /// noise parameter
#[clap(short = 'n', long, default_value_t = 80)] #[clap(short = 'n', long, default_value_t = 80)]
noise: u32, noise: u32,
/// number of public key elements (theta)
#[arg(short = 't', long, default_value_t = 10)]
theta: usize,
}, },
/// Decrypt a single bit }
Decrypt {
/// ciphertext to decrypt (hex) #[derive(Args)]
#[clap(short = 'c', long)] #[command(group(ArgGroup::new("keysource").required(true).args(&["key", "privkey", "pubkey"])))]
ciphertext: String, struct EncryptArgs {
/// secret key (hex) /// bit to encrypt
#[clap(short = 'k', long)] #[arg(short = 'b', long)]
key: String, bit: u8,
}, /// Key as hex string
#[arg(short = 'k', long)]
key: Option<String>,
/// path to private key file
#[arg(long)]
privkey: Option<String>,
/// path to public key file
#[arg(long)]
pubkey: Option<String>,
/// noise parameter
#[arg(short = 'n', long, default_value_t = 80)]
noise: u32,
}
#[derive(Args)]
#[command(group(ArgGroup::new("keysource").required(true).args(&["key", "privkey"])))]
struct DecryptArgs {
/// ciphertext to decrypt (hex-encoded)
#[arg(short = 'c', long)]
ciphertext: String,
/// key as hex string
#[arg(short = 'k', long)]
key: Option<String>,
/// path to private key file
#[arg(long)]
privkey: Option<String>,
} }
fn main() { fn main() {
@ -52,22 +85,47 @@ fn main() {
match cli.command { match cli.command {
Commands::Keygen { size } => { Commands::Keygen { size } => {
let sk = generate_secret_key(size as u32); let sk = generate_secret_key(size);
println!("Secret key (p): {}", sk.to_string_radix(16)); println!("Secret key (p): {}", sk.to_string_radix(16));
} }
Commands::Encrypt { bit, key, noise } => { Commands::Encrypt(args) => {
let p = Integer::from_str_radix(&key, 16) let ct = if let Some(pub_path) = args.pubkey {
.expect("Invalid secret key: must be hexadecimal integer"); let pk = read_pubkey(pub_path).expect("Failed to load public key");
let ct = encrypt_bit(bit, &p, noise as u32, noise as u32); encrypt_bit_asym(args.bit, &pk, args.noise)
println!("Encrypted bit (c): {}", ct.to_string_radix(16)); } else {
let p = if let Some(hex_str) = args.key {
Integer::from_str_radix(&hex_str, 16).expect("Invalid key hex")
} else {
read_privkey(args.privkey.unwrap())
.expect("Failed to load private key")
.p
};
encrypt_bit(args.bit, &p, args.noise, args.noise)
};
println!("Encrypted bit (hex): {}", ct.to_string_radix(16));
} }
Commands::Decrypt { ciphertext, key } => { Commands::Decrypt(args) => {
let p = Integer::from_str_radix(&key, 16) let p = if let Some(hex_str) = args.key {
.expect("Invalid secret key: must be hexadecimal integer"); Integer::from_str_radix(&hex_str, 16).expect("Invalid key hex")
let ct = Integer::from_str_radix(&ciphertext, 16) } else {
.expect("Invalid ciphertext: must be hexadecimal integer"); read_privkey(args.privkey.unwrap())
.expect("Failed to load private key")
.p
};
let ct = Integer::from_str_radix(&args.ciphertext, 16).expect("Invalid ciphertext");
let res = decrypt_bit(&ct, &p); let res = decrypt_bit(&ct, &p);
println!("Decrypted bit: {}", res); println!("Decrypted bit: {}", res);
} }
Commands::KeygenPair {
path,
size,
noise,
theta,
} => {
let (sk, pk) = generate_keys(noise, size, noise, theta);
write_privkey(&path, &sk).expect("Failed to write privkey");
write_pubkey(&path, &pk).expect("Failed to write pubkey");
println!("keys written to {}.[privkey|pubkey]", path);
}
} }
} }