extern crate downify;
extern crate structopt;
use std::fs;
use std::io::Write;
use std::io::stdout;
use url::Url;
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
#[structopt(name = "Downify")]
struct Opt {
#[structopt(short = "G")]
generate: bool,
#[structopt(short = "S")]
sign: bool,
#[structopt(short = "V")]
local: bool,
#[structopt(short = "R")]
remote: bool,
#[structopt(short)]
message: Option<String>,
#[structopt(short)]
url: Option<String>,
#[structopt(short, default_value = "publickey")]
pubkey: String,
#[structopt(short, default_value = "secretkey")]
seckey: String,
#[structopt(short = "x", default_value = "signature")]
sigfile: String,
}
fn main() {
let opt = Opt::from_args();
let mut selected_modes = 0;
if opt.generate { selected_modes += 1; }
if opt.sign { selected_modes += 1; }
if opt.local { selected_modes += 1; }
if opt.remote { selected_modes += 1; }
if selected_modes != 1 {
println!("Please use one of the -G, -S, -V, or -R flags.");
return;
}
if opt.generate {
let (pk, sk) = downify::gen_keypair();
fs::write(opt.pubkey, pk).expect("Unable to write public key");
fs::write(opt.seckey, sk).expect("Unable to write secret key");
} else if opt.sign {
if opt.message.is_none() {
println!("Please specify a file to sign with the -m option.");
return;
}
let secret_key = fs::read_to_string(opt.seckey).expect("Unable to read secret key");
let signature = downify::sign(&opt.message.unwrap(), &secret_key);
fs::write(opt.sigfile, signature).expect("Unable to write signature");
} else if opt.local {
if opt.message.is_none() {
println!("Please specify a file to verify with the -m option.");
return;
}
let signature = fs::read_to_string(opt.sigfile).expect("Unable to read signature");
let public_key = fs::read_to_string(opt.pubkey).expect("Unable to read public key");
let verified = downify::verify_open(&opt.message.unwrap(), &signature, &public_key);
if verified.is_some() {
println!("Verification Success");
} else {
println!("Verification Failed");
}
} else if opt.remote {
if opt.url.is_none() {
println!("Please specify a URL to verify with the -u option.");
return;
}
let signature = fs::read_to_string(opt.sigfile).expect("Unable to read signature");
let public_key = fs::read_to_string(opt.pubkey).expect("Unable to read public key");
let url_clone = opt.url.clone().unwrap();
let parsed_url = Url::parse(&url_clone).expect("Invalid URL");
let dest = parsed_url.path_segments().unwrap().last().unwrap();
let mut context = downify::Context::new(&url_clone, &dest, &signature, &public_key, 1024*1024).unwrap();
loop {
let progress = context.step().unwrap();
print!("\r{:?} / {:?} bytes", progress.completed_bytes, progress.total_bytes);
stdout().flush().ok().expect("Could not flush stdout");
if progress.completed_bytes >= progress.total_bytes {
break;
}
}
let verified = context.finish();
if verified.is_some() {
println!("\nVerification Success");
} else {
println!("\nVerification Failed");
}
}
}