use cotton::prelude::*;
use cbradio::crypto::{
generate_encryption_key, generate_signing_key,
encode,
default_base_staion_public_key_file, default_base_staion_secret_key_file,
default_network_public_key_file, default_network_secret_key_file,
SignPublicKey,
};
use cbradio::with_create_dir;
#[derive(Debug, StructOpt)]
enum KeyPair {
BaseStation,
Network,
}
#[derive(Debug, StructOpt)]
struct Cli {
#[structopt(flatten)]
logging: LoggingOpt,
#[structopt(long, short = "k")]
public_key: Option<PathBuf>,
#[structopt(long, short = "K")]
secret_key: Option<PathBuf>,
#[structopt(subcommand)]
key_pair: KeyPair,
}
fn write_key_pair(public_key_file: &Path, secret_key_file: &Path, generate_key_pair: impl Fn() -> ([u8; 32], [u8; 32])) -> PResult<()> {
if public_key_file.exists() {
problem!("Public key file already exists")?;
}
if secret_key_file.exists() {
problem!("Secret key file already exists")?;
}
let (public_key, secret_key) = generate_key_pair();
write(public_key_file, encode(&public_key))?;
println!("Written public key: {}", public_key_file.display());
with_umask(0o077, || write(secret_key_file, encode(&secret_key)))?;
println!("Written public key: {}", secret_key_file.display());
Ok(())
}
fn main() -> FinalResult {
let args = Cli::from_args();
init_logger(&args.logging, vec![module_path!()]);
match args.key_pair {
KeyPair::BaseStation => {
let public_key_file = args.public_key.map(Ok).unwrap_or_else(|| with_create_dir(default_base_staion_public_key_file()))?;
let secret_key_file = args.secret_key.map(Ok).unwrap_or_else(|| with_create_dir(default_base_staion_secret_key_file()))?;
write_key_pair(&public_key_file, &secret_key_file, || {
let key = generate_signing_key();
let pub_key: SignPublicKey = (&key).into();
(pub_key.to_bytes(), key.to_bytes())
})?;
},
KeyPair::Network => {
let public_key_file = args.public_key.map(Ok).unwrap_or_else(|| with_create_dir(default_network_public_key_file()))?;
let secret_key_file = args.secret_key.map(Ok).unwrap_or_else(|| with_create_dir(default_network_secret_key_file()))?;
write_key_pair(&public_key_file, &secret_key_file, || {
let key = generate_encryption_key();
let pub_key = key.public_key();
(*pub_key.as_bytes(), key.to_bytes())
})?;
},
};
Ok(())
}