use signature::Signer; use ssh_agent_lib::agent::{Agent, Session}; use ssh_agent_lib::proto::message::Message; use ssh_key::public::PublicKey; use ssh_key::private::PrivateKey; use tokio::net::UnixListener; struct SshAgent; impl std::default::Default for SshAgent { fn default() -> Self { SshAgent {} } } #[ssh_agent_lib::async_trait] impl Session for SshAgent { async fn handle(&mut self, message: Message) -> Result> { println!("Received message"); match message { Message::RequestIdentities => { let p = std::path::PathBuf::from("/home/joe/.ssh/id_ed25519.pub"); let pubkey = PublicKey::read_openssh_file(&p).unwrap(); let id = ssh_agent_lib::proto::message::Identity { pubkey_blob: pubkey.to_bytes().unwrap(), comment: pubkey.comment().to_owned(), }; Ok(Message::IdentitiesAnswer(vec![id])) }, Message::SignRequest(req) => { println!("Received sign request"); let mut req_bytes = vec![13]; encode_string(&mut req_bytes, &req.pubkey_blob); encode_string(&mut req_bytes, &req.data); req_bytes.extend(req.flags.to_be_bytes()); std::fs::File::create("/tmp/signreq").unwrap().write(&req_bytes).unwrap(); let p = std::path::PathBuf::from("/home/joe/.ssh/id_ed25519"); let passphrase = std::env::var("PRIVKEY_PASSPHRASE").unwrap(); let privkey = PrivateKey::read_openssh_file(&p) .unwrap() .decrypt(passphrase.as_bytes()) .unwrap(); let sig = Signer::sign(&privkey, &req.data); use std::io::Write; std::fs::File::create("/tmp/sig").unwrap().write(sig.as_bytes()).unwrap(); let mut payload = Vec::with_capacity(128); encode_string(&mut payload, "ssh-ed25519".as_bytes()); encode_string(&mut payload, sig.as_bytes()); println!("Payload length: {}", payload.len()); std::fs::File::create("/tmp/payload").unwrap().write(&payload).unwrap(); Ok(Message::SignResponse(payload)) }, _ => Ok(Message::Failure), } } } fn encode_string(buf: &mut Vec, s: &[u8]) { let len = s.len() as u32; buf.extend(len.to_be_bytes()); buf.extend(s); } pub async fn run() { let socket = "/tmp/creddy-agent.sock"; let _ = std::fs::remove_file(socket); let listener = UnixListener::bind(socket).unwrap(); SshAgent.listen(listener).await.unwrap(); }