sshkeys-0.3.2/.cargo_vcs_info.json0000644000000001360000000000100125270ustar { "git": { "sha1": "f27b78dda932a3a24b9cfafd28de3e0b1efe6e8b" }, "path_in_vcs": "" }sshkeys-0.3.2/.gitignore000064400000000000000000000000410072674642500133320ustar 00000000000000target/ **/*.rs.bk Cargo.lock *~ sshkeys-0.3.2/.travis.yml000064400000000000000000000001550072674642500134610ustar 00000000000000language: rust rust: - stable - beta - nightly matrix: allow_failures: - nightly cache: cargo sshkeys-0.3.2/Cargo.lock0000644000000057350000000000100105140ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "base64" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" [[package]] name = "block-buffer" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" dependencies = [ "block-padding", "byte-tools", "byteorder", "generic-array", ] [[package]] name = "block-padding" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" dependencies = [ "byte-tools", ] [[package]] name = "byte-tools" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "digest" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ "generic-array", ] [[package]] name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "generic-array" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" dependencies = [ "typenum", ] [[package]] name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "serde" version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" [[package]] name = "serde_test" version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21675ba6f9d97711cc00eee79d8dd7d0a31e571c350fb4d8a7c78f70c0e7b0e9" dependencies = [ "serde", ] [[package]] name = "sha2" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" dependencies = [ "block-buffer", "digest", "fake-simd", "opaque-debug", ] [[package]] name = "sshkeys" version = "0.3.2" dependencies = [ "base64", "byteorder", "serde", "serde_test", "sha2", ] [[package]] name = "typenum" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" sshkeys-0.3.2/Cargo.toml0000644000000021620000000000100105260ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] name = "sshkeys" version = "0.3.2" authors = ["Marin Atanasov Nikolov "] description = "Rust library for parsing OpenSSH certificates and public keys" documentation = "https://docs.rs/sshkeys" readme = "README.md" keywords = ["ssh", "openssh", "parser", "key", "certificate"] categories = ["cryptography", "parser-implementations", "encoding"] license-file = "LICENSE" repository = "https://github.com/dnaeon/rust-sshkeys" [dependencies.base64] version = "0.12.1" [dependencies.byteorder] version = "1.3.4" [dependencies.serde] version = "1" optional = true [dependencies.sha2] version = "0.8.1" [dev-dependencies.serde_test] version = "1" sshkeys-0.3.2/Cargo.toml.orig000064400000000000000000000011300072674642500142310ustar 00000000000000[package] name = "sshkeys" version = "0.3.2" authors = ["Marin Atanasov Nikolov "] description = "Rust library for parsing OpenSSH certificates and public keys" documentation = "https://docs.rs/sshkeys" repository = "https://github.com/dnaeon/rust-sshkeys" readme = "README.md" keywords = ["ssh", "openssh", "parser", "key", "certificate"] categories = ["cryptography", "parser-implementations", "encoding"] license-file = "LICENSE" [dependencies] base64 = "0.12.1" byteorder = "1.3.4" sha2 = "0.8.1" serde = { version = "1", optional = true } [dev-dependencies] serde_test = "1" sshkeys-0.3.2/LICENSE000064400000000000000000000024510072674642500123560ustar 00000000000000Copyright (c) 2017 Marin Atanasov Nikolov All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer in this position and unchanged. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. sshkeys-0.3.2/README.md000064400000000000000000000024340072674642500126310ustar 00000000000000## sshkeys - Rust library for parsing OpenSSH public keys and certificates [![Build Status](https://travis-ci.org/dnaeon/rust-sshkeys.svg?branch=master)](https://travis-ci.org/dnaeon/rust-sshkeys) [![Docs](https://docs.rs/sshkeys/badge.svg)](https://docs.rs/sshkeys/) The `sshkeys` crate is a Rust library, which provides types and methods for parsing OpenSSH public keys and certificates. In order to use this crate in your project, simply add the following to your `Cargo.toml` file. ```toml [dependencies] sshkeys = "0.1.1" ``` ## Tests In order to test this crate locally, execute the following command. ```bash $ cargo test ``` ## Documentation The `sshkeys` crate has documentation, which you can build and view locally. ```bash $ cargo doc --open ``` ## Examples For examples on how to use this crate, please refer to the `examples` directory. In order to run an example, simply execute the following command. ```bash $ cargo run --example ``` ## Contributions The `sshkeys` crate is hosted on [Github](https://github.com/dnaeon/rust-sshkeys). Please contribute by reporting issues, suggesting features or by sending patches using pull requests. ## License This project is Open Source and licensed under the [BSD License](http://opensource.org/licenses/BSD-2-Clause). sshkeys-0.3.2/examples/certificate.rs000064400000000000000000000014150072674642500160160ustar 00000000000000extern crate sshkeys; fn main() { let cert = sshkeys::Certificate::from_path("examples/id_ed25519-cert.pub").unwrap(); println!("Type: {} {}", cert.key_type.name, cert.cert_type); println!("Public key: {}", cert.key); println!("Signing CA: {}", cert.signature_key); println!("Key ID: {}", cert.key_id); println!("Serial: {}", cert.serial); println!("Valid from {} to {}", cert.valid_after, cert.valid_before); println!("Principals:"); for p in cert.valid_principals { println!("\t{}", p); } println!("Critical Options:"); for (name, value) in cert.critical_options { println!("\t{} {}", name, value); } println!("Extensions:"); for (name, _) in cert.extensions { println!("\t{}", name); } } sshkeys-0.3.2/examples/id_ed25519-cert.pub000064400000000000000000000023320072674642500163020ustar 00000000000000ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIEiLBwyltbppduCgS0d6CdF1YNayWQ3fwPCJuD9YSybIAAAAIMIVp6q5co/r5GwY0dH+NYQbfKicapeF3gXEU3dzaAvDAAAAAAAAAAAAAAABAAAACGpvaG4uZG9lAAAACAAAAARyb290AAAAAFnR/XwAAAAAW7Hf4QAAACYAAAANZm9yY2UtY29tbWFuZAAAABEAAAANL3Vzci9iaW4vdHJ1ZQAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAJ1L6RsW758SzSjA9CAI6HpuUaJMd9fX75rtVeGSBd7S7rpnuY/aLdCKE3X6T1C7OKExBa6fMldoy98H6cK181Xei2WNQaJgy2MmgSKQApEoqZCiKs/GeDBDDiWBtLF+a+nYviI0f+jG7iGqTMQXfXBb9vkha88HQetQXojj6qXQHoGB75cb6fCmkq8plyubcDlOob7a9kEMsCrxknjBDZiha8nlUp2Dk4AYAY8ME9QW5lCQQz7g+Pb5aY3LUr2lEgJTMn5g1v0HxYWeFRe9Ucups+52O1f8XMOPxmUmfS6/YPijJKtJiYFFaq8l/p8CJJuZjbxidyVVNlp5sLPK9mcAAAEPAAAAB3NzaC1yc2EAAAEAYI/gkKir10GYput31qa61cY1+QYwknS7kvkRVIvSB1idZYwqKSKp99Ra4e+4OUKfJjPxtx8dXJ4KBsh7Fvk8TgTDZjIEUwoUZUSKmaW0GFm9r4H5P5XNJr9ZyDA5MqRKLIfyk2g85q1oQapmRWcIuPF+9N+fU02nW3VbxMTCRePatr0PzkRpA8bBFge8Jfjsyb5s+C6sg7c6i5tZqrc2j5htKGOYePRHMNq9Ik3DJbEjnbyQbKkmoobzlCvHGUaYvR/I7mubhdp89VgqRWPppfITr1jsG4gdel2Xn36PJ8WQnnfqXMb2lJ3/KLyJbqIWBpThyqZtDQIOur5Lo1EiHw== me@home sshkeys-0.3.2/examples/id_rsa_2048.pub000064400000000000000000000006050072674642500156140ustar 00000000000000ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCiChinH9volauTvLfGWv2xCIo0jrQAv0jCQjfDodZW+E1vLFUcgdULKemujxG2vLzLUHfSHF9mjnwnGbyHYZi1fEO70s3gGZNd9K2xwvkGo28svefCfNR3hi+jSB9Q9drvR7CgYdEY5D90Z/OfSWJ4a60/qpD7L3uXf5riqYddDUbHVlDg11SK27KHan33UAfskd5u2AccRbXKJX3I6oO78AwI4/fHs2N/RuoleYcsHX9FNaVX8NHxSEY7EXLTPmykRQj8/8ubjuflvm4qYTsW8cFtRETfxkgFMF0p375YEVQles/6JwRsljnVaobiyeNG1u/5p4zaEguuqN7oVpsP me@home sshkeys-0.3.2/examples/pubkey.rs000064400000000000000000000002200072674642500150240ustar 00000000000000extern crate sshkeys; fn main() { let key = sshkeys::PublicKey::from_path("examples/id_rsa_2048.pub").unwrap(); println!("{}", key); } sshkeys-0.3.2/src/cert.rs000064400000000000000000000174460072674642500134550ustar 00000000000000use std::collections::HashMap; use std::fmt; use std::fs::File; use std::io::Read; use std::path::Path; use super::error::{Error, ErrorKind, Result}; use super::keytype::KeyType; use super::pubkey::PublicKey; use super::reader::Reader; use base64; /// Represents the different types a certificate can be. #[derive(Debug, PartialEq)] pub enum CertType { /// Represents a user certificate. User, /// Represents a host certificate. Host, } impl fmt::Display for CertType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { CertType::User => write!(f, "user certificate"), CertType::Host => write!(f, "host certificate"), } } } /// A type which represents an OpenSSH certificate key. /// Please refer to [PROTOCOL.certkeys] for more details about OpenSSH certificates. /// [PROTOCOL.certkeys]: https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD #[derive(Debug)] pub struct Certificate { /// Type of key. pub key_type: KeyType, /// Cryptographic nonce. pub nonce: Vec, /// Public key part of the certificate. pub key: PublicKey, /// Serial number of certificate. pub serial: u64, /// Represents the type of the certificate. pub cert_type: CertType, /// Key identity. pub key_id: String, /// The list of valid principals for the certificate. pub valid_principals: Vec, /// Time after which certificate is considered as valid. pub valid_after: u64, /// Time before which certificate is considered as valid. pub valid_before: u64, /// Critical options of the certificate. Generally used to /// control features which restrict access. pub critical_options: HashMap, /// Certificate extensions. Extensions are usually used to /// enable features that grant access. pub extensions: HashMap, /// The `reserved` field is currently unused and is ignored in this version of the protocol. pub reserved: Vec, /// Signature key contains the CA public key used to sign the certificate. pub signature_key: PublicKey, /// Signature of the certificate. pub signature: Vec, /// Associated comment, if any. pub comment: Option, } impl Certificate { /// Reads an OpenSSH certificate from a given path. /// /// # Example /// /// ```rust /// # use sshkeys; /// # fn example() -> sshkeys::Result<()> { /// let cert = sshkeys::Certificate::from_path("/path/to/id_ed25519-cert.pub")?; /// # Ok(()) /// # } /// ``` pub fn from_path>(path: P) -> Result { let mut contents = String::new(); File::open(path)?.read_to_string(&mut contents)?; Certificate::from_string(&contents) } /// Reads an OpenSSH certificate from a given string. /// /// # Example /// /// ```rust /// # use sshkeys; /// # fn example() -> sshkeys::Result<()> { /// let cert = sshkeys::Certificate::from_string("ssh-rsa AAAAB3NzaC1yc2EAAAA...")?; /// # Ok(()) /// # } /// ``` pub fn from_string(s: &str) -> Result { let mut iter = s.split_whitespace(); let kt_name = iter .next() .ok_or(Error::with_kind(ErrorKind::InvalidFormat))?; let kt = KeyType::from_name(&kt_name)?; if !kt.is_cert { return Err(Error::with_kind(ErrorKind::NotCertificate)); } let data = iter .next() .ok_or(Error::with_kind(ErrorKind::InvalidFormat))?; let comment = iter.next().map(|v| String::from(v)); let decoded = base64::decode(&data)?; let mut reader = Reader::new(&decoded); // Validate key types before reading the rest of the data let kt_from_reader = reader.read_string()?; if kt_name != kt_from_reader { return Err(Error::with_kind(ErrorKind::KeyTypeMismatch)); } let nonce = reader.read_bytes()?; let key = PublicKey::from_reader(&kt_name, &mut reader)?; let serial = reader.read_u64()?; let cert_type = match reader.read_u32()? { 1 => CertType::User, 2 => CertType::Host, n => return Err(Error::with_kind(ErrorKind::InvalidCertType(n))), }; let key_id = reader.read_string()?; let principals = reader.read_bytes().and_then(|v| read_principals(&v))?; let valid_after = reader.read_u64()?; let valid_before = reader.read_u64()?; let critical_options = reader.read_bytes().and_then(|v| read_options(&v))?; let extensions = reader.read_bytes().and_then(|v| read_options(&v))?; let reserved = reader.read_bytes()?; let signature_key = reader .read_bytes() .and_then(|v| PublicKey::from_bytes(&v))?; let signature = reader.read_bytes()?; let cert = Certificate { key_type: kt, nonce: nonce, key: key, serial: serial, cert_type: cert_type, key_id: key_id, valid_principals: principals, valid_after: valid_after, valid_before: valid_before, critical_options: critical_options, extensions: extensions, reserved: reserved, signature_key: signature_key, signature: signature, comment: comment, }; Ok(cert) } } // Reads `option` values from a byte sequence. // The `option` values are used to represent the `critical options` and // `extensions` in an OpenSSH certificate key, which are represented as tuples // containing the `name` and `data` values of type `string`. // Some `options` are `flags` only (e.g. the certificate extensions) and the // associated value with them is the empty string (""), while others are `string` // options and have an associated value, which is a `string`. // The `critical options` of a certificate are always `string` options, since they // have an associated `string` value, which is embedded in a separate buffer, so // in order to extract the associated value we need to read the buffer first and then // read the `string` value itself. fn read_options(buf: &[u8]) -> Result> { let mut reader = Reader::new(&buf); let mut options = HashMap::new(); // Use a `Reader` and loop until EOF is reached, so that we can // read all options from the provided byte slice. loop { let name = match reader.read_string() { Ok(v) => v, Err(e) => match e.kind { ErrorKind::UnexpectedEof => break, _ => return Err(e), }, }; // If we have a `string` option extract the value from the buffer, // otherwise we have a `flag` option which is the `empty` string. let value_buf = reader.read_bytes()?; let value = if value_buf.len() > 0 { Reader::new(&value_buf).read_string()? } else { "".to_string() }; options.insert(name, value); } Ok(options) } // Reads the `valid principals` field of a certificate key. // The `valid principals` are represented as a sequence of `string` values // embedded in a buffer. // This function reads the whole byte slice until EOF is reached in order to // ensure all principals are read from the byte slice. fn read_principals(buf: &[u8]) -> Result> { let mut reader = Reader::new(&buf); let mut items = Vec::new(); loop { let principal = match reader.read_string() { Ok(v) => v, Err(e) => match e.kind { ErrorKind::UnexpectedEof => break, _ => return Err(e), }, }; items.push(principal); } Ok(items) } sshkeys-0.3.2/src/error.rs000064400000000000000000000053350072674642500136430ustar 00000000000000use std::error::Error as StdError; use std::{fmt, io, result, string}; use base64; /// The `Error` type represents the possible errors that may occur when /// working with OpenSSH keys. #[derive(Debug)] pub struct Error { pub(crate) kind: ErrorKind, } impl Error { pub(crate) fn with_kind(kind: ErrorKind) -> Error { Error { kind: kind } } } /// A type to represent the different kinds of errors. #[derive(Debug)] pub(crate) enum ErrorKind { Io(io::Error), Decode(base64::DecodeError), Utf8Error(string::FromUtf8Error), InvalidCertType(u32), InvalidFormat, UnexpectedEof, NotCertificate, KeyTypeMismatch, UnknownKeyType(String), UnknownCurve(String), } /// A `Result` type alias where the `Err` variant is `Error` pub type Result = result::Result; impl From for Error { fn from(error: io::Error) -> Error { Error { kind: ErrorKind::Io(error), } } } impl From for Error { fn from(error: base64::DecodeError) -> Error { Error { kind: ErrorKind::Decode(error), } } } impl From for Error { fn from(error: string::FromUtf8Error) -> Error { Error { kind: ErrorKind::Utf8Error(error), } } } impl StdError for Error { fn source(&self) -> Option<&(dyn StdError + 'static)> { match self.kind { ErrorKind::Io(ref e) => e.source(), ErrorKind::Decode(ref e) => e.source(), ErrorKind::Utf8Error(ref e) => e.source(), ErrorKind::InvalidCertType(_) | ErrorKind::InvalidFormat | ErrorKind::UnexpectedEof | ErrorKind::NotCertificate | ErrorKind::KeyTypeMismatch | ErrorKind::UnknownCurve(_) | ErrorKind::UnknownKeyType(_) => None, } } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.kind { ErrorKind::Io(ref err) => err.fmt(f), ErrorKind::Decode(ref err) => err.fmt(f), ErrorKind::Utf8Error(ref err) => err.fmt(f), ErrorKind::InvalidFormat => write!(f, "Invalid format"), ErrorKind::InvalidCertType(v) => write!(f, "Invalid certificate type with value {}", v), ErrorKind::UnexpectedEof => write!(f, "Unexpected EOF reached while reading data"), ErrorKind::UnknownKeyType(ref v) => write!(f, "Unknown key type {}", v), ErrorKind::NotCertificate => write!(f, "Not a certificate"), ErrorKind::KeyTypeMismatch => write!(f, "Key type mismatch"), ErrorKind::UnknownCurve(ref v) => write!(f, "Unknown curve {}", v), } } } sshkeys-0.3.2/src/keytype.rs000064400000000000000000000142770072674642500142110ustar 00000000000000use super::error::{Error, ErrorKind, Result}; use std::fmt; /// A type which represents the various kinds of keys. #[derive(Debug, PartialEq)] pub enum KeyTypeKind { /// Represents an RSA key type. Rsa, /// Represents a DSA key type. Dsa, /// Represents an ED25519 key type. Ed25519, /// Represents an ECDSA key type. Ecdsa, /// Represents an RSA certificate key type. RsaCert, /// Represents a DSA certificate key type. DsaCert, /// Represents an ED25519 certificate key type. Ed25519Cert, /// Represents an ECDSA certificate key type. EcdsaCert, /// Represents an ED25519 key type, generated by a security key. Ed25519Sk, /// Represents an ECDSA key type, generated by a security key. EcdsaSk, } /// `KeyType` represents the type of an OpenSSH key. #[derive(Debug, PartialEq)] pub struct KeyType { /// Name of the key type. pub name: &'static str, /// Short name of the key type. pub short_name: &'static str, /// Indicates whether the key type represents a certificate or not. pub is_cert: bool, /// Indicates whether the key type is used with a security key or not pub is_sk: bool, /// Kind of the key type. pub kind: KeyTypeKind, /// The cert-less equivalent to a certified key type. pub plain: &'static str, } impl KeyType { /// Creates a new `KeyType` from a given name. /// /// # Example /// ```rust /// # use sshkeys; /// let kt = sshkeys::KeyType::from_name("ssh-rsa").unwrap(); /// assert_eq!(kt.kind, sshkeys::KeyTypeKind::Rsa); /// ``` pub fn from_name(name: &str) -> Result { let kt = match name { "ssh-rsa" => KeyType { name: "ssh-rsa", plain: "ssh-rsa", short_name: "RSA", is_cert: false, is_sk: false, kind: KeyTypeKind::Rsa, }, "ssh-rsa-cert-v01@openssh.com" => KeyType { name: "ssh-rsa-cert-v01@openssh.com", plain: "ssh-rsa", short_name: "RSA-CERT", is_cert: true, is_sk: false, kind: KeyTypeKind::RsaCert, }, "ssh-dss" => KeyType { name: "ssh-dss", plain: "ssh-dss", short_name: "DSA", is_cert: false, is_sk: false, kind: KeyTypeKind::Dsa, }, "ssh-dss-cert-v01@openssh.com" => KeyType { name: "ssh-dss-cert-v01@openssh.com", plain: "ssh-dss", short_name: "DSA-CERT", is_cert: true, is_sk: false, kind: KeyTypeKind::DsaCert, }, "ecdsa-sha2-nistp256" => KeyType { name: "ecdsa-sha2-nistp256", plain: "ecdsa-sha2-nistp256", short_name: "ECDSA", is_cert: false, is_sk: false, kind: KeyTypeKind::Ecdsa, }, "ecdsa-sha2-nistp384" => KeyType { name: "ecdsa-sha2-nistp384", plain: "ecdsa-sha2-nistp384", short_name: "ECDSA", is_cert: false, is_sk: false, kind: KeyTypeKind::Ecdsa, }, "ecdsa-sha2-nistp521" => KeyType { name: "ecdsa-sha2-nistp521", plain: "ecdsa-sha2-nistp521", short_name: "ECDSA", is_cert: false, is_sk: false, kind: KeyTypeKind::Ecdsa, }, "ecdsa-sha2-nistp256-cert-v01@openssh.com" => KeyType { name: "ecdsa-sha2-nistp256-cert-v01@openssh.com", plain: "ecdsa-sha2-nistp256", short_name: "ECDSA-CERT", is_cert: true, is_sk: false, kind: KeyTypeKind::EcdsaCert, }, "ecdsa-sha2-nistp384-cert-v01@openssh.com" => KeyType { name: "ecdsa-sha2-nistp384-cert-v01@openssh.com", plain: "ecdsa-sha2-nistp384", short_name: "ECDSA-CERT", is_cert: true, is_sk: false, kind: KeyTypeKind::EcdsaCert, }, "ecdsa-sha2-nistp521-cert-v01@openssh.com" => KeyType { name: "ecdsa-sha2-nistp521-cert-v01@openssh.com", plain: "ecdsa-sha2-nistp521", short_name: "ECDSA-CERT", is_cert: true, is_sk: false, kind: KeyTypeKind::EcdsaCert, }, "ssh-ed25519" => KeyType { name: "ssh-ed25519", plain: "ssh-ed25519", short_name: "ED25519", is_cert: false, is_sk: false, kind: KeyTypeKind::Ed25519, }, "ssh-ed25519-cert-v01@openssh.com" => KeyType { name: "ssh-ed25519-cert-v01@openssh.com", plain: "ssh-ed25519", short_name: "ED25519-CERT", is_cert: true, is_sk: false, kind: KeyTypeKind::Ed25519Cert, }, "sk-ecdsa-sha2-nistp256@openssh.com" => KeyType { name: "sk-ecdsa-sha2-nistp256@openssh.com", plain: "sk-ecdsa-sha2-nistp256@openssh.com", short_name: "ECDSA-SK", is_cert: false, is_sk: true, kind: KeyTypeKind::EcdsaSk, }, "sk-ssh-ed25519@openssh.com" => KeyType { name: "sk-ssh-ed25519@openssh.com", plain: "sk-ssh-ed25519@openssh.com", short_name: "ED25519-SK", is_cert: false, is_sk: true, kind: KeyTypeKind::Ed25519Sk, }, _ => { return Err(Error::with_kind(ErrorKind::UnknownKeyType( name.to_string(), ))) } }; Ok(kt) } } impl fmt::Display for KeyType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.name) } } sshkeys-0.3.2/src/lib.rs000064400000000000000000000024630072674642500132570ustar 00000000000000#![deny(warnings)] #![deny(missing_docs)] #![deny(missing_debug_implementations)] //! The `sshkeys` crate provides types and methods for parsing //! OpenSSH public keys and certificates. //! //! The following public key types are supported. //! //! - RSA //! - DSA //! - ECDSA //! - ED25519 //! //! The following OpenSSH certificate types are supported as well. //! //! - ssh-rsa-cert-v01@openssh.com //! - ssh-dss-cert-v01@openssh.com //! - ecdsa-sha2-nistp256-cert-v01@openssh.com //! - ecdsa-sha2-nistp384-cert-v01@openssh.com //! - ecdsa-sha2-nistp512-cert-v01@openssh.com //! - ssh-ed25519-cert-v01@openssh.com //! //! # Examples //! //! In order to view examples of this crate in use, please refer to the //! `examples` directory. extern crate base64; extern crate byteorder; extern crate sha2; mod cert; mod error; mod keytype; mod pubkey; mod reader; mod writer; // Serialization and deserialization support for sshkeys #[cfg(feature = "serde")] mod serde; pub use self::cert::{CertType, Certificate}; pub use self::error::{Error, Result}; pub use self::keytype::{KeyType, KeyTypeKind}; pub use self::pubkey::{ Curve, CurveKind, DsaPublicKey, EcdsaPublicKey, Ed25519PublicKey, Fingerprint, FingerprintKind, PublicKey, PublicKeyKind, RsaPublicKey, }; pub use self::reader::Reader; pub use self::writer::Writer; sshkeys-0.3.2/src/pubkey.rs000064400000000000000000000401450072674642500140070ustar 00000000000000use std::fmt; use std::fs::File; use std::io::{self, Read}; use std::path::Path; use super::error::{Error, ErrorKind, Result}; use super::keytype::{KeyType, KeyTypeKind}; use super::reader::Reader; use super::writer::Writer; use base64; use sha2::{Digest, Sha256, Sha384, Sha512}; /// A type which represents the different kinds a public key can be. #[derive(Debug, PartialEq)] pub enum PublicKeyKind { /// Represents an RSA public key. Rsa(RsaPublicKey), /// Represents a DSA public key. Dsa(DsaPublicKey), /// Represents an ECDSA public key. Ecdsa(EcdsaPublicKey), /// Represents an ED25519 public key. Ed25519(Ed25519PublicKey), } /// RSA public key. /// The format of RSA public keys is described in RFC 4253, section 6.6 #[derive(Debug, PartialEq)] pub struct RsaPublicKey { /// Exponent of key. pub e: Vec, /// Modulus of key. pub n: Vec, } /// DSA public key. /// The format of DSA public keys is described in RFC 4253, section 6.6 #[derive(Debug, PartialEq)] pub struct DsaPublicKey { /// Parameter `p`. pub p: Vec, /// Parameter `q`. pub q: Vec, /// Parameter `g`. pub g: Vec, /// Parameter `y`. pub y: Vec, } /// Represents the different kinds of supported curves. #[derive(Debug, PartialEq)] pub enum CurveKind { /// Represents a NIST P-256 curve. Nistp256, /// Represents a NIST P-384 curve. Nistp384, /// Represents a NIST P-521 curve. Nistp521, } /// A type which represents a cryptographic curve. #[derive(Debug, PartialEq)] pub struct Curve { /// The curve kind. pub kind: CurveKind, /// Curve identifier. pub identifier: &'static str, } impl Curve { /// Creates a new `Curve` from the given identifier. /// /// # Example /// ```rust /// # use sshkeys; /// let curve = sshkeys::Curve::from_identifier("nistp256").unwrap(); /// assert_eq!(curve.kind, sshkeys::CurveKind::Nistp256); /// ``` pub fn from_identifier(id: &str) -> Result { let curve = match id { "nistp256" => Curve { kind: CurveKind::Nistp256, identifier: "nistp256", }, "nistp384" => Curve { kind: CurveKind::Nistp384, identifier: "nistp384", }, "nistp521" => Curve { kind: CurveKind::Nistp521, identifier: "nistp521", }, _ => return Err(Error::with_kind(ErrorKind::UnknownCurve(id.to_string()))), }; Ok(curve) } } /// ECDSA public key. /// The format of ECDSA public keys is described in RFC 5656, section 3.1. #[derive(Debug, PartialEq)] pub struct EcdsaPublicKey { /// The curve being used. pub curve: Curve, /// The public key. pub key: Vec, /// Associated security key application, if any. pub sk_application: Option, } /// ED25519 public key. /// The format of ED25519 public keys is described in https://tools.ietf.org/html/draft-bjh21-ssh-ed25519-02 #[derive(Debug, PartialEq)] pub struct Ed25519PublicKey { /// The public key. pub key: Vec, /// Associated security key application, if any. pub sk_application: Option, } /// A type which represents an OpenSSH public key. #[derive(Debug, PartialEq)] pub struct PublicKey { /// Key type. pub key_type: KeyType, /// The kind of public key. pub kind: PublicKeyKind, /// Associated comment, if any. pub comment: Option, } impl fmt::Display for PublicKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let comment = match self.comment { Some(ref c) => c, None => "", }; write!( f, "{} {} {}", self.key_type, base64::encode(&self.encode()), comment ) } } /// The `FingerprintKind` enum represents the different fingerprint representation. #[derive(Debug, PartialEq)] pub enum FingerprintKind { /// A kind used to represent the fingerprint using SHA256. Sha256, /// A kind used to represent the fingerprint using SHA384. Sha384, /// A kind used to represent the fingerprint using SHA512. Sha512, } impl fmt::Display for FingerprintKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let kind = match *self { FingerprintKind::Sha256 => "SHA256", FingerprintKind::Sha384 => "SHA384", FingerprintKind::Sha512 => "SHA512", }; write!(f, "{}", kind) } } /// A type that represents an OpenSSH public key fingerprint. #[derive(Debug)] pub struct Fingerprint { /// The kind used to represent the fingerprint. pub kind: FingerprintKind, /// The computed fingerprint. pub hash: String, } impl fmt::Display for Fingerprint { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}:{}", self.kind, self.hash) } } impl Fingerprint { /// Computes the fingerprint of a byte sequence using a given fingerprint representation. /// /// This method computes a fingerprint the way OpenSSH does it and is generally being /// used to compute the fingerprint of an already encoded OpenSSH public key. /// /// # Example /// ```rust /// # use sshkeys; /// let fp = sshkeys::Fingerprint::compute(sshkeys::FingerprintKind::Sha256, "some data".as_bytes()); /// assert_eq!(fp.kind, sshkeys::FingerprintKind::Sha256); /// assert_eq!(fp.hash, "EweZDmulyhRes16ZGCqb7EZTG8VN32VqYCx4D6AkDe4"); /// ``` pub fn compute>(kind: FingerprintKind, data: &T) -> Fingerprint { let digest = match kind { FingerprintKind::Sha256 => Sha256::digest(&data.as_ref()).to_vec(), FingerprintKind::Sha384 => Sha384::digest(&data.as_ref()).to_vec(), FingerprintKind::Sha512 => Sha512::digest(&data.as_ref()).to_vec(), }; let mut encoded = base64::encode(&digest); // Trim padding characters from end let hash = match encoded.find('=') { Some(offset) => encoded.drain(..offset).collect(), None => encoded, }; let fp = Fingerprint { kind: kind, hash: hash, }; fp } } impl PublicKey { /// Reads an OpenSSH public key from a given path. /// /// # Examples /// /// ```rust /// # fn example() -> sshkeys::Result<()> { /// let key = sshkeys::PublicKey::from_path("/path/to/id_ed25519.pub")?; /// # Ok(()) /// # } /// ``` pub fn from_path>(path: P) -> Result { let mut contents = String::new(); File::open(path)?.read_to_string(&mut contents)?; PublicKey::from_string(&contents) } /// Reads an OpenSSH public key from a given string. /// /// # Examples /// /// ```rust /// # use sshkeys; /// let key = sshkeys::PublicKey::from_string("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHkbe7gwx7s0dlApEEzpUyOAPrzPLy4czEZw/sh8m8rd me@home").unwrap(); /// let fp = key.fingerprint(); /// assert_eq!(fp.hash, "ciQkdxjFUhk2E2vRkWJD9kB8pi+EneOkaCJJHNWzPC4"); /// ``` pub fn from_string(contents: &str) -> Result { let mut iter = contents.split_whitespace(); let kt_name = iter .next() .ok_or(Error::with_kind(ErrorKind::InvalidFormat))?; let data = iter .next() .ok_or(Error::with_kind(ErrorKind::InvalidFormat))?; let comment = iter.next().map(|v| String::from(v)); let kt = KeyType::from_name(&kt_name)?; let decoded = base64::decode(&data)?; let mut reader = Reader::new(&decoded); // Validate key type before reading rest of the data let kt_from_reader = reader.read_string()?; if kt_name != kt_from_reader { return Err(Error::with_kind(ErrorKind::KeyTypeMismatch)); } // Construct a new `PublicKey` value and preserve the `comment` value. let k = PublicKey::from_reader(&kt_name, &mut reader)?; let key = PublicKey { key_type: kt, kind: k.kind, comment: comment, }; Ok(key) } /// Reads a public key from a given byte sequence. /// /// The byte sequence is expected to be the base64 decoded body of the public key. /// /// # Example /// /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 11, 115, 115, 104, 45, /// 101, 100, 50, 53, 53, 49, 57, /// 0, 0, 0, 32, 121, 27, 123, 184, /// 48, 199, 187, 52, 118, 80, 41, 16, /// 76, 233, 83, 35, 128, 62, 188, /// 207, 47, 46, 28, 204, 70, 112, /// 254, 200, 124, 155, 202, 221]; /// /// let key = sshkeys::PublicKey::from_bytes(&data).unwrap(); /// let fp = key.fingerprint(); /// assert_eq!(fp.hash, "ciQkdxjFUhk2E2vRkWJD9kB8pi+EneOkaCJJHNWzPC4"); /// ``` pub fn from_bytes>(data: &T) -> Result { let mut reader = Reader::new(&data); let kt_name = reader.read_string()?; PublicKey::from_reader(&kt_name, &mut reader) } // This function is used for extracting a public key from an existing reader, e.g. // we already have a reader for reading an OpenSSH certificate key and // we want to extract the public key information from it. pub(crate) fn from_reader(kt_name: &str, reader: &mut Reader) -> Result { let kt = KeyType::from_name(&kt_name)?; let kind = match kt.kind { KeyTypeKind::Rsa | KeyTypeKind::RsaCert => { let k = RsaPublicKey { e: reader.read_mpint()?, n: reader.read_mpint()?, }; PublicKeyKind::Rsa(k) } KeyTypeKind::Dsa | KeyTypeKind::DsaCert => { let k = DsaPublicKey { p: reader.read_mpint()?, q: reader.read_mpint()?, g: reader.read_mpint()?, y: reader.read_mpint()?, }; PublicKeyKind::Dsa(k) } KeyTypeKind::Ecdsa | KeyTypeKind::EcdsaCert | KeyTypeKind::EcdsaSk => { let identifier = reader.read_string()?; let curve = Curve::from_identifier(&identifier)?; let key = reader.read_bytes()?; let sk_application = match kt.kind { KeyTypeKind::EcdsaSk => Some(reader.read_string()?), _ => None, }; let k = EcdsaPublicKey { curve: curve, key: key, sk_application: sk_application, }; PublicKeyKind::Ecdsa(k) } KeyTypeKind::Ed25519 | KeyTypeKind::Ed25519Cert | KeyTypeKind::Ed25519Sk => { let key = reader.read_bytes()?; let sk_application = match kt.kind { KeyTypeKind::Ed25519Sk => Some(reader.read_string()?), _ => None, }; let k = Ed25519PublicKey { key: key, sk_application: sk_application, }; PublicKeyKind::Ed25519(k) } }; let key = PublicKey { key_type: kt, kind: kind, comment: None, }; Ok(key) } /// Returns the number of bits of the public key. /// /// # Example /// /// ```rust /// # use sshkeys; /// let key = sshkeys::PublicKey::from_string("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHkbe7gwx7s0dlApEEzpUyOAPrzPLy4czEZw/sh8m8rd me@home").unwrap(); /// assert_eq!(key.bits(), 256); /// ``` pub fn bits(&self) -> usize { match self.kind { // For RSA public key the size of the key is the number of bits of the modulus PublicKeyKind::Rsa(ref k) => k.n.len() * 8, // For DSA public keys the size of the key is the number of bits of the `p` parameter PublicKeyKind::Dsa(ref k) => k.p.len() * 8, // ECDSA key size depends on the curve PublicKeyKind::Ecdsa(ref k) => match k.curve.kind { CurveKind::Nistp256 => 256, CurveKind::Nistp384 => 384, CurveKind::Nistp521 => 521, }, // ED25519 key size is 256 bits // https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.5 PublicKeyKind::Ed25519(_) => 256, } } /// Encodes the public key in an OpenSSH compatible format. /// /// # Example /// ```rust /// # use sshkeys; /// let key = sshkeys::PublicKey::from_string("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHkbe7gwx7s0dlApEEzpUyOAPrzPLy4czEZw/sh8m8rd me@home").unwrap(); /// assert_eq!(key.encode(), vec![0, 0, 0, 11, 115, 115, 104, 45, 101, 100, 50, 53, 53, 49, 57, 0, 0, 0, 32, 121, 27, 123, 184, 48, 199, 187, 52, 118, 80, 41, 16, 76, 233, 83, 35, 128, 62, 188, 207, 47, 46, 28, 204, 70, 112, 254, 200, 124, 155, 202, 221]); /// ``` pub fn encode(&self) -> Vec { let mut w = Writer::new(); w.write_string(self.key_type.plain); match self.kind { PublicKeyKind::Rsa(ref k) => { w.write_mpint(&k.e); w.write_mpint(&k.n); } PublicKeyKind::Dsa(ref k) => { w.write_mpint(&k.p); w.write_mpint(&k.q); w.write_mpint(&k.g); w.write_mpint(&k.y); } PublicKeyKind::Ecdsa(ref k) => { w.write_string(&k.curve.identifier); w.write_bytes(&k.key); if self.key_type.kind == KeyTypeKind::EcdsaSk { w.write_string(&k.sk_application.as_ref().unwrap()); } } PublicKeyKind::Ed25519(ref k) => { w.write_bytes(&k.key); if self.key_type.kind == KeyTypeKind::Ed25519Sk { w.write_string(&k.sk_application.as_ref().unwrap()); } } } w.into_bytes() } /// Computes the fingerprint of the public key using the /// default OpenSSH fingerprint representation with SHA256. /// /// # Example /// /// ```rust /// # use sshkeys; /// # fn example() -> sshkeys::Result<()> { /// let key = sshkeys::PublicKey::from_path("/path/to/id_ed25519.pub")?; /// let fp = key.fingerprint(); /// println!("{}", fp.hash); /// # Ok(()) /// # } /// ``` pub fn fingerprint(&self) -> Fingerprint { self.fingerprint_with(FingerprintKind::Sha256) } /// Computes the fingerprint of the public key using a given /// fingerprint representation. /// /// # Example /// /// ```rust /// # use sshkeys; /// # fn example() -> sshkeys::Result<()> { /// let key = sshkeys::PublicKey::from_path("/path/to/id_ed25519.pub").unwrap(); /// let sha512fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha512); /// println!("{}", sha512fp.hash); /// # Ok(()) /// # } /// ``` pub fn fingerprint_with(&self, kind: FingerprintKind) -> Fingerprint { Fingerprint::compute(kind, &self.encode()) } /// Writes the public key to a given writer. /// /// # Example /// ```rust /// # use sshkeys; /// use std::fs::File; /// # fn example() -> sshkeys::Result<()> { /// let key = sshkeys::PublicKey::from_string("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...")?; /// let mut file = File::create("/path/to/id_ed25519.pub")?; /// key.write(&mut file).unwrap(); /// # Ok(()) /// # } /// ``` pub fn write(&self, w: &mut W) -> io::Result<()> { let encoded = self.encode(); let data = base64::encode(&encoded); match self.comment { Some(ref c) => w.write_fmt(format_args!("{} {} {}\n", self.key_type.name, data, c)), None => w.write_fmt(format_args!("{} {}\n", self.key_type.name, data)), } } } sshkeys-0.3.2/src/reader.rs000064400000000000000000000123150072674642500137500ustar 00000000000000use super::error::{Error, ErrorKind, Result}; use byteorder::{BigEndian, ByteOrder}; /// A `Reader` is used for reading from a byte sequence /// representing an encoded OpenSSH public key or certificate. #[derive(Debug)] pub struct Reader<'a> { inner: &'a [u8], offset: usize, } impl<'a> Reader<'a> { /// Creates a new `Reader` instance from the given byte sequence. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 42]; /// let mut reader = sshkeys::Reader::new(&data); /// let num = reader.read_u32().unwrap(); /// assert_eq!(num, 42); /// ``` pub fn new>(inner: &T) -> Reader { Reader { inner: inner.as_ref(), offset: 0, } } /// Sets the `Reader` current offset to a given position. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 42]; /// let mut reader = sshkeys::Reader::new(&data); /// let num = reader.read_u32().unwrap(); /// assert_eq!(num, 42); /// reader.set_offset(0); /// let num_42_again = reader.read_u32().unwrap(); /// assert_eq!(num_42_again, 42); /// ``` pub fn set_offset(&mut self, offset: usize) -> Result<()> { self.offset = offset; Ok(()) } /// Reads a byte buffer from the wrapped byte sequence and /// returns it as a `Vec`. /// The buffer is represented by it's length as `u32` value /// followed by the actual bytes to read. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 13, 97, 32, 116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 103]; /// let mut reader = sshkeys::Reader::new(&data); /// let bytes = reader.read_bytes().unwrap(); /// assert_eq!(bytes, [97, 32, 116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 103]); /// ``` pub fn read_bytes(&mut self) -> Result> { if self.offset >= self.inner.len() { return Err(Error::with_kind(ErrorKind::UnexpectedEof)); } let slice = &self.inner[self.offset..]; if slice.len() < 4 { return Err(Error::with_kind(ErrorKind::InvalidFormat)); } let size = BigEndian::read_u32(&slice[..4]) as usize; if slice.len() < size + 4 { return Err(Error::with_kind(ErrorKind::InvalidFormat)); } self.offset += size + 4; let result = slice[4..size + 4].to_vec(); Ok(result) } /// Reads an `mpint` value from the wrapped byte sequence. /// /// Drops the leading byte if it's value is zero according to the RFC 4251, section 5. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 3, 1, 0, 1]; /// let mut reader = sshkeys::Reader::new(&data); /// let mpint = reader.read_mpint().unwrap(); /// assert_eq!(mpint, [1, 0, 1]); /// ``` pub fn read_mpint(&mut self) -> Result> { let bytes = self.read_bytes()?; if bytes[0] == 0 { return Ok(bytes[1..].to_vec()); } Ok(bytes) } /// Reads a `string` value from the wrapped byte sequence and /// returns it as a `String`. The value that we read should be a valid UTF-8. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 13, 97, 32, 116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 103]; /// let mut reader = sshkeys::Reader::new(&data); /// let result = reader.read_string().unwrap(); /// assert_eq!(result, "a test string"); /// ``` pub fn read_string(&mut self) -> Result { let bytes = self.read_bytes()?; let result = String::from_utf8(bytes)?; Ok(result) } /// Reads an `u32` value from the wrapped byte sequence and returns it. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 42]; /// let mut reader = sshkeys::Reader::new(&data); /// let num = reader.read_u32().unwrap(); /// assert_eq!(num, 42); /// ``` pub fn read_u32(&mut self) -> Result { if self.offset >= self.inner.len() { return Err(Error::with_kind(ErrorKind::UnexpectedEof)); } let slice = &self.inner[self.offset..]; if slice.len() < 4 { return Err(Error::with_kind(ErrorKind::InvalidFormat)); } self.offset += 4; let value = BigEndian::read_u32(&slice[..4]); Ok(value) } /// Reads an `u64` value from the wrapped byte sequence and returns it. /// /// # Example /// ```rust /// # use sshkeys; /// let data = vec![0, 0, 0, 0, 0, 0, 0, 42]; /// let mut reader = sshkeys::Reader::new(&data); /// let num = reader.read_u64().unwrap(); /// assert_eq!(num, 42); /// ``` pub fn read_u64(&mut self) -> Result { if self.offset >= self.inner.len() { return Err(Error::with_kind(ErrorKind::UnexpectedEof)); } let slice = &self.inner[self.offset..]; if slice.len() < 8 { return Err(Error::with_kind(ErrorKind::InvalidFormat)); } self.offset += 8; let value = BigEndian::read_u64(&slice[..8]); Ok(value) } } sshkeys-0.3.2/src/serde.rs000064400000000000000000000016710072674642500136130ustar 00000000000000extern crate serde; use self::serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use super::pubkey::PublicKey; use std::fmt; impl Serialize for PublicKey { fn serialize(&self, serializer: S) -> Result { serializer.serialize_str(&self.to_string()) } } impl<'de> Deserialize<'de> for PublicKey { fn deserialize>(deserializer: D) -> Result { struct Visitor; impl<'de> de::Visitor<'de> for Visitor { type Value = PublicKey; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a valid public key") } fn visit_str(self, value: &str) -> Result { PublicKey::from_string(value).map_err(|e| E::custom(e.to_string())) } } deserializer.deserialize_str(Visitor) } } sshkeys-0.3.2/src/writer.rs000064400000000000000000000055330072674642500140260ustar 00000000000000use byteorder::{BigEndian, ByteOrder}; /// A `Writer` is used for encoding a key in OpenSSH compatible format. #[derive(Debug)] pub struct Writer { inner: Vec, } impl Writer { /// Creates a new `Writer` instance. /// /// # Example /// ```rust /// let writer = sshkeys::Writer::new(); /// ``` pub fn new() -> Writer { Writer { inner: Vec::new() } } /// Writes a byte sequence to the underlying vector. /// The value is represented as a the byte sequence length, /// followed by the actual byte sequence. /// /// # Example /// ```rust /// # use sshkeys; /// let mut writer = sshkeys::Writer::new(); /// writer.write_bytes(&[0, 0, 0, 42]); /// let bytes = writer.into_bytes(); /// assert_eq!(bytes, vec![0, 0, 0, 4, 0, 0, 0, 42]); /// ``` pub fn write_bytes(&mut self, val: &[u8]) { let size = val.len() as u32; let mut buf = vec![0; 4]; BigEndian::write_u32(&mut buf, size); self.inner.append(&mut buf); self.inner.extend_from_slice(&val); } /// Writes a `string` value to the underlying byte sequence. /// /// # Example /// ```rust /// # use sshkeys; /// let mut writer = sshkeys::Writer::new(); /// writer.write_string("a test string"); /// let bytes = writer.into_bytes(); /// assert_eq!(bytes, [0, 0, 0, 13, 97, 32, 116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 103]); /// ``` pub fn write_string(&mut self, val: &str) { self.write_bytes(val.as_bytes()); } /// Writes an `mpint` value to the underlying byte sequence. /// If the MSB bit of the first byte is set then the number is /// negative, otherwise it is positive. /// Positive numbers must be preceeded by a leading zero byte according to RFC 4251, section 5. /// /// # Example /// ```rust /// # use sshkeys; /// let mut writer = sshkeys::Writer::new(); /// writer.write_mpint(&[1, 0, 1]); /// let bytes = writer.into_bytes(); /// assert_eq!(bytes, [0, 0, 0, 3, 1, 0, 1]); /// ``` pub fn write_mpint(&mut self, val: &[u8]) { let mut bytes = val.to_vec(); // If most significant bit is set then prepend a zero byte to // avoid interpretation as a negative number. if val.get(0).unwrap_or(&0) & 0x80 != 0 { bytes.insert(0, 0); } self.write_bytes(&bytes); } /// Converts the `Writer` into a byte sequence. /// This consumes the underlying byte sequence used by the `Writer`. /// /// # Example /// ```rust /// let mut writer = sshkeys::Writer::new(); /// writer.write_string("some data"); /// let bytes = writer.into_bytes(); /// assert_eq!(bytes, [0, 0, 0, 9, 115, 111, 109, 101, 32, 100, 97, 116, 97]); /// ``` pub fn into_bytes(self) -> Vec { self.inner } } sshkeys-0.3.2/tests/keys.rs000064400000000000000000001054710072674642500140420ustar 00000000000000use std::collections::HashMap; extern crate sshkeys; #[test] fn test_rsa_pubkey_1024() { let key = sshkeys::PublicKey::from_path("tests/test-keys/id_rsa_1024.pub").unwrap(); assert_eq!(key.key_type.name, "ssh-rsa"); assert_eq!(key.key_type.plain, "ssh-rsa"); assert_eq!(key.key_type.short_name, "RSA"); assert_eq!(key.key_type.is_cert, false); assert_eq!(key.key_type.is_sk, false); assert_eq!(key.key_type.kind, sshkeys::KeyTypeKind::Rsa); assert_eq!(key.bits(), 1024); assert_eq!(key.comment, None); match key.kind { sshkeys::PublicKeyKind::Rsa(_) => {} _ => panic!("Expected RSA public key"), } let sha256fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "izTlwvAwZNoPhsSHPFvSWBx7mAnX0regyVjXfQTMv6Y"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "dBi3NL7zSWb1zsQob8ROuRggCtkr6n60VbIy+Io4iYil4UIieUvcco03TWpjdv/u" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "0GhrWC58WCwoXXE5mfmKBeLdEjwH2Xzg1Z3K7n5mBtLmcTu+OeIOw9bJJ2FPuskz57Bu2dJvOFkGidw2RW4fvg" ); } #[test] fn test_rsa_pubkey_2048() { let key = sshkeys::PublicKey::from_path("tests/test-keys/id_rsa_2048.pub").unwrap(); assert_eq!(key.key_type.name, "ssh-rsa"); assert_eq!(key.key_type.plain, "ssh-rsa"); assert_eq!(key.key_type.short_name, "RSA"); assert_eq!(key.key_type.is_cert, false); assert_eq!(key.key_type.is_sk, false); assert_eq!(key.key_type.kind, sshkeys::KeyTypeKind::Rsa); assert_eq!(key.bits(), 2048); assert_eq!(key.comment, Some("me@home".to_string())); match key.kind { sshkeys::PublicKeyKind::Rsa(_) => {} _ => panic!("Expected RSA public key"), }; let sha256fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "5mDozobgKuNO6/FutOgATBvGfYQbNfBlUY6iBYSdqF0"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "dgNFIE9GNNznHqdnL7Ml1CScn5X/5NAT2tpSqd6NWGhXPU3o1rz3SMKyELzuuArv" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "FDoxtx0ir1FlZUkHjUugzNZE7Qi3lJaUkN9QabPulm6/MXAcXXIhsW5C/mJaCDY1hDbeoo39aqHcTO+MdQiJsQ" ); } #[test] #[should_panic(expected = "Invalid format")] fn test_rsa_pubkey_2048_invalid_format() { match sshkeys::PublicKey::from_path("tests/test-keys/id_rsa_2048_invalid_format.pub") { Ok(v) => panic!("Expected invalid format, got {:?}", v), Err(e) => panic!("{}", e.to_string()), } } #[test] #[should_panic(expected = "Unknown key type")] fn test_rsa_pubkey_2048_unknown_keytype() { match sshkeys::PublicKey::from_path("tests/test-keys/id_rsa_2048_unknown_keytype.pub") { Ok(v) => panic!("Expected unknown key type, got {:?}", v), Err(e) => panic!("{}", e.to_string()), } } #[test] fn test_rsa_user_cert() { let cert = sshkeys::Certificate::from_path("tests/test-keys/id_rsa_2048-cert.pub").unwrap(); assert_eq!(cert.key_type.name, "ssh-rsa-cert-v01@openssh.com"); assert_eq!(cert.key_type.plain, "ssh-rsa"); assert_eq!(cert.key_type.short_name, "RSA-CERT"); assert_eq!(cert.key_type.is_cert, true); assert_eq!(cert.key_type.is_sk, false); assert_eq!(cert.key_type.kind, sshkeys::KeyTypeKind::RsaCert); // Public key part of the certificate assert_eq!(cert.key.key_type.name, "ssh-rsa-cert-v01@openssh.com"); assert_eq!(cert.key.key_type.plain, "ssh-rsa"); assert_eq!(cert.key.key_type.short_name, "RSA-CERT"); assert_eq!(cert.key.key_type.is_cert, true); assert_eq!(cert.key.key_type.is_sk, false); assert_eq!(cert.key.key_type.kind, sshkeys::KeyTypeKind::RsaCert); assert_eq!(cert.key.bits(), 2048); assert_eq!(cert.key.comment, None); // Fingerprints of public key let sha256fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "5mDozobgKuNO6/FutOgATBvGfYQbNfBlUY6iBYSdqF0"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "dgNFIE9GNNznHqdnL7Ml1CScn5X/5NAT2tpSqd6NWGhXPU3o1rz3SMKyELzuuArv" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "FDoxtx0ir1FlZUkHjUugzNZE7Qi3lJaUkN9QabPulm6/MXAcXXIhsW5C/mJaCDY1hDbeoo39aqHcTO+MdQiJsQ" ); assert_eq!(cert.serial, 0); assert_eq!(cert.cert_type, sshkeys::CertType::User); assert_eq!(cert.key_id, "john.doe"); assert_eq!(cert.valid_principals, vec!["root"]); assert_eq!(cert.valid_after, 1505374860); assert_eq!(cert.valid_before, 1536824561); let mut co = HashMap::new(); co.insert("force-command".to_string(), "/usr/bin/true".to_string()); co.insert("source-address".to_string(), "127.0.0.1".to_string()); assert_eq!(cert.critical_options, co); let mut extensions = HashMap::new(); extensions.insert("permit-X11-forwarding".to_string(), "".to_string()); extensions.insert("permit-agent-forwarding".to_string(), "".to_string()); extensions.insert("permit-port-forwarding".to_string(), "".to_string()); extensions.insert("permit-pty".to_string(), "".to_string()); extensions.insert("permit-user-rc".to_string(), "".to_string()); assert_eq!(cert.extensions, extensions); // The `reserved` field is empty in the current implementation of OpenSSH certificates assert_eq!(cert.reserved, Vec::new()); // CA public key assert_eq!(cert.signature_key.key_type.name, "ssh-rsa"); assert_eq!(cert.signature_key.key_type.plain, "ssh-rsa"); assert_eq!(cert.signature_key.key_type.short_name, "RSA"); assert_eq!(cert.signature_key.key_type.is_cert, false); assert_eq!(cert.signature_key.key_type.is_sk, false); assert_eq!(cert.signature_key.key_type.kind, sshkeys::KeyTypeKind::Rsa); assert_eq!(cert.signature_key.bits(), 2048); assert_eq!(cert.signature_key.comment, None); // CA public key fingerprints let sha256fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "8bEmsdiV2BXhjrzPhp8dPrSLUK3U/YpIXT8NIw6Ym+s"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "7+2ZLPaqbntHUtypie8404NhIIqgo9b6/XWNABjgTphWic38/EDYXYm35SLllIxm" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "BrQgwbsBLlnyiOGITMfl+H2I7HCcCYiy22Hx0j62bWvifyZLyGA5PIoId+846U1P31cMX77l9Ok0qh9meltGCw" ); assert_eq!(cert.comment, Some("me@home".to_string())); } #[test] #[should_panic(expected = "Not a certificate")] fn test_rsa_not_cert() { match sshkeys::Certificate::from_path("tests/test-keys/id_rsa_2048.pub") { Ok(v) => panic!("Expected public key, got certificate {:?}", v), Err(e) => panic!("{}", e.to_string()), } } #[test] fn test_dsa_pubkey_1024() { let key = sshkeys::PublicKey::from_path("tests/test-keys/id_dsa_1024.pub").unwrap(); assert_eq!(key.key_type.name, "ssh-dss"); assert_eq!(key.key_type.plain, "ssh-dss"); assert_eq!(key.key_type.short_name, "DSA"); assert_eq!(key.key_type.is_cert, false); assert_eq!(key.key_type.is_sk, false); assert_eq!(key.key_type.kind, sshkeys::KeyTypeKind::Dsa); assert_eq!(key.bits(), 1024); assert_eq!(key.comment, Some("me@home".to_string())); match key.kind { sshkeys::PublicKeyKind::Dsa(_) => {} _ => panic!("Expected DSA public key"), } let sha256fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "i+5TCv/r9PXHeJMeGbgH8xfpgbGsTFFKapQudFR2aFQ"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "m55cGSOiyn+U2mJX7sLOK/hcwDQmh16YhC5/ibhc2tnn8OOin4sXgpBRY6ZLXL/j" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "nNCtXgIQx+DZTUQPDVEVIl5SObBlD4MiJzBiFUsuNGPnjoF22kQeQkGYCioWfGQBrUR33p9/1jXLHfpHETuYSw" ); } #[test] fn test_dsa_user_cert() { let cert = sshkeys::Certificate::from_path("tests/test-keys/id_dsa_1024-cert.pub").unwrap(); assert_eq!(cert.key_type.name, "ssh-dss-cert-v01@openssh.com"); assert_eq!(cert.key_type.plain, "ssh-dss"); assert_eq!(cert.key_type.short_name, "DSA-CERT"); assert_eq!(cert.key_type.is_cert, true); assert_eq!(cert.key_type.is_sk, false); assert_eq!(cert.key_type.kind, sshkeys::KeyTypeKind::DsaCert); // Public key part of the certificate assert_eq!(cert.key.key_type.name, "ssh-dss-cert-v01@openssh.com"); assert_eq!(cert.key.key_type.plain, "ssh-dss"); assert_eq!(cert.key.key_type.short_name, "DSA-CERT"); assert_eq!(cert.key.key_type.is_cert, true); assert_eq!(cert.key.key_type.is_sk, false); assert_eq!(cert.key.key_type.kind, sshkeys::KeyTypeKind::DsaCert); assert_eq!(cert.key.bits(), 1024); assert_eq!(cert.key.comment, None); let sha256fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "i+5TCv/r9PXHeJMeGbgH8xfpgbGsTFFKapQudFR2aFQ"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "m55cGSOiyn+U2mJX7sLOK/hcwDQmh16YhC5/ibhc2tnn8OOin4sXgpBRY6ZLXL/j" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "nNCtXgIQx+DZTUQPDVEVIl5SObBlD4MiJzBiFUsuNGPnjoF22kQeQkGYCioWfGQBrUR33p9/1jXLHfpHETuYSw" ); assert_eq!(cert.serial, 0); assert_eq!(cert.cert_type, sshkeys::CertType::User); assert_eq!(cert.key_id, "john.doe"); assert_eq!(cert.valid_principals, vec!["root"]); assert_eq!(cert.valid_after, 1505475180); assert_eq!(cert.valid_before, 1536924895); let mut co = HashMap::new(); co.insert("force-command".to_string(), "/usr/bin/true".to_string()); co.insert("source-address".to_string(), "127.0.0.1".to_string()); assert_eq!(cert.critical_options, co); let mut extensions = HashMap::new(); extensions.insert("permit-X11-forwarding".to_string(), "".to_string()); extensions.insert("permit-agent-forwarding".to_string(), "".to_string()); extensions.insert("permit-port-forwarding".to_string(), "".to_string()); extensions.insert("permit-pty".to_string(), "".to_string()); extensions.insert("permit-user-rc".to_string(), "".to_string()); assert_eq!(cert.extensions, extensions); // The `reserved` field is empty in the current implementation of OpenSSH certificates assert_eq!(cert.reserved, Vec::new()); // CA public key assert_eq!(cert.signature_key.key_type.name, "ssh-rsa"); assert_eq!(cert.signature_key.key_type.plain, "ssh-rsa"); assert_eq!(cert.signature_key.key_type.short_name, "RSA"); assert_eq!(cert.signature_key.key_type.is_cert, false); assert_eq!(cert.signature_key.key_type.is_sk, false); assert_eq!(cert.signature_key.key_type.kind, sshkeys::KeyTypeKind::Rsa); assert_eq!(cert.signature_key.bits(), 2048); assert_eq!(cert.signature_key.comment, None); // CA public key fingerprints let sha256fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "8bEmsdiV2BXhjrzPhp8dPrSLUK3U/YpIXT8NIw6Ym+s"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "7+2ZLPaqbntHUtypie8404NhIIqgo9b6/XWNABjgTphWic38/EDYXYm35SLllIxm" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "BrQgwbsBLlnyiOGITMfl+H2I7HCcCYiy22Hx0j62bWvifyZLyGA5PIoId+846U1P31cMX77l9Ok0qh9meltGCw" ); assert_eq!(cert.comment, Some("me@home".to_string())); } #[test] pub fn test_ecdsa_nistp256_pubkey() { let key = sshkeys::PublicKey::from_path("tests/test-keys/id_ecdsa_256.pub").unwrap(); assert_eq!(key.key_type.name, "ecdsa-sha2-nistp256"); assert_eq!(key.key_type.plain, "ecdsa-sha2-nistp256"); assert_eq!(key.key_type.short_name, "ECDSA"); assert_eq!(key.key_type.is_cert, false); assert_eq!(key.key_type.is_sk, false); assert_eq!(key.key_type.kind, sshkeys::KeyTypeKind::Ecdsa); assert_eq!(key.bits(), 256); assert_eq!(key.comment, Some("me@home".to_string())); let sha256fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "RiRAmX+9kOD9dgFhocPtQi726sZXbQ2RmrkXevu6Avg"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "fM0Czmf55Od4g4zbLZueLFnbwFr0DmJQytpB7Xb2kjG6diar/7CskhVUkfX43fh6" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "8qXVmeSbYWN6D79reref2iz+tadg68qpkJDG0Z6B6u4U7XK0C3vYrDQVHg38FUKxvzAkw0c2gOYXqhP1RYo+Fw" ); let ecdsa = match key.kind { sshkeys::PublicKeyKind::Ecdsa(ref k) => k, _ => panic!("Expected ECDSA public key"), }; assert_eq!(ecdsa.curve.identifier, "nistp256"); assert_eq!(ecdsa.curve.kind, sshkeys::CurveKind::Nistp256); } #[test] pub fn test_ecdsa_nistp384_pubkey() { let key = sshkeys::PublicKey::from_path("tests/test-keys/id_ecdsa_384.pub").unwrap(); assert_eq!(key.key_type.name, "ecdsa-sha2-nistp384"); assert_eq!(key.key_type.plain, "ecdsa-sha2-nistp384"); assert_eq!(key.key_type.short_name, "ECDSA"); assert_eq!(key.key_type.is_cert, false); assert_eq!(key.key_type.is_sk, false); assert_eq!(key.key_type.kind, sshkeys::KeyTypeKind::Ecdsa); assert_eq!(key.bits(), 384); assert_eq!(key.comment, Some("me@home".to_string())); let sha256fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "XyWmNHs59uQcNJBv6Iq6sbDAa5/u2GD1Nyu2YHcS2jQ"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "YXnQ8c1kDAQirgRgHSwswvT6zOFmvbvwL8au771Ska7+arFQgMe5Se9LPXeKmIWR" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "p73av0cbNsWXLexTQNpUxjGE4k+on8IrwsmIJP7xUhf7s1irVTBCpLA0wJ44IbMzUvMLuIj/FtoV1nTilYpb3w" ); let ecdsa = match key.kind { sshkeys::PublicKeyKind::Ecdsa(ref k) => k, _ => panic!("Expected ECDSA public key"), }; assert_eq!(ecdsa.curve.identifier, "nistp384"); assert_eq!(ecdsa.curve.kind, sshkeys::CurveKind::Nistp384); } #[test] pub fn test_ecdsa_nistp521_pubkey() { let key = sshkeys::PublicKey::from_path("tests/test-keys/id_ecdsa_521.pub").unwrap(); assert_eq!(key.key_type.name, "ecdsa-sha2-nistp521"); assert_eq!(key.key_type.plain, "ecdsa-sha2-nistp521"); assert_eq!(key.key_type.short_name, "ECDSA"); assert_eq!(key.key_type.is_cert, false); assert_eq!(key.key_type.is_sk, false); assert_eq!(key.key_type.kind, sshkeys::KeyTypeKind::Ecdsa); assert_eq!(key.bits(), 521); assert_eq!(key.comment, Some("me@home".to_string())); let sha256fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "kEdMLsbAeJPDv3mEwIchjSxkcL/+XFzI9u1NHCWbsT8"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "ZD2U1VncXLttbPAEMtUX/rCl4JtgxI1XJOYPXeP7EzzBeXr3KVVb4Wn/u/Qp4i0Q" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "4EI3hnZ0KhIa0Sp8Z1CWWL8I0t8DaSs4+E8jiLFRAZ+EUeFYPysy6SrCbMDgSk5sfo3+2UA5SVqnZtBdmVQeIg" ); let ecdsa = match key.kind { sshkeys::PublicKeyKind::Ecdsa(ref k) => k, _ => panic!("Expected ECDSA public key"), }; assert_eq!(ecdsa.curve.identifier, "nistp521"); assert_eq!(ecdsa.curve.kind, sshkeys::CurveKind::Nistp521); } #[test] fn test_ecdsa_user_cert() { let cert = sshkeys::Certificate::from_path("tests/test-keys/id_ecdsa_521-cert.pub").unwrap(); assert_eq!( cert.key_type.name, "ecdsa-sha2-nistp521-cert-v01@openssh.com" ); assert_eq!(cert.key_type.plain, "ecdsa-sha2-nistp521"); assert_eq!(cert.key_type.short_name, "ECDSA-CERT"); assert_eq!(cert.key_type.is_cert, true); assert_eq!(cert.key_type.is_sk, false); assert_eq!(cert.key_type.kind, sshkeys::KeyTypeKind::EcdsaCert); // Public key part of the certificate assert_eq!( cert.key.key_type.name, "ecdsa-sha2-nistp521-cert-v01@openssh.com" ); assert_eq!(cert.key.key_type.plain, "ecdsa-sha2-nistp521"); assert_eq!(cert.key.key_type.short_name, "ECDSA-CERT"); assert_eq!(cert.key.key_type.is_cert, true); assert_eq!(cert.key.key_type.is_sk, false); assert_eq!(cert.key.key_type.kind, sshkeys::KeyTypeKind::EcdsaCert); assert_eq!(cert.key.bits(), 521); assert_eq!(cert.key.comment, None); let sha256fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "kEdMLsbAeJPDv3mEwIchjSxkcL/+XFzI9u1NHCWbsT8"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "ZD2U1VncXLttbPAEMtUX/rCl4JtgxI1XJOYPXeP7EzzBeXr3KVVb4Wn/u/Qp4i0Q" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "4EI3hnZ0KhIa0Sp8Z1CWWL8I0t8DaSs4+E8jiLFRAZ+EUeFYPysy6SrCbMDgSk5sfo3+2UA5SVqnZtBdmVQeIg" ); assert_eq!(cert.serial, 0); assert_eq!(cert.cert_type, sshkeys::CertType::User); assert_eq!(cert.key_id, "john.doe"); assert_eq!(cert.valid_principals, vec!["root"]); assert_eq!(cert.valid_after, 1506340920); assert_eq!(cert.valid_before, 1537790635); let mut co = HashMap::new(); co.insert("source-address".to_string(), "127.0.0.1".to_string()); assert_eq!(cert.critical_options, co); let mut extensions = HashMap::new(); extensions.insert("permit-X11-forwarding".to_string(), "".to_string()); extensions.insert("permit-agent-forwarding".to_string(), "".to_string()); extensions.insert("permit-port-forwarding".to_string(), "".to_string()); extensions.insert("permit-pty".to_string(), "".to_string()); extensions.insert("permit-user-rc".to_string(), "".to_string()); assert_eq!(cert.extensions, extensions); // The `reserved` field is empty in the current implementation of OpenSSH certificates assert_eq!(cert.reserved, Vec::new()); // CA public key assert_eq!(cert.signature_key.key_type.name, "ssh-rsa"); assert_eq!(cert.signature_key.key_type.plain, "ssh-rsa"); assert_eq!(cert.signature_key.key_type.short_name, "RSA"); assert_eq!(cert.signature_key.key_type.is_cert, false); assert_eq!(cert.signature_key.key_type.is_sk, false); assert_eq!(cert.signature_key.key_type.kind, sshkeys::KeyTypeKind::Rsa); assert_eq!(cert.signature_key.bits(), 2048); assert_eq!(cert.signature_key.comment, None); let sha256fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "8bEmsdiV2BXhjrzPhp8dPrSLUK3U/YpIXT8NIw6Ym+s"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "7+2ZLPaqbntHUtypie8404NhIIqgo9b6/XWNABjgTphWic38/EDYXYm35SLllIxm" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "BrQgwbsBLlnyiOGITMfl+H2I7HCcCYiy22Hx0j62bWvifyZLyGA5PIoId+846U1P31cMX77l9Ok0qh9meltGCw" ); assert_eq!(cert.comment, Some("me@home".to_string())); } #[test] pub fn test_ed25519_pubkey() { let key = sshkeys::PublicKey::from_path("tests/test-keys/id_ed25519.pub").unwrap(); assert_eq!(key.key_type.name, "ssh-ed25519"); assert_eq!(key.key_type.plain, "ssh-ed25519"); assert_eq!(key.key_type.short_name, "ED25519"); assert_eq!(key.key_type.is_cert, false); assert_eq!(key.key_type.is_sk, false); assert_eq!(key.key_type.kind, sshkeys::KeyTypeKind::Ed25519); assert_eq!(key.bits(), 256); assert_eq!(key.comment, Some("me@home".to_string())); let sha256fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "ppYFPx0k4Ogs230n6eX9vGPpnNsTB0LPrDWXh1YjClA"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "B4spD+NiA6esYoqr6dx+w0wBI3p3rQJsTku1rXIWGXTO87W1vvTKMFpwUOdNST2h" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "ljOfAT2lmNZbMDGNwNiLH/dPFIu+euUdXHP+5m0IobCBFYdg7mv8ltqtDBP2vP9vUcOWOow90EQoTPR4oZR1Nw" ); let ed25519 = match key.kind { sshkeys::PublicKeyKind::Ed25519(ref k) => k, _ => panic!("Expected ED25519 public key"), }; // Key size should be 32 bytes // https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.5 assert_eq!(ed25519.key.len(), 32); } #[test] pub fn test_ed25519_user_cert() { let cert = sshkeys::Certificate::from_path("tests/test-keys/id_ed25519-cert.pub").unwrap(); assert_eq!(cert.key_type.name, "ssh-ed25519-cert-v01@openssh.com"); assert_eq!(cert.key_type.plain, "ssh-ed25519"); assert_eq!(cert.key_type.short_name, "ED25519-CERT"); assert_eq!(cert.key_type.is_cert, true); assert_eq!(cert.key.key_type.is_sk, false); assert_eq!(cert.key_type.kind, sshkeys::KeyTypeKind::Ed25519Cert); // Public key part of the certificate assert_eq!(cert.key.key_type.name, "ssh-ed25519-cert-v01@openssh.com"); assert_eq!(cert.key.key_type.plain, "ssh-ed25519"); assert_eq!(cert.key.key_type.short_name, "ED25519-CERT"); assert_eq!(cert.key.key_type.is_cert, true); assert_eq!(cert.key.key_type.is_sk, false); assert_eq!(cert.key.key_type.kind, sshkeys::KeyTypeKind::Ed25519Cert); assert_eq!(cert.key.bits(), 256); assert_eq!(cert.key.comment, None); let sha256fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "ppYFPx0k4Ogs230n6eX9vGPpnNsTB0LPrDWXh1YjClA"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "B4spD+NiA6esYoqr6dx+w0wBI3p3rQJsTku1rXIWGXTO87W1vvTKMFpwUOdNST2h" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "ljOfAT2lmNZbMDGNwNiLH/dPFIu+euUdXHP+5m0IobCBFYdg7mv8ltqtDBP2vP9vUcOWOow90EQoTPR4oZR1Nw" ); assert_eq!(cert.serial, 0); assert_eq!(cert.cert_type, sshkeys::CertType::User); assert_eq!(cert.key_id, "john.doe"); assert_eq!(cert.valid_principals, vec!["root"]); assert_eq!(cert.valid_after, 1506934140); assert_eq!(cert.valid_before, 1538383841); let mut co = HashMap::new(); co.insert("force-command".to_string(), "/usr/bin/true".to_string()); assert_eq!(cert.critical_options, co); let mut extensions = HashMap::new(); extensions.insert("permit-X11-forwarding".to_string(), "".to_string()); extensions.insert("permit-agent-forwarding".to_string(), "".to_string()); extensions.insert("permit-port-forwarding".to_string(), "".to_string()); extensions.insert("permit-pty".to_string(), "".to_string()); extensions.insert("permit-user-rc".to_string(), "".to_string()); assert_eq!(cert.extensions, extensions); // The `reserved` field is empty in the current implementation of OpenSSH certificates assert_eq!(cert.reserved, Vec::new()); // CA public key assert_eq!(cert.signature_key.key_type.name, "ssh-rsa"); assert_eq!(cert.signature_key.key_type.plain, "ssh-rsa"); assert_eq!(cert.signature_key.key_type.short_name, "RSA"); assert_eq!(cert.signature_key.key_type.is_cert, false); assert_eq!(cert.signature_key.key_type.is_sk, false); assert_eq!(cert.signature_key.key_type.kind, sshkeys::KeyTypeKind::Rsa); assert_eq!(cert.signature_key.bits(), 2048); assert_eq!(cert.signature_key.comment, None); let sha256fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "8bEmsdiV2BXhjrzPhp8dPrSLUK3U/YpIXT8NIw6Ym+s"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "7+2ZLPaqbntHUtypie8404NhIIqgo9b6/XWNABjgTphWic38/EDYXYm35SLllIxm" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "BrQgwbsBLlnyiOGITMfl+H2I7HCcCYiy22Hx0j62bWvifyZLyGA5PIoId+846U1P31cMX77l9Ok0qh9meltGCw" ); assert_eq!(cert.comment, Some("me@home".to_string())); } #[test] fn test_ed25519_host_cert() { let cert = sshkeys::Certificate::from_path("tests/test-keys/id_ed25519_host-cert.pub").unwrap(); assert_eq!(cert.key_type.name, "ssh-ed25519-cert-v01@openssh.com"); assert_eq!(cert.key_type.plain, "ssh-ed25519"); assert_eq!(cert.key_type.short_name, "ED25519-CERT"); assert_eq!(cert.key_type.is_cert, true); assert_eq!(cert.key_type.is_sk, false); assert_eq!(cert.key_type.kind, sshkeys::KeyTypeKind::Ed25519Cert); // Public key part of the certificate assert_eq!(cert.key.key_type.name, "ssh-ed25519-cert-v01@openssh.com"); assert_eq!(cert.key.key_type.plain, "ssh-ed25519"); assert_eq!(cert.key.key_type.short_name, "ED25519-CERT"); assert_eq!(cert.key.key_type.is_cert, true); assert_eq!(cert.key.key_type.is_sk, false); assert_eq!(cert.key.key_type.kind, sshkeys::KeyTypeKind::Ed25519Cert); assert_eq!(cert.key.bits(), 256); assert_eq!(cert.key.comment, None); let sha256fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = cert.key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "kkaqMnJz4XAhwz7n7Ov8RbHEYIJ8sxyGQWDmM5Ckot0"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "vGjciz1R26zOHfZ8Vv8m2O7Cz7HxHKWbfuev/LbznWlOWuAqLl1QuuDk/oqhSxKr" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "NCUwuFl6hLiLLX9TUVwmaLjD5q4ql1ayGciFBklt3GYdQzLpX8sLMMBEgcrUgEfZjQtF18d3mNWbEx/okW6Vqw" ); assert_eq!(cert.serial, 0); assert_eq!(cert.cert_type, sshkeys::CertType::Host); assert_eq!(cert.key_id, "host01"); assert_eq!(cert.valid_principals, vec!["host01.example.com"]); assert_eq!(cert.valid_after, 1506936000); assert_eq!(cert.valid_before, 1538385716); // No critical options are defined for host certificates let co = HashMap::new(); assert_eq!(cert.critical_options, co); // No extensions are defined for host certificates let extensions = HashMap::new(); assert_eq!(cert.extensions, extensions); // The `reserved` field is empty in the current implementation of OpenSSH certificates assert_eq!(cert.reserved, Vec::new()); // CA public key assert_eq!(cert.signature_key.key_type.name, "ssh-ed25519"); assert_eq!(cert.signature_key.key_type.plain, "ssh-ed25519"); assert_eq!(cert.signature_key.key_type.short_name, "ED25519"); assert_eq!(cert.signature_key.key_type.is_cert, false); assert_eq!(cert.signature_key.key_type.is_sk, false); assert_eq!( cert.signature_key.key_type.kind, sshkeys::KeyTypeKind::Ed25519 ); assert_eq!(cert.signature_key.bits(), 256); assert_eq!(cert.signature_key.comment, None); let sha256fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = cert .signature_key .fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "elYqUIgEUqMyc8AdNNk+IeI+2l1vWEh4K4n03hqhoD8"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "XPQbeB2kZcG3AUIjIq2wtUDMQYS/Iy0G6trb4XH97zzi4MK+YUqEdx7BAKkZYs0u" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "nIa7CBs7SST41mSeHA7/69y7yy9y3Ec7W6JQKWJsgsBNbY3hq8WiPaa00z5q0AEgC+TO4MK56MoYY2PsE997zw" ); assert_eq!(cert.comment, Some("me@home".to_string())); } #[test] pub fn test_ecdsa_sk_sha2_nistp256_pubkey() { let key = sshkeys::PublicKey::from_path("tests/test-keys/id_ecdsa_sk_sha2_nistp256.pub").unwrap(); assert_eq!(key.key_type.name, "sk-ecdsa-sha2-nistp256@openssh.com"); assert_eq!(key.key_type.plain, "sk-ecdsa-sha2-nistp256@openssh.com"); assert_eq!(key.key_type.short_name, "ECDSA-SK"); assert_eq!(key.key_type.is_cert, false); assert_eq!(key.key_type.is_sk, true); assert_eq!(key.key_type.kind, sshkeys::KeyTypeKind::EcdsaSk); assert_eq!(key.bits(), 256); assert_eq!(key.comment, Some("yubikey-5c-test-wbrown".to_string())); let sha256fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "lJ9TEvCO2FVQ443DnK7UQsA0sR44xXikW9p8gzH/q7s"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "AqhOsPFQcdju8x42C9PMXP3wJiiR1EEkkxQIug8U6g/fdkAayCCaoHplws9j5Bci" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "cQ8670XPoWANc1OjqLcd8kVSvpQGwFy6TufEvZTVJAcvoagSdOyWDwCUBdByVNA1wC5M1iRud32YjH5cNZDReQ" ); let ecdsa = match key.kind { sshkeys::PublicKeyKind::Ecdsa(ref k) => k, _ => panic!("Expected ECDSA public key"), }; assert_eq!(ecdsa.curve.identifier, "nistp256"); assert_eq!(ecdsa.curve.kind, sshkeys::CurveKind::Nistp256); } #[test] pub fn test_ed25519_sk_pubkey() { let key = sshkeys::PublicKey::from_path("tests/test-keys/id_ed25519_sk.pub").unwrap(); assert_eq!(key.key_type.name, "sk-ssh-ed25519@openssh.com"); assert_eq!(key.key_type.plain, "sk-ssh-ed25519@openssh.com"); assert_eq!(key.key_type.short_name, "ED25519-SK"); assert_eq!(key.key_type.is_cert, false); assert_eq!(key.key_type.is_sk, true); assert_eq!(key.key_type.kind, sshkeys::KeyTypeKind::Ed25519Sk); assert_eq!(key.bits(), 256); assert_eq!(key.comment, Some("yubikey-test".to_string())); let sha256fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha256); let sha384fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha384); let sha512fp = key.fingerprint_with(sshkeys::FingerprintKind::Sha512); assert_eq!(sha256fp.kind, sshkeys::FingerprintKind::Sha256); assert_eq!(sha256fp.hash, "SeRUPq2byTg+3B7rlHh+UBoiVET8yG9UJyeG3g3ul2c"); assert_eq!(sha384fp.kind, sshkeys::FingerprintKind::Sha384); assert_eq!( sha384fp.hash, "DCgIRkLNG6UIVdyd3NGeKoP3CZh49BYCyyjvPOfb2ItOTOZDaI87lSuhXLWhcN6N" ); assert_eq!(sha512fp.kind, sshkeys::FingerprintKind::Sha512); assert_eq!( sha512fp.hash, "Se8yFxdmPxL7JtDgUPx71z+xZ8iP9G0cufzQ9rxILApVoN8dpAW8wkd4br+OEjuvzJzzolMUOkia+8Kt6NULeg" ); let ed25519 = match key.kind { sshkeys::PublicKeyKind::Ed25519(ref k) => k, _ => panic!("Expected ED25519 public key"), }; // Key size should be 32 bytes // https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.5 assert_eq!(ed25519.key.len(), 32); } sshkeys-0.3.2/tests/serde.rs000064400000000000000000000015760072674642500141720ustar 00000000000000#![cfg(feature = "serde")] extern crate serde_test; extern crate sshkeys; use self::serde_test::{assert_de_tokens_error, assert_tokens, Token}; use std::fmt; #[test] fn serde_ok_both_ways() { let key = sshkeys::PublicKey::from_path("tests/test-keys/id_ed25519.pub").unwrap(); assert_tokens( &key, &[Token::String( "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIVp6q5co/r5GwY0dH+NYQbfKicapeF3gXEU3dzaAvD me@home", )], ); } #[test] fn serde_de_error() { struct MockError {} impl fmt::Display for MockError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Invalid format") } } let err_format = MockError {}.to_string(); assert_de_tokens_error::(&[Token::Str("M")], &err_format); assert_de_tokens_error::(&[Token::Str("")], &err_format); } sshkeys-0.3.2/tests/test-keys/id_dsa_1024000064400000000000000000000012340072674642500162550ustar 00000000000000-----BEGIN DSA PRIVATE KEY----- MIIBugIBAAKBgQCdU7V8nU7bb98tzEDejbr4DbXnlENPwqvBw9ciHmzpllgXLWfU GIjplTOcidtd0boa7fJCIfQK83Dq2fWHmarke+i+/omtqEUVREJ4mDzDBFo9kGdv uWEjyonLphQL9CElswigT/ZI0Zrx37VtK5BZnAOv2QZCaU4yWRN0UKQdvQIVAPM0 G1PHakq1ZA9PVKY+mo9n/byfAoGAeOg0VlkaPoLw9V+uFyavDdZGOLTaHjOKXJwi N0NgEgCsyUyooNFLAlcEe3/2ioJn17LQjvuuyHI0Iq/A2h2thVyDPRbqXgPLjjnN wRy1R2h5yKiZQvsO2468LFBh4UAYTMR1KKFSH2lAT927i2Z2qATWCo/k8vPrApKc kycY++kCgYAPH5Yamm3tsucA4Vd8umOwiClzQd55F8/fuPMbfZ2QV0bf/vPNQGE4 Yzl5tky/Hl93vIUTmudZczw+8sLg+ZtKnwfcn4iOe1OyokfKzX4hfsHmvWAua85m SIOso2e/52BsYpa8zAtkEIK7iuH8QtijyyhZdlFMgGAd9kCHg1v/2AIUeWdwVoIM z+escl5M+TvWr9mRm7g= -----END DSA PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/id_dsa_1024-cert.pub000064400000000000000000000034020072674642500177740ustar 00000000000000ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgMaBZ3iUI2+Tp2+QcxL81xgccpe1pVTi3MzHOSxK5RIUAAACBAJ1TtXydTttv3y3MQN6NuvgNteeUQ0/Cq8HD1yIebOmWWBctZ9QYiOmVM5yJ213Ruhrt8kIh9ArzcOrZ9YeZquR76L7+ia2oRRVEQniYPMMEWj2QZ2+5YSPKicumFAv0ISWzCKBP9kjRmvHftW0rkFmcA6/ZBkJpTjJZE3RQpB29AAAAFQDzNBtTx2pKtWQPT1SmPpqPZ/28nwAAAIB46DRWWRo+gvD1X64XJq8N1kY4tNoeM4pcnCI3Q2ASAKzJTKig0UsCVwR7f/aKgmfXstCO+67IcjQir8DaHa2FXIM9FupeA8uOOc3BHLVHaHnIqJlC+w7bjrwsUGHhQBhMxHUooVIfaUBP3buLZnaoBNYKj+Ty8+sCkpyTJxj76QAAAIAPH5Yamm3tsucA4Vd8umOwiClzQd55F8/fuPMbfZ2QV0bf/vPNQGE4Yzl5tky/Hl93vIUTmudZczw+8sLg+ZtKnwfcn4iOe1OyokfKzX4hfsHmvWAua85mSIOso2e/52BsYpa8zAtkEIK7iuH8QtijyyhZdlFMgGAd9kCHg1v/2AAAAAAAAAAAAAAAAQAAAAhqb2huLmRvZQAAAAgAAAAEcm9vdAAAAABZu7psAAAAAFubnN8AAABJAAAADWZvcmNlLWNvbW1hbmQAAAARAAAADS91c3IvYmluL3RydWUAAAAOc291cmNlLWFkZHJlc3MAAAANAAAACTEyNy4wLjAuMQAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAJ1L6RsW758SzSjA9CAI6HpuUaJMd9fX75rtVeGSBd7S7rpnuY/aLdCKE3X6T1C7OKExBa6fMldoy98H6cK181Xei2WNQaJgy2MmgSKQApEoqZCiKs/GeDBDDiWBtLF+a+nYviI0f+jG7iGqTMQXfXBb9vkha88HQetQXojj6qXQHoGB75cb6fCmkq8plyubcDlOob7a9kEMsCrxknjBDZiha8nlUp2Dk4AYAY8ME9QW5lCQQz7g+Pb5aY3LUr2lEgJTMn5g1v0HxYWeFRe9Ucups+52O1f8XMOPxmUmfS6/YPijJKtJiYFFaq8l/p8CJJuZjbxidyVVNlp5sLPK9mcAAAEPAAAAB3NzaC1yc2EAAAEANJTLYfmsxSVRTA3ixJuMvrc6+FuGYrlrDMWLs7OXxzjV3GyJ8eOmZj+DzJ6qjsugkRqW8FeV78l65s7Ggv0kwvQWRS9lK9K006Dr85e2VMXOxFWWjY8bTlpjHujfAXfCUcMOYctA7whfv0kkBCDqZ66Gn97eWCVlz9AP9OAUZ9UO7q0yrZZfe0xDNtDuhEHomLiYseexwZYurPpTeELgf+2NnTv9JIX8uuLaNUAUu7BUom3GMHvmEWAFt+JF8DR17jh90eEdtlvtaRv2TrGsoLMv8MXkqrR6JAPWOVv5pbF3VYlKwj77/Px8ycTB3Ov17OAH4YcHbP5TkMM4DaIN8w== me@home sshkeys-0.3.2/tests/test-keys/id_dsa_1024.pub000064400000000000000000000011250072674642500170410ustar 00000000000000ssh-dss AAAAB3NzaC1kc3MAAACBAJ1TtXydTttv3y3MQN6NuvgNteeUQ0/Cq8HD1yIebOmWWBctZ9QYiOmVM5yJ213Ruhrt8kIh9ArzcOrZ9YeZquR76L7+ia2oRRVEQniYPMMEWj2QZ2+5YSPKicumFAv0ISWzCKBP9kjRmvHftW0rkFmcA6/ZBkJpTjJZE3RQpB29AAAAFQDzNBtTx2pKtWQPT1SmPpqPZ/28nwAAAIB46DRWWRo+gvD1X64XJq8N1kY4tNoeM4pcnCI3Q2ASAKzJTKig0UsCVwR7f/aKgmfXstCO+67IcjQir8DaHa2FXIM9FupeA8uOOc3BHLVHaHnIqJlC+w7bjrwsUGHhQBhMxHUooVIfaUBP3buLZnaoBNYKj+Ty8+sCkpyTJxj76QAAAIAPH5Yamm3tsucA4Vd8umOwiClzQd55F8/fuPMbfZ2QV0bf/vPNQGE4Yzl5tky/Hl93vIUTmudZczw+8sLg+ZtKnwfcn4iOe1OyokfKzX4hfsHmvWAua85mSIOso2e/52BsYpa8zAtkEIK7iuH8QtijyyhZdlFMgGAd9kCHg1v/2A== me@home sshkeys-0.3.2/tests/test-keys/id_ecdsa_256000064400000000000000000000003430072674642500165130ustar 00000000000000-----BEGIN EC PRIVATE KEY----- MHcCAQEEILk5U280r87cmQi10Zi4TWjtHuxTrK+ew2D1nGJoqEKRoAoGCCqGSM49 AwEHoUQDQgAEiom75u8Z83fVtIjv4QgRSnbBREHI7C95rOGgL6SoDh4odLxjV6Fq LaTRnf4H4g874fCHh3FQ6x1GN+jU6XZ3aw== -----END EC PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/id_ecdsa_256.pub000064400000000000000000000002510072674642500172760ustar 00000000000000ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIqJu+bvGfN31bSI7+EIEUp2wURByOwveazhoC+kqA4eKHS8Y1ehai2k0Z3+B+IPO+Hwh4dxUOsdRjfo1Ol2d2s= me@home sshkeys-0.3.2/tests/test-keys/id_ecdsa_384000064400000000000000000000004400072674642500165130ustar 00000000000000-----BEGIN EC PRIVATE KEY----- MIGkAgEBBDDRSQ7r3fCcXAYCXwIZ9/YvaCtlayHfioqGsc8uirTqKKEly0wzaoQR 99u49k36QNSgBwYFK4EEACKhZANiAAQWPJNnoyl33SWRRGNKoZtRfWo15QGpUrnQ hTQ2O0lxmco9T6GV6s6Xysx425RDox5tJq2LiA+6s72xKOo22KG2GYxW0Ub1Vc3k gWZNtk2V4EcHaAU5ACqY2KHUVxfM4Ek= -----END EC PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/id_ecdsa_384.pub000064400000000000000000000003250072674642500173020ustar 00000000000000ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBBY8k2ejKXfdJZFEY0qhm1F9ajXlAalSudCFNDY7SXGZyj1PoZXqzpfKzHjblEOjHm0mrYuID7qzvbEo6jbYobYZjFbRRvVVzeSBZk22TZXgRwdoBTkAKpjYodRXF8zgSQ== me@home sshkeys-0.3.2/tests/test-keys/id_ecdsa_521000064400000000000000000000005550072674642500165130ustar 00000000000000-----BEGIN EC PRIVATE KEY----- MIHcAgEBBEIB39GDiEm3ewG1LCD2sfF/ysaHBJrZtX1WzdI/ULUolnT4TzNgGHQ6 etbmTaWBEGVyn0rlXgdmd9Z2bIwj55Gz0fCgBwYFK4EEACOhgYkDgYYABAF/4t16 u6atSiFoO4+oQWRMOWZsyh27H7eR/t7os2So1LYnzV5R/XlMOmXA3f4ipOAHluqE Dlj81N//21fh/rys5wDLxyPUVShIsUAAZrBjbQQgYQT8k5PBfGoABRpaDv1UJoHB Mxd0YG+n4oH3PjLsxdp820rdvougVR0jaW2uwGYi1Q== -----END EC PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/id_ecdsa_521-cert.pub000064400000000000000000000025760072674642500202400ustar 00000000000000ecdsa-sha2-nistp521-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHA1MjEtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgUliw6TZfSXoDVhMBtcW3y4YJZQN8aY5/m4j4JFGan9IAAAAIbmlzdHA1MjEAAACFBAF/4t16u6atSiFoO4+oQWRMOWZsyh27H7eR/t7os2So1LYnzV5R/XlMOmXA3f4ipOAHluqEDlj81N//21fh/rys5wDLxyPUVShIsUAAZrBjbQQgYQT8k5PBfGoABRpaDv1UJoHBMxd0YG+n4oH3PjLsxdp820rdvougVR0jaW2uwGYi1QAAAAAAAAAAAAAAAQAAAAhqb2huLmRvZQAAAAgAAAAEcm9vdAAAAABZyPA4AAAAAFuo0qsAAAAjAAAADnNvdXJjZS1hZGRyZXNzAAAADQAAAAkxMjcuMC4wLjEAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQCdS+kbFu+fEs0owPQgCOh6blGiTHfX1++a7VXhkgXe0u66Z7mP2i3QihN1+k9QuzihMQWunzJXaMvfB+nCtfNV3otljUGiYMtjJoEikAKRKKmQoirPxngwQw4lgbSxfmvp2L4iNH/oxu4hqkzEF31wW/b5IWvPB0HrUF6I4+ql0B6Bge+XG+nwppKvKZcrm3A5TqG+2vZBDLAq8ZJ4wQ2YoWvJ5VKdg5OAGAGPDBPUFuZQkEM+4Pj2+WmNy1K9pRICUzJ+YNb9B8WFnhUXvVHLqbPudjtX/FzDj8ZlJn0uv2D4oySrSYmBRWqvJf6fAiSbmY28YnclVTZaebCzyvZnAAABDwAAAAdzc2gtcnNhAAABABxk5IpgmCrI32lxRtKAVn2rowe625zPHlWMGmJqjz7HPCqB/1p0Y8lKvaMD0rGGlCMb469GWV5qr8TZheThxcM1R8zuW5DzPX4ONv8Hb8MYA6vdfSWuNNA5oHbM5NNFi3YrjBc7h4qARuYnh2hgdlawY1BLMi4rIO6Ynui6ThEhgF6xYdEh+qV7nZ6djz5qpTC+/cBM4ePWW+IW69oWVP29L1iK7CgObeaYz63fONrdPZqK6ZsjkWv3uVgaTgrWYQbK+cjrAfBk4l4cpi4+SQdBKVaofjkCqfXcpvH05Ol2/v/Tw4uWZjhRtlhPjspPkIvKbqyJGezqQOhvmZj12Ts= me@home sshkeys-0.3.2/tests/test-keys/id_ecdsa_521.pub000064400000000000000000000004050072674642500172720ustar 00000000000000ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAF/4t16u6atSiFoO4+oQWRMOWZsyh27H7eR/t7os2So1LYnzV5R/XlMOmXA3f4ipOAHluqEDlj81N//21fh/rys5wDLxyPUVShIsUAAZrBjbQQgYQT8k5PBfGoABRpaDv1UJoHBMxd0YG+n4oH3PjLsxdp820rdvougVR0jaW2uwGYi1Q== me@home sshkeys-0.3.2/tests/test-keys/id_ecdsa_sk_sha2_nistp256000064400000000000000000000011660072674642500212070ustar 00000000000000-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQRkJSmr25+S ZKmHXz9ERDRluu14/5EPhO9ZTDxhtTmURdzd3poC/xlRXUASB7Q4VCM0IZXbX0fuCt5Jim VGleM/AAAABHNzaDoAAADwY3SdlmN0nZYAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEZCUpq9ufkmSph18/REQ0ZbrteP+RD4TvWU w8YbU5lEXc3d6aAv8ZUV1AEge0OFQjNCGV219H7greSYplRpXjPwAAAARzc2g6AQAAAEBA uC6CL/7Ti4yHVjp/UK5LpTZrX42TXE0lKV9JPvYzWiooxbQy0HqDgKi/JhI2hEdt6mPK3o DAzCxFue76G32nAAAAAAAAABZ5dWJpa2V5LTVjLXRlc3Qtd2Jyb3duAQIDBAUG -----END OPENSSH PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/id_ecdsa_sk_sha2_nistp256.pub000064400000000000000000000003470072674642500217740ustar 00000000000000sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGQlKavbn5JkqYdfP0RENGW67Xj/kQ+E71lMPGG1OZRF3N3emgL/GVFdQBIHtDhUIzQhldtfR+4K3kmKZUaV4z8AAAAEc3NoOg== yubikey-5c-test-wbrown sshkeys-0.3.2/tests/test-keys/id_ed25519000064400000000000000000000006600072674642500160400ustar 00000000000000-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACDCFaequXKP6+RsGNHR/jWEG3yonGqXhd4FxFN3c2gLwwAAAKjZ+nZU2fp2 VAAAAAtzc2gtZWQyNTUxOQAAACDCFaequXKP6+RsGNHR/jWEG3yonGqXhd4FxFN3c2gLww AAAECFK2VE62tOHZ061qT7egrpMkqFzB3mRVHK83LwGd3cUMIVp6q5co/r5GwY0dH+NYQb fKicapeF3gXEU3dzaAvDAAAAIW1uaWtvbG92QE1hcmlucy1NYWNCb29rLVByby5sb2NhbA ECAwQ= -----END OPENSSH PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/id_ed25519-cert.pub000064400000000000000000000023320072674642500175560ustar 00000000000000ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIEiLBwyltbppduCgS0d6CdF1YNayWQ3fwPCJuD9YSybIAAAAIMIVp6q5co/r5GwY0dH+NYQbfKicapeF3gXEU3dzaAvDAAAAAAAAAAAAAAABAAAACGpvaG4uZG9lAAAACAAAAARyb290AAAAAFnR/XwAAAAAW7Hf4QAAACYAAAANZm9yY2UtY29tbWFuZAAAABEAAAANL3Vzci9iaW4vdHJ1ZQAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAJ1L6RsW758SzSjA9CAI6HpuUaJMd9fX75rtVeGSBd7S7rpnuY/aLdCKE3X6T1C7OKExBa6fMldoy98H6cK181Xei2WNQaJgy2MmgSKQApEoqZCiKs/GeDBDDiWBtLF+a+nYviI0f+jG7iGqTMQXfXBb9vkha88HQetQXojj6qXQHoGB75cb6fCmkq8plyubcDlOob7a9kEMsCrxknjBDZiha8nlUp2Dk4AYAY8ME9QW5lCQQz7g+Pb5aY3LUr2lEgJTMn5g1v0HxYWeFRe9Ucups+52O1f8XMOPxmUmfS6/YPijJKtJiYFFaq8l/p8CJJuZjbxidyVVNlp5sLPK9mcAAAEPAAAAB3NzaC1yc2EAAAEAYI/gkKir10GYput31qa61cY1+QYwknS7kvkRVIvSB1idZYwqKSKp99Ra4e+4OUKfJjPxtx8dXJ4KBsh7Fvk8TgTDZjIEUwoUZUSKmaW0GFm9r4H5P5XNJr9ZyDA5MqRKLIfyk2g85q1oQapmRWcIuPF+9N+fU02nW3VbxMTCRePatr0PzkRpA8bBFge8Jfjsyb5s+C6sg7c6i5tZqrc2j5htKGOYePRHMNq9Ik3DJbEjnbyQbKkmoobzlCvHGUaYvR/I7mubhdp89VgqRWPppfITr1jsG4gdel2Xn36PJ8WQnnfqXMb2lJ3/KLyJbqIWBpThyqZtDQIOur5Lo1EiHw== me@home sshkeys-0.3.2/tests/test-keys/id_ed25519.pub000064400000000000000000000001310072674642500166160ustar 00000000000000ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIVp6q5co/r5GwY0dH+NYQbfKicapeF3gXEU3dzaAvD me@home sshkeys-0.3.2/tests/test-keys/id_ed25519_host000064400000000000000000000006600072674642500170750ustar 00000000000000-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACAlPpritUYVtrsA3zGtNtiJSvxghe/MnUZ8CuwzbRyI7AAAAKhRX9aXUV/W lwAAAAtzc2gtZWQyNTUxOQAAACAlPpritUYVtrsA3zGtNtiJSvxghe/MnUZ8CuwzbRyI7A AAAED1ybv0T69JZt3+7bdt4FwuzptUpf+TGeqQ2RJyf+JHQCU+muK1RhW2uwDfMa022IlK /GCF78ydRnwK7DNtHIjsAAAAIW1uaWtvbG92QE1hcmlucy1NYWNCb29rLVByby5sb2NhbA ECAwQ= -----END OPENSSH PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/id_ed25519_host-cert.pub000064400000000000000000000007360072674642500206210ustar 00000000000000ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAINj/mLyWPRYnl3+9w5iGY4vtxIwqnTZIAyNY6IvaNHCpAAAAICU+muK1RhW2uwDfMa022IlK/GCF78ydRnwK7DNtHIjsAAAAAAAAAAAAAAACAAAABmhvc3QwMQAAABYAAAASaG9zdDAxLmV4YW1wbGUuY29tAAAAAFnSBMAAAAAAW7HnNAAAAAAAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgyckf14Eho016YGNDfa+4aAoRlOnWX+7fyq7RDtVzaJsAAABTAAAAC3NzaC1lZDI1NTE5AAAAQAMXmH0ahsXqfgWM/Fqag+PA7x25XVftmgjIu0S+Y7eFHaZQeqpeLf4HZ0GxJHkPZwmmVTJx7P5ZovawNgQRFQ0= me@home sshkeys-0.3.2/tests/test-keys/id_ed25519_host.pub000064400000000000000000000001310072674642500176530ustar 00000000000000ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICU+muK1RhW2uwDfMa022IlK/GCF78ydRnwK7DNtHIjs me@home sshkeys-0.3.2/tests/test-keys/id_ed25519_sk000064400000000000000000000010610072674642500165310ustar 00000000000000-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACBqKBR8V8Pgx2mBiwKsXPBS3O52boJSK/HLqG2K x2q6LAAAAARzc2g6AAAA8AE94cQBPeHEAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 9tAAAAIGooFHxXw+DHaYGLAqxc8FLc7nZuglIr8cuobYrHarosAAAABHNzaDoBAAAAgJNz 4kZKZRD5SS9e4rBoMULdNJfFfZ2x2EIIjAZmGmhnj1UZp8D04T2tMY4gYly0ldP3+o1vTi 8L/xFUFh4R0T+0LJG8+UJESEZrOb38vSYtQ7XDCHZHNf3rOPTWeFHDN+NqesnpGQfYzAST PkKH6dZC7fYDMTc5W9AzrpqckofYAAAAAAAAAAx5dWJpa2V5LXRlc3QBAgMEBQ== -----END OPENSSH PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/id_ed25519_sk.pub000064400000000000000000000002150072674642500173160ustar 00000000000000sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIGooFHxXw+DHaYGLAqxc8FLc7nZuglIr8cuobYrHarosAAAABHNzaDo= yubikey-test sshkeys-0.3.2/tests/test-keys/id_rsa_1024000064400000000000000000000015670072674642500163040ustar 00000000000000-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQC+TbX3SNqSrKOTVp2PxWA1sm//M6NQhl/wLZgwlUfitJyc5HMk yLF8ClrNc97XPs8M+yHTn7X3NVBK/SMO9J7vAPugGND+pIjYVFor3Ft++/WT+t5X cCS/MTzo6D5m6CZ/IuBYqTtELkrJjf/0YbV1X9Vwzmt8P2xiFrl5Gq2B6wIDAQAB AoGALkY3OSo9++x+2hT1u0ADZQs+sI+d5rbGHWD44Ndr43SHoJ7sYMVsYv0hl1PV nAFp1345e3wag0IzhAiJvdk9y/SVuAOu0WfaJVbqswsMP/oMTC2BWtwcIPSLwUiW XnCtGvCzYa6T44ez0fJaErvpj7U1qd9AHPqWNTEIR00V+gECQQDsxm4Ll0FcyxZv IPaOpfnEMIkyBk36PET2ydKFJd01WWOkirILMdptt9YWenD0H+qpaigmS2yRmpZD FDD/qdUnAkEAzcFUmXQAxX/b1pJ+dthMkgvhwnU0KwAr0uuKPKz8u95mER/kyWKR Z8gAOBl62Zhwg/SNNE1b2C2PDUK0vgOPnQJBAJ4LQW8pMi7fPIVHCmxjK1miUCF9 BdWvHxVf186aXJJ8rT8qePdx+mvcFuIALp81IqycuFn/ZGO4PO5fbulokmcCQQC3 GOP/6osFNdKcD6EagUEidhBgy4uw+GYHPDO36vi89hw+APPHgj+C6yfGxGXeXRlD U8yUToL8zQ4P7tyIewLBAkAgq/lBnvEc3yGDC0jztLDKhprC/5uNqmtPqrT+CnBz Pz9x/ziBHVsGZiYpxNHBHXAJusWjrOpWSMfC/tF2lvSO -----END RSA PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/id_rsa_1024.pub000064400000000000000000000003250072674642500170600ustar 00000000000000ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+TbX3SNqSrKOTVp2PxWA1sm//M6NQhl/wLZgwlUfitJyc5HMkyLF8ClrNc97XPs8M+yHTn7X3NVBK/SMO9J7vAPugGND+pIjYVFor3Ft++/WT+t5XcCS/MTzo6D5m6CZ/IuBYqTtELkrJjf/0YbV1X9Vwzmt8P2xiFrl5Gq2B6w== sshkeys-0.3.2/tests/test-keys/id_rsa_2048000064400000000000000000000032130072674642500163010ustar 00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAogoYpx/b6JWrk7y3xlr9sQiKNI60AL9IwkI3w6HWVvhNbyxV HIHVCynpro8Rtry8y1B30hxfZo58Jxm8h2GYtXxDu9LN4BmTXfStscL5BqNvLL3n wnzUd4Yvo0gfUPXa70ewoGHRGOQ/dGfzn0lieGutP6qQ+y97l3+a4qmHXQ1Gx1ZQ 4NdUituyh2p991AH7JHebtgHHEW1yiV9yOqDu/AMCOP3x7Njf0bqJXmHLB1/RTWl V/DR8UhGOxFy0z5spEUI/P/Lm47n5b5uKmE7FvHBbURE38ZIBTBdKd++WBFUJXrP +icEbJY51WqG4snjRtbv+aeM2hILrqje6FabDwIDAQABAoIBAFusxqHW/n2qH/Zn sLmCRUFhiX+OtPwvPKTa/d2qtC9kL7sUI9sLAVNdlR3zR5xRT6bfkcrHzpmhR1B/ 2Q/nAZS8Bz4+V8fP8HYZtiN6IZXF5WI01uhL45Dz1APXDBCr5/+0WZODg99HUzcy kLyvsgxbLxt0Dq5uAMiHo0NVkoXr1HuTZpPuf0qIsyGMi8cNwyrB5BFuR8ZA5qaM KWbXrzRjGcJ+TlMq7beJYZqqnYkbotmQloOgWh52cKogp5bgTfDYde1/xnHmS7nt uFrjg6NHJwUcmbbQnz+ZkmpCQW+8RPozRmke+lwyVVFQSXBKCwvY1f7oaYIKl3Mj AK+eG/ECgYEAz9DkBVqMLNVsz69rTuF+wGAQ5WlLWOnRPUFtpndkRTRnV76xIOyI 58yiuBja2CJ3vh14GpvQIpM19KOKcHEZ204zgmWdqHug8gW2Xouz6QM4RoTRw/VB 9YdlLZW+NlQaAXBE2QvoNEWrdmcfP5zfrQkaBtc3tngddJBQD/qZktUCgYEAx5wY xaA/HohZA/EIxZbc/N4esLlPI/RIjYbx68MilhqYR4yFfh/3V+cCo6rMHPF5X6E0 smfm+ujN0dRjG8tvZD4mIwfbhCy5oMGvCMCwV1GjLU0WgQ7mixP4xLND2R089KAx MkOWZ8qWTHwiFO+yX7y1wkPEsG7hNNR0ClRcAFMCgYBV6UBqqi0q16xdC2LsQDJb KxuxC193yWmTzjmbSN4t8eULFC07tC1AzosyWiwWj+E6ugoNzf40XPFASl+P7mHH FMQckw+jOECn7Q6gdVaR7J/WH1BslzaGX0vHlZEF+qypjZUYuWBsQ6UHlMgJTzv0 179nto80ouFib8p5YJseZQKBgGEbnKWQRwTIml2jhnvx4AKY4N9i15CLSDyp+MmU vh++QnUUdOEeFgvKk+shrXkrNLwERgnBKIrKdU7uf2THPKLM5WrHaNDNnWUKtOeS LnfcfIEObrNMl3XzumOfPpPCeKQdxrFIVkSaNzJwdXgwAFw5B0fCBk87Mg6siON5 lOSHAoGAZlVs4hb50/kTNh//5DPT0E+QK3sA6qIz9TpUGlwoapkRWkW8A9pfIK+U rgZIGwNMwtPFfMOqBfZj556ga5WrmDitdQW/jnNIGIIC4hvJN7MT4xOjNZAe570G Lw7aBhNUV1FVirIXONMcz97hOy7ZblyntiE9p9kDeSfuCjNn0cM= -----END RSA PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/id_rsa_2048-cert.pub000064400000000000000000000030620072674642500200230ustar 00000000000000ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgZ7GOtg84uGTuHiLqi4VKLmPTyMP62TAFVoSRMKjw3fsAAAADAQABAAABAQCiChinH9volauTvLfGWv2xCIo0jrQAv0jCQjfDodZW+E1vLFUcgdULKemujxG2vLzLUHfSHF9mjnwnGbyHYZi1fEO70s3gGZNd9K2xwvkGo28svefCfNR3hi+jSB9Q9drvR7CgYdEY5D90Z/OfSWJ4a60/qpD7L3uXf5riqYddDUbHVlDg11SK27KHan33UAfskd5u2AccRbXKJX3I6oO78AwI4/fHs2N/RuoleYcsHX9FNaVX8NHxSEY7EXLTPmykRQj8/8ubjuflvm4qYTsW8cFtRETfxkgFMF0p375YEVQles/6JwRsljnVaobiyeNG1u/5p4zaEguuqN7oVpsPAAAAAAAAAAAAAAABAAAACGpvaG4uZG9lAAAACAAAAARyb290AAAAAFm6MowAAAAAW5oU8QAAAEkAAAANZm9yY2UtY29tbWFuZAAAABEAAAANL3Vzci9iaW4vdHJ1ZQAAAA5zb3VyY2UtYWRkcmVzcwAAAA0AAAAJMTI3LjAuMC4xAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAABFwAAAAdzc2gtcnNhAAAAAwEAAQAAAQEAnUvpGxbvnxLNKMD0IAjoem5Rokx319fvmu1V4ZIF3tLuume5j9ot0IoTdfpPULs4oTEFrp8yV2jL3wfpwrXzVd6LZY1BomDLYyaBIpACkSipkKIqz8Z4MEMOJYG0sX5r6di+IjR/6MbuIapMxBd9cFv2+SFrzwdB61BeiOPqpdAegYHvlxvp8KaSrymXK5twOU6hvtr2QQywKvGSeMENmKFryeVSnYOTgBgBjwwT1BbmUJBDPuD49vlpjctSvaUSAlMyfmDW/QfFhZ4VF71Ry6mz7nY7V/xcw4/GZSZ9Lr9g+KMkq0mJgUVqryX+nwIkm5mNvGJ3JVU2Wnmws8r2ZwAAAQ8AAAAHc3NoLXJzYQAAAQCQiF5UPpWCEg9+TtGeJftRWPYwae5aNauLyrwWwwavUHIkkC5wzowNNHQkLDgJ9wELuFCntobV8R+DbBq3wpOZL/+IlxDTDOWAczh2sIz5EnpwJ85W80ic4oeG0Q/QTx9mxbwiaoOFZPlEzYOuezSiYA5DhktOeAeqhs7nLO5Mq12YlXshmpTuGed3MJ038je1jKDUKElDDf9DMgT84a6AYGvudApbS/kKGO1J+ID+PNnaQqdHk9asCDM1fB0tUiYnpu645TDqEMjz/+1d2yd0mmNhfIjjUWGNzDhRitEaEpgemg/ppnqEakropZQtOW/JQiKBt4v0TshWiMkRPT8L me@home sshkeys-0.3.2/tests/test-keys/id_rsa_2048.pub000064400000000000000000000006050072674642500170700ustar 00000000000000ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCiChinH9volauTvLfGWv2xCIo0jrQAv0jCQjfDodZW+E1vLFUcgdULKemujxG2vLzLUHfSHF9mjnwnGbyHYZi1fEO70s3gGZNd9K2xwvkGo28svefCfNR3hi+jSB9Q9drvR7CgYdEY5D90Z/OfSWJ4a60/qpD7L3uXf5riqYddDUbHVlDg11SK27KHan33UAfskd5u2AccRbXKJX3I6oO78AwI4/fHs2N/RuoleYcsHX9FNaVX8NHxSEY7EXLTPmykRQj8/8ubjuflvm4qYTsW8cFtRETfxkgFMF0p375YEVQles/6JwRsljnVaobiyeNG1u/5p4zaEguuqN7oVpsP me@home sshkeys-0.3.2/tests/test-keys/id_rsa_2048_invalid000064400000000000000000000032170072674642500200130ustar 00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAxgzUkMoGDNM93lS6I42OYD1Ijrugt1JxLWKB3jnZ6NI69pxP ggPMr0QLv5SLaj4KKQ1mD+NyV82YLuEZWaNhswtaw3geCi96I7bE3bG2z/12iC8h qDtMaKXuGSPy7sY15AJ+i6lG70WMNUZhLTKXrC9wZi5OL0o6AZKNuq1VrZtP0RC4 MO6wP7rLxd9xJU7+YtAUiftg/2o5sLS76m7WIVr45l1ObM9xdw2IWr7Mxb3/iq1Z uXjzdJ4YJjejV/iT3s8Boo3LyjN6VNhddSO05GSwYQawlZL92QUlje4ypLgsamM2 xOOvc9B59lG+ZcbWsFJTpzlnTLafEOi2fLkBCQIDAQABAoIBAQCsyiDiuf+RTPPb eBx2TFh9iro1HWnYx2rK5/jaQ6rkwBaFdla/3kTEXR/K4/TGmp4OtwvmrM/j3xH5 RJbzZ+IjbbKge7nptQZhBmK38QbIbCDwK/63YhUF8E7NTFn1DKWT6sExZFzpAMqU 6HR8FHnT1gfAfoHkLGRzXsOcrQHlVeSMfcJPbR07b18567cbCgnOOx7ZU0ANY+zG clSVc31QyoKhgsBjFTQT1+cqHSXvNsjFuoLL/5sigSfugCFnh9bcYLxmaFPTMUK/ K1Jkp2LzjrB9QNslkyK0bUhMyPz7gmGjWwkMjF4NvwCO7Xz8YoLW5k1gKAsZ+q/C aubdZ4tpAoGBAOq/6X+pJcdtUXgxkfqyHFyqXV4Yel3y9SNNiRt7TWOl4dks8vOL QzFQ8gwp9ME/8la35EnHYwweCSryQoZNYJA/CNRmLOSOAlBV0jn3JhMOz4H0had/ OGNW0jtqbWyeszXQgiWobuhOIaukoBh+mEQcKHW5saSj+UpVd5CV3e+zAoGBANf6 cXfHlpB5dG1V6ZRmPpUKK+54OnQK4/PJGnlnBslG5u96NVzeo7TGxNrW6V4bufKR /nALAQ1yspKssMzPhj8nEcISg1UOIBH4J9PQr70h4GqyYP6ZhKAwDOiSQ6tKyKZO rSNO/S3T7rsO7dTjSfoPPOlw94rq1WkpUdHKdY5TAoGALWtEOjb34EX+ZUrx+5dK dYNg3TvPMS44z8PIq1CIAKevst1HhGeFcJ1At6nGeT1uHekmej/hog6Np4mH5YRD EqWfh7jdJrtzJyfzrNNswnMzIum0klvDBTVfJ6/HzCRIeDkHdVHJY5j6WsNXVmXo AAWSrnRnMnunWAKBR7A3aJECgYEArvtofPwGn4zXaFHnyeTApW21RCLCcQv1vajc OynelKpOJg3kOBblmWxFR2xBbI6YK9BezZYMx0F7LlydbYJhKL9Vot/u6bVlBEoC spjsGRbeRHO7I+trSYFEpBUEoD4ZrKwnmGjBtSR00bb5t7ZiVCeOWS++Tx2NxALH GGqoraMCgYBBhcEu4S+UySTxIKz+NpHx71d+hM5oplEQMoJMMRkR19chtPOys2uH z2xXGDYwUXS7dnKgWGs256s0LbWi3bGk2cH6psU48UMFAhH5vzNEzyq0Gp/5uUH8 LjCZ5Z1UI2nseciuDJlpiVGbnZBH0YmTI44I71F5zbSfIiC+Q3SA0Q== -----END RSA PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/id_rsa_2048_invalid_format000064400000000000000000000032130072674642500213570ustar 00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA6Es6hPr6KKT+Dq6D6cDFbdmJpASpAjs7OA9Vw3D3EriIKppA WC2oJjkzDz6G2DMQtsZU3MHLQO5QBnNcPk03qy26u59QJj0Sv0DhnX9B4uoNcV2Z KYB5wDQ33kMcEZkLGvRZVIKyPS1YGevuOrbOOvKHUYha8QxYTYB58mt3nqnFW6pf c9Z4NS9bfFtMCIXWmQMDUvyyJUUPilNoO3qkLtZI68zMRPd+brlfpDyUoJFfE+2t mJKtHUkkW/eXqMlzxcppsvMUCrU+QkAkhZ1NlRmZcs/YaHdzxtMfE4XoGCCynVsA Ai+RfpOkgzcSRn8czQgqj6zG+UaCNPOnt7TkdQIDAQABAoIBAQCTzQHwCMzQvaJU 7x9JxPkZmvdj3/81R0C3u7IjB6Z9R+KD0N+t+2bo4y4kvfEIcP1qfikSyU+tAbTz VcVUcsc/6HnO1WAm5GcgP4UONCFU4v0oq5g/etp8u/zsM6ERZWJWhTCtf/cuy8Ip xB8xRo1TnmsRKoRKqUMqFNwCrfRPg5l3s0dxZKWuttSmhFYqWjddHhCuw0ymnQqg pQAZDdgOMBk9siaMKST46vdy39P4YnIpfT+S9KZTvT4l1KRl5ixBD+4Z4pzUsVca cvcaNrISeQwap+82FZusw1ZQhB5Qn5Ty6zNk0lSPJu2Drz0KdT6VXmDaiMlC4qX7 En+gNFSBAoGBAPrep4cVmkMPO+OyuAWUyOfR+VGwnBxvZkn5yaDLvYrTRvSbLSp5 kEEzeIDtfH8y/U8xwaSpc35mgXNWXu5ApuY5MhjZWcFqIaTGFTvwr84D5HZEDn/s q74+m0FGhUTmk0ac/CG7Ov64W4UiABvcA72XjSSGiWEtIxUz9bek+HzhAoGBAO0L U4hD7yQtW6LgdqtiD5GOqi5OB8peAE8US2ymLPYeRVx4Fx5TuIQFyYPMhLMn7qx+ 7C+7mATyRZoN9ZJQVGPq56Cq1o6norjEBuYFRVY0xkWFbcLA7kfXEHoCJ0EaOVXc O+8hFYhVqmZ+Ll6Lnqj0rmB94lqL1Je6gSKWsWYVAoGBAJ54vgz4GX1ZBzT79YEZ DpxaKItw6/yOZmg+kR6w9SfX9M+ZortdFUIKuImA+48Cb79yJ+fTXvCu4gEww0Dv uD5gTQQjcK5cU6pZspotnXCfRtdqgFpQ7+B6feqLGK6AlPIbQq4wLsEvRijgZH80 yWwfavpyvh+TusCvFP4QCSQhAoGAC/UoT5VtuNt45eyA0ABwXJ1fxFo3VmQLi/Gw JFj1p6y7PwDn2aXLhw1rrvRgNVFsXtNAQuApuQYnsK/HlYvr1eaBrL8xd5zJPpzU 5EGbz891uQgUE2D8JC+bKyx0onoaLlSfyV5X4brAj88Js8dDR66gJUn0YzDuloDY BtCnPkkCf0Ov5skAUBHcl7nYi7WqUKl1JR06tPYhcFbWslnYj+Yxy0v41uoGX93C kyDWBFrpsu0B0R90wYb83Ju8bkD8nYtvLpadTRX0x8kADrKhrAEJTZlnxPP+oXe/ YkCLrvtSu0o4h+RWccqCbOWrctWt9scVOsXHD2a7ujWZfQPfTKA= -----END RSA PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/id_rsa_2048_invalid_format.pub000064400000000000000000000005650072674642500221530ustar 00000000000000AAAAB3NzaC1yc2EAAAADAQABAAABAQDoSzqE+voopP4OroPpwMVt2YmkBKkCOzs4D1XDcPcSuIgqmkBYLagmOTMPPobYMxC2xlTcwctA7lAGc1w+TTerLbq7n1AmPRK/QOGdf0Hi6g1xXZkpgHnANDfeQxwRmQsa9FlUgrI9LVgZ6+46ts468odRiFrxDFhNgHnya3eeqcVbql9z1ng1L1t8W0wIhdaZAwNS/LIlRQ+KU2g7eqQu1kjrzMxE935uuV+kPJSgkV8T7a2Ykq0dSSRb95eoyXPFymmy8xQKtT5CQCSFnU2VGZlyz9hod3PG0x8ThegYILKdWwACL5F+k6SDNxJGfxzNCCqPrMb5RoI086e3tOR1 sshkeys-0.3.2/tests/test-keys/id_rsa_2048_unknown_keytype.pub000064400000000000000000000006220072674642500224200ustar 00000000000000ssh-rsa-invalid-type AAAAB3NzaC1yc2EAAAADAQABAAABAQDGDNSQygYM0z3eVLojjY5gPUiOu6C3UnEtYoHeOdno0jr2nE+CA8yvRAu/lItqPgopDWYP43JXzZgu4RlZo2GzC1rDeB4KL3ojtsTdsbbP/XaILyGoO0xope4ZI/LuxjXkAn6LqUbvRYw1RmEtMpesL3BmLk4vSjoBko26rVWtm0/RELgw7rA/usvF33ElTv5i0BSJ+2D/ajmwtLvqbtYhWvjmXU5sz3F3DYhavszFvf+KrVm5ePN0nhgmN6NX+JPezwGijcvKM3pU2F11I7TkZLBhBrCVkv3ZBSWN7jKkuCxqYzbE469z0Hn2Ub5lxtawUlOnOWdMtp8Q6LZ8uQEJ me@home sshkeys-0.3.2/tests/test-keys/ssh_ca_host_key000064400000000000000000000006600072674642500175330ustar 00000000000000-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACDJyR/XgSGjTXpgY0N9r7hoChGU6dZf7t/KrtEO1XNomwAAAKiLJ0DeiydA 3gAAAAtzc2gtZWQyNTUxOQAAACDJyR/XgSGjTXpgY0N9r7hoChGU6dZf7t/KrtEO1XNomw AAAEAFmLDaWR0fgxo8lQo1ebYghxMUoHqkjlpZazA3YCFa7MnJH9eBIaNNemBjQ32vuGgK EZTp1l/u38qu0Q7Vc2ibAAAAIW1uaWtvbG92QE1hcmlucy1NYWNCb29rLVByby5sb2NhbA ECAwQ= -----END OPENSSH PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/ssh_ca_host_key.pub000064400000000000000000000001310072674642500203110ustar 00000000000000ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMnJH9eBIaNNemBjQ32vuGgKEZTp1l/u38qu0Q7Vc2ib me@home sshkeys-0.3.2/tests/test-keys/ssh_ca_user_key000064400000000000000000000032170072674642500175350ustar 00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEAnUvpGxbvnxLNKMD0IAjoem5Rokx319fvmu1V4ZIF3tLuume5 j9ot0IoTdfpPULs4oTEFrp8yV2jL3wfpwrXzVd6LZY1BomDLYyaBIpACkSipkKIq z8Z4MEMOJYG0sX5r6di+IjR/6MbuIapMxBd9cFv2+SFrzwdB61BeiOPqpdAegYHv lxvp8KaSrymXK5twOU6hvtr2QQywKvGSeMENmKFryeVSnYOTgBgBjwwT1BbmUJBD PuD49vlpjctSvaUSAlMyfmDW/QfFhZ4VF71Ry6mz7nY7V/xcw4/GZSZ9Lr9g+KMk q0mJgUVqryX+nwIkm5mNvGJ3JVU2Wnmws8r2ZwIDAQABAoIBAQCOXYpZzmSKoUW2 wQ0zgVyIkxinwHYnkXV3z5+PTc6qYldXt1Gn9VzKBm6etTLcatdSbUArUEMMAfmj n1HfvTbEXWvlOfhRszHiR5NRaO4p25e9JEmDTKqzY72GDOMyUq3xNQ7BfqrWUFZv eeeJA4mxDEt4KNuewX7UMCWf2EkkUNH7bShYU9N12M8nFl3Mt1WCbX/ildsYa664 ulh9F+8B8685nTPRLJP/fT5HCYsv2WN/lxRfmVsrb5F71k8Sx3FfRbCBEHYRcS9M 9fLQDRo8DTzvlW7liPFdRuAxL5JBCEbsmHtBB8G8rMgMAWy2ZrbEshGavqADARQK 8ax0K07BAoGBANE35Co9Xeoh8Gu5GBw6/tCsdW6uF0BsoU08KF9WfaTN8VNKmCDU EJd2awp+cqswFcaPq9k/bljcuJ9+6S6lkOGI8NzltVVK6kFNIrytp6wK4jnXixEt cBHxkjxJ29AQhk/5aqq5zEdFz54vwOjZ3szOfhYIN6HqnOKz6ggEwdeJAoGBAMB3 50Mx4U3QWbO18fh3b0MzRcbXJhZot8xb51qQ5y/8npXgUgWmtp4kOLSMJ5kt9EzS /ZEsotSQFOs5TPRsx6R5E9IxNK+XU1uo07w9i5B6vluHlklq48D2Ph2j1FrWdwrd WizfZsUNkB9b4KdjYKP4Xa4qoNWIeFFjlrjnR/JvAoGBAMJjx99nPUc5WYT9aWVx eyiv1DyODJSTWhvE9U3/sqXZo4vcFxUJdJEGOdZ6PljISLNA8k7cHM775Z5r8ISi 2MZ00jasR5uEC7u4y7m7L7suMZvEpTXEnghOB610goQDlofgGjeegisGti0n+Xlg VR6+DXCzGd2be0E4IQ5qPSDhAoGASKH3KCh+ufrSnzseYYHQ/y8uOeefe/1wvzI/ kLH2TOmsfyr0SSWs7OkGbTwnBWuOMh+9iTerC0SEYHBzVhpnDO6USFJBa7JTxtdj cDpZnOB1Td1RHcu0v3Et58mXreAZdIQsL5rvEZYYuXzWvtSF99sWn09++pZRsYU/ r++3+wkCgYEAvRG7czdvlWUpTUiPYimE/0idDSGXSaWVunZnlVf56os6IkHwsL7a U/raUb6dDG+j9dFQIwD10jbmT09wIRrqRZPAKUrZfBqBGk+blNPNeZjlhMXimqo/ R5u9JFfve4Kk9D89i+RMPW0yLSEnF/WdmURmlW5oDjyemBNaFd8FR+E= -----END RSA PRIVATE KEY----- sshkeys-0.3.2/tests/test-keys/ssh_ca_user_key.pub000064400000000000000000000006050072674642500203200ustar 00000000000000ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCdS+kbFu+fEs0owPQgCOh6blGiTHfX1++a7VXhkgXe0u66Z7mP2i3QihN1+k9QuzihMQWunzJXaMvfB+nCtfNV3otljUGiYMtjJoEikAKRKKmQoirPxngwQw4lgbSxfmvp2L4iNH/oxu4hqkzEF31wW/b5IWvPB0HrUF6I4+ql0B6Bge+XG+nwppKvKZcrm3A5TqG+2vZBDLAq8ZJ4wQ2YoWvJ5VKdg5OAGAGPDBPUFuZQkEM+4Pj2+WmNy1K9pRICUzJ+YNb9B8WFnhUXvVHLqbPudjtX/FzDj8ZlJn0uv2D4oySrSYmBRWqvJf6fAiSbmY28YnclVTZaebCzyvZn me@home