Crate thrussh_keys[][src]

This crate contains methods to deal with SSH keys, as defined in crate Thrussh. This includes in particular various functions for opening key files, deciphering encrypted keys, and dealing with agents.

The following example shows how to do all these in a single example: start and SSH agent server, connect to it with a client, decipher an encrypted private key (the password is b"blabla"), send it to the agent, and ask the agent to sign a piece of data (`b"Please sign this", below).

 extern crate thrussh_keys;
 extern crate futures;
 extern crate tempdir;
 extern crate tokio_uds;
 extern crate tokio;
 use thrussh_keys::*;
 use futures::Future;

 struct F(bool);
 impl std::convert::From<bool> for F {
     fn from(e: bool) -> Self {
         F(e)
     }
 }
 impl futures::Future for F {
     type Item = bool;
     type Error = Error;
     fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
         Ok(futures::Async::Ready(self.0))
     }
 }
 #[derive(Clone)]
 struct X{}
 impl agent::server::Agent for X {
     type F = F;
     fn confirm(&self, pk: &key::KeyPair) -> Self::F {
         F(true)
     }
 }


 const PKCS8_ENCRYPTED: &'static str = "-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQITo1O0b8YrS0CAggA\nMAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBBtLH4T1KOfo1GGr7salhR8BIIE\n0KN9ednYwcTGSX3hg7fROhTw7JAJ1D4IdT1fsoGeNu2BFuIgF3cthGHe6S5zceI2\nMpkfwvHbsOlDFWMUIAb/VY8/iYxhNmd5J6NStMYRC9NC0fVzOmrJqE1wITqxtORx\nIkzqkgFUbaaiFFQPepsh5CvQfAgGEWV329SsTOKIgyTj97RxfZIKA+TR5J5g2dJY\nj346SvHhSxJ4Jc0asccgMb0HGh9UUDzDSql0OIdbnZW5KzYJPOx+aDqnpbz7UzY/\nP8N0w/pEiGmkdkNyvGsdttcjFpOWlLnLDhtLx8dDwi/sbEYHtpMzsYC9jPn3hnds\nTcotqjoSZ31O6rJD4z18FOQb4iZs3MohwEdDd9XKblTfYKM62aQJWH6cVQcg+1C7\njX9l2wmyK26Tkkl5Qg/qSfzrCveke5muZgZkFwL0GCcgPJ8RixSB4GOdSMa/hAMU\nkvFAtoV2GluIgmSe1pG5cNMhurxM1dPPf4WnD+9hkFFSsMkTAuxDZIdDk3FA8zof\nYhv0ZTfvT6V+vgH3Hv7Tqcxomy5Qr3tj5vvAqqDU6k7fC4FvkxDh2mG5ovWvc4Nb\nXv8sed0LGpYitIOMldu6650LoZAqJVv5N4cAA2Edqldf7S2Iz1QnA/usXkQd4tLa\nZ80+sDNv9eCVkfaJ6kOVLk/ghLdXWJYRLenfQZtVUXrPkaPpNXgD0dlaTN8KuvML\nUw/UGa+4ybnPsdVflI0YkJKbxouhp4iB4S5ACAwqHVmsH5GRnujf10qLoS7RjDAl\no/wSHxdT9BECp7TT8ID65u2mlJvH13iJbktPczGXt07nBiBse6OxsClfBtHkRLzE\nQF6UMEXsJnIIMRfrZQnduC8FUOkfPOSXc8r9SeZ3GhfbV/DmWZvFPCpjzKYPsM5+\nN8Bw/iZ7NIH4xzNOgwdp5BzjH9hRtCt4sUKVVlWfEDtTnkHNOusQGKu7HkBF87YZ\nRN/Nd3gvHob668JOcGchcOzcsqsgzhGMD8+G9T9oZkFCYtwUXQU2XjMN0R4VtQgZ\nrAxWyQau9xXMGyDC67gQ5xSn+oqMK0HmoW8jh2LG/cUowHFAkUxdzGadnjGhMOI2\nzwNJPIjF93eDF/+zW5E1l0iGdiYyHkJbWSvcCuvTwma9FIDB45vOh5mSR+YjjSM5\nnq3THSWNi7Cxqz12Q1+i9pz92T2myYKBBtu1WDh+2KOn5DUkfEadY5SsIu/Rb7ub\n5FBihk2RN3y/iZk+36I69HgGg1OElYjps3D+A9AjVby10zxxLAz8U28YqJZm4wA/\nT0HLxBiVw+rsHmLP79KvsT2+b4Diqih+VTXouPWC/W+lELYKSlqnJCat77IxgM9e\nYIhzD47OgWl33GJ/R10+RDoDvY4koYE+V5NLglEhbwjloo9Ryv5ywBJNS7mfXMsK\n/uf+l2AscZTZ1mhtL38efTQCIRjyFHc3V31DI0UdETADi+/Omz+bXu0D5VvX+7c6\nb1iVZKpJw8KUjzeUV8yOZhvGu3LrQbhkTPVYL555iP1KN0Eya88ra+FUKMwLgjYr\nJkUx4iad4dTsGPodwEP/Y9oX/Qk3ZQr+REZ8lg6IBoKKqqrQeBJ9gkm1jfKE6Xkc\nCog3JMeTrb3LiPHgN6gU2P30MRp6L1j1J/MtlOAr5rux\n-----END ENCRYPTED PRIVATE KEY-----\n";

 fn main() {
     let dir = tempdir::TempDir::new("thrussh").unwrap();
     let agent_path = dir.path().join("agent");

     let mut core = tokio::runtime::Runtime::new().unwrap();
     let listener = tokio_uds::UnixListener::bind(&agent_path).unwrap().incoming();

     core.spawn(
         agent::server::AgentServer::new(listener, X{})
             .map_err(|e| println!("{:?}", e))
     );

     let key = decode_secret_key(PKCS8_ENCRYPTED, Some(b"blabla")).unwrap();
     let public = key.clone_public_key();
     core.block_on(
         tokio_uds::UnixStream::connect(&agent_path).from_err().and_then(move |stream| {
             agent::client::AgentClient::connect(stream)
                 .add_identity(&key, &[agent::Constraint::KeyLifetime { seconds: 60 }]).and_then(move |(client, _)| {
                     client.request_identities().and_then(move |(client, id)| {
                         client.sign_request(&public, b"Please sign this").and_then(|(_, sig)| {
                             let sig = sig.unwrap();
                             futures::finished(())
                         })
                     })
                 })
         })
     ).unwrap();
 }

Modules

agent

A module to write SSH agent.

encoding
key
signature

Structs

Error

The Error type.

Enums

Encryption

AES encryption key.

ErrorKind

The kind of an error.

Traits

PublicKeyBase64
ResultExt

Additional methods for Result, for easy interaction with this crate.

Functions

check_known_hosts

Check whether the host is known, from its standard location.

check_known_hosts_path

Check that a server key matches the one recorded in file path.

decode_openssh

Decode a secret key given in the OpenSSH format, deciphering it if needed using the supplied password.

decode_pkcs5

Decode a secret key in the PKCS#5 format, possible deciphering it using the supplied password.

decode_secret_key

Decode a secret key, possibly deciphering it with the supplied password.

encode_pkcs8_pem
encode_pkcs8_pem_encrypted
learn_known_hosts

Record a host's public key into the user's known_hosts file.

learn_known_hosts_path

Record a host's public key into a nonstandard location.

load_public_key

Load a public key from a file. Ed25519 and RSA keys are supported.

load_secret_key

Load a secret key, deciphering it with the supplied password if necessary.

parse_public_key_base64

Reads a public key from the standard encoding. In some cases, the encoding is prefixed with a key type identifier and a space (such as ssh-ed25519 AAAAC3N...).

write_public_key_base64

Write a public key onto the provided Write, encoded in base-64.

Type Definitions

Result

Convenient wrapper around std::Result.