use std::io::BufReader; use std::fs::File; use std::io::prelude::*; use rand::rngs::OsRng; use ed25519_dalek::SigningKey; use ed25519_dalek::Signature; use ed25519_dalek::Signer; use ed25519_dalek::Verifier; use ed25519_dalek::VerifyingKey; use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, SIGNATURE_LENGTH}; fn main() -> std::io::Result<()>{ let action = std::env::args().nth(1).expect("no command given"); if action == "sign" { let keyfilepath = std::env::args().nth(2).expect("no keyfilepath given"); let messagefilepath = std::env::args().nth(3).expect("no message given"); let maybe_signature_filepath = std::env::args().nth(4); let mut keyfile = File::open(&keyfilepath).expect("no file found"); let mut keybuffer: [u8; 32] = [0; SECRET_KEY_LENGTH]; keyfile.read(&mut keybuffer).expect("buffer overflow"); let signing_key: SigningKey = SigningKey::from_bytes(&keybuffer); let messagefile= File::open(&messagefilepath).expect("no file found"); let mut messagereader = BufReader::new(messagefile); let mut messagebuf = Vec::new(); messagereader.read_to_end(&mut messagebuf)?; println!("Using key {keyfilepath}"); let signature: Signature = signing_key.sign(&messagebuf); if maybe_signature_filepath.is_some() { let filename = maybe_signature_filepath.expect("Not possible"); let mut file = File::create(filename.clone())?; println!("Writing signature to {filename}"); file.write_all(&signature.to_bytes())?; } else { println!("Signture: {signature}"); } } else if action == "validate" { let public_key_filepath = std::env::args().nth(2).expect("no key filepath given"); let message_filepath = std::env::args().nth(3).expect("no message filepath given"); let signature_filepath = std::env::args().nth(4).expect("no signature filepath given"); let mut public_keyfile = File::open(&public_key_filepath).expect("no file found"); let mut public_keybuffer: [u8; PUBLIC_KEY_LENGTH] = [0; PUBLIC_KEY_LENGTH]; public_keyfile.read(&mut public_keybuffer).expect("buffer overflow"); let public_key: VerifyingKey = VerifyingKey::from_bytes(&public_keybuffer).expect("Faled to make a key"); let messagefile= File::open(&message_filepath).expect("no file found"); let mut messagereader = BufReader::new(messagefile); let mut messagebuf = Vec::new(); messagereader.read_to_end(&mut messagebuf)?; let signature_file = File::open(&signature_filepath).expect("no file found"); let mut signature_reader = BufReader::new(signature_file); let mut signature_buf: [u8; SIGNATURE_LENGTH] = [0; SIGNATURE_LENGTH]; signature_reader.read(&mut signature_buf).expect("buffer overflow"); let signature: Signature = Signature::try_from(&signature_buf[..]).expect("not a signature"); if public_key.verify(&messagebuf, &signature).is_ok() { println!("Yep, that checks out."); } else { println!("Invalid signature."); } } else if action == "create" { let signing_key_filepath = std::env::args().nth(2).expect("no signing key file path given"); let verifying_key_filepath = std::env::args().nth(3).expect("no verifying key file path given"); let mut csprng = OsRng; let signing_key: SigningKey = SigningKey::generate(&mut csprng); println!("Writing new private key to {signing_key_filepath}"); let mut file = File::create(signing_key_filepath)?; file.write_all(&signing_key.to_bytes())?; println!("Writing new public key to {verifying_key_filepath}"); let verifying_key: VerifyingKey = signing_key.verifying_key(); file = File::create(verifying_key_filepath)?; file.write_all(&verifying_key.to_bytes())?; } else { println!("Unrecognized command {action}"); } return Ok(()); }