chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

56
vendor/ssh-key/tests/algorithm_name.rs vendored Normal file
View File

@@ -0,0 +1,56 @@
//! Tests for `AlgorithmName` parsing.
#![cfg(feature = "alloc")]
use ssh_key::AlgorithmName;
use std::str::FromStr;
#[test]
fn additional_algorithm_name() {
const NAME: &str = "name@example.com";
const CERT_STR: &str = "name-cert-v01@example.com";
let name = AlgorithmName::from_str(NAME).unwrap();
assert_eq!(name.as_str(), NAME);
assert_eq!(name.certificate_type(), CERT_STR);
let name = AlgorithmName::from_certificate_type(CERT_STR).unwrap();
assert_eq!(name.as_str(), NAME);
assert_eq!(name.certificate_type(), CERT_STR);
}
#[test]
fn invalid_algorithm_name() {
const INVALID_NAMES: &[&str] = &[
"nameß@example.com",
"name@example@com",
"name",
"@name",
"name@",
"",
"@",
"a-name-that-is-too-long-but-would-otherwise-be-valid-@example.com",
];
const INVALID_CERT_STRS: &[&str] = &[
"nameß-cert-v01@example.com",
"name-cert-v01@example@com",
"name@example.com",
];
for name in INVALID_NAMES {
assert!(
AlgorithmName::from_str(&name).is_err(),
"{:?} should be an invalid algorithm name",
name
);
}
for name in INVALID_CERT_STRS {
assert!(
AlgorithmName::from_certificate_type(&name).is_err(),
"{:?} should be an invalid certificate str",
name
);
}
}

55
vendor/ssh-key/tests/authorized_keys.rs vendored Normal file
View File

@@ -0,0 +1,55 @@
//! Tests for parsing `authorized_keys` files.
#![cfg(all(feature = "ecdsa", feature = "std"))]
use ssh_key::AuthorizedKeys;
// TODO(tarcieri): test file permissions
#[test]
fn read_example_file() {
let authorized_keys = AuthorizedKeys::read_file("./tests/examples/authorized_keys").unwrap();
assert_eq!(authorized_keys.len(), 5);
assert_eq!(authorized_keys[0].config_opts().to_string(), "");
assert_eq!(
authorized_keys[0].public_key().to_string(),
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqti"
);
assert_eq!(authorized_keys[0].public_key().comment(), "");
assert_eq!(
authorized_keys[1].config_opts().to_string(),
"command=\"/usr/bin/date\""
);
assert_eq!(authorized_keys[1].public_key().to_string(), "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHwf2HMM5TRXvo2SQJjsNkiDD5KqiiNjrGVv3UUh+mMT5RHxiRtOnlqvjhQtBq0VpmpCV/PwUdhOig4vkbqAcEc= user2@example.com");
assert_eq!(
authorized_keys[1].public_key().comment(),
"user2@example.com"
);
assert_eq!(
authorized_keys[2].config_opts().to_string(),
"environment=\"PATH=/bin:/usr/bin\""
);
assert_eq!(authorized_keys[2].public_key().to_string(), "ssh-dss AAAAB3NzaC1kc3MAAACBANw9iSUO2UYhFMssjUgW46URqv8bBrDgHeF8HLBOWBvKuXF2Rx2J/XyhgX48SOLMuv0hcPaejlyLarabnF9F2V4dkpPpZSJ+7luHmxEjNxwhsdtg8UteXAWkeCzrQ6MvRJZHcDBjYh56KGvslbFnJsGLXlI4PQCyl6awNImwYGilAAAAFQCJGBU3hZf+QtP9Jh/nbfNlhFu7hwAAAIBHObOQioQVRm3HsVb7mOy3FVKhcLoLO3qoG9gTkd4KeuehtFAC3+rckiX7xSCnE/5BBKdL7VP9WRXac2Nlr9Pwl3e7zPut96wrCHt/TZX6vkfXKkbpUIj5zSqfvyNrWKaYJkfzwAQwrXNS1Hol676Ud/DDEn2oatdEhkS3beWHXAAAAIBgQqaz/YYTRMshzMzYcZ4lqgvgmA55y6v0h39e8HH2A5dwNS6sPUw2jyna+le0dceNRJifFld1J+WYM0vmquSr11DDavgEidOSaXwfMvPPPJqLmbzdtT16N+Gij9U9STQTHPQcQ3xnNNHgQAStzZJbhLOVbDDDo5BO7LMUALDfSA== user3@example.com");
assert_eq!(
authorized_keys[2].public_key().comment(),
"user3@example.com"
);
assert_eq!(
authorized_keys[3].config_opts().to_string(),
"from=\"10.0.0.?,*.example.com\",no-X11-forwarding"
);
assert_eq!(authorized_keys[3].public_key().to_string(), "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC0WRHtxuxefSJhpIxGq4ibGFgwYnESPm8C3JFM88A1JJLoprenklrd7VJ+VH3Ov/bQwZwLyRU5dRmfR/SWTtIPWs7tToJVayKKDB+/qoXmM5ui/0CU2U4rCdQ6PdaCJdC7yFgpPL8WexjWN06+eSIKYz1AAXbx9rRv1iasslK/KUqtsqzVliagI6jl7FPO2GhRZMcso6LsZGgSxuYf/Lp0D/FcBU8GkeOo1Sx5xEt8H8bJcErtCe4Blb8JxcW6EXO3sReb4z+zcR07gumPgFITZ6hDA8sSNuvo/AlWg0IKTeZSwHHVknWdQqDJ0uczE837caBxyTZllDNIGkBjCIIOFzuTT76HfYc/7CTTGk07uaNkUFXKN79xDiFOX8JQ1ZZMZvGOTwWjuT9CqgdTvQRORbRWwOYv3MH8re9ykw3Ip6lrPifY7s6hOaAKry/nkGPMt40m1TdiW98MTIpooE7W+WXu96ax2l2OJvxX8QR7l+LFlKnkIEEJd/ItF1G22UmOjkVwNASTwza/hlY+8DoVvEmwum/nMgH2TwQT3bTQzF9s9DOJkH4d8p4Mw4gEDjNx0EgUFA91ysCAeUMQQyIvuR8HXXa+VcvhOOO5mmBcVhxJ3qUOJTyDBsT0932Zb4mNtkxdigoVxu+iiwk0vwtvKwGVDYdyMP5EAQeEIP1t0w== user4@example.com");
assert_eq!(
authorized_keys[3].public_key().comment(),
"user4@example.com"
);
assert_eq!(authorized_keys[4].public_key().to_string(), "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN76zuqnjypL54/w4763l7q1Sn3IBYHptJ5wcYfEWkzeNTvpexr05Z18m2yPT2SWRd1JJ8Aj5TYidG9MdSS5J78= hello world this is a long comment");
assert_eq!(
authorized_keys[4].public_key().comment(),
"hello world this is a long comment"
);
}

354
vendor/ssh-key/tests/certificate.rs vendored Normal file
View File

@@ -0,0 +1,354 @@
//! OpenSSH certificate tests.
#![cfg(feature = "alloc")]
use hex_literal::hex;
use ssh_key::{Algorithm, Certificate};
use std::str::FromStr;
#[cfg(feature = "ecdsa")]
use ssh_key::EcdsaCurve;
#[cfg(feature = "rsa")]
use ssh_key::HashAlg;
/// DSA OpenSSH Certificate
const DSA_CERT_EXAMPLE: &str = include_str!("examples/id_dsa_1024-cert.pub");
/// ECDSA/P-256 OpenSSH Certificate
#[cfg(feature = "ecdsa")]
const ECDSA_P256_CERT_EXAMPLE: &str = include_str!("examples/id_ecdsa_p256-cert.pub");
/// Ed25519 OpenSSH Certificate
const ED25519_CERT_EXAMPLE: &str = include_str!("examples/id_ed25519-cert.pub");
/// Ed25519 OpenSSH Certificate with deliberately invalid signature
#[cfg(feature = "ed25519")]
const ED25519_CERT_BADSIG_EXAMPLE: &str = include_str!("examples/id_ed25519-cert-badsig.pub");
/// Ed25519 OpenSSH Certificate with P-256 certificate authority
#[cfg(feature = "p256")]
const ED25519_CERT_WITH_P256_CA_EXAMPLE: &str =
include_str!("examples/id_ed25519-cert-with-p256-ca.pub");
/// Ed25519 OpenSSH Certificate with RSA certificate authority
#[cfg(feature = "rsa")]
const ED25519_CERT_WITH_RSA_CA_EXAMPLE: &str =
include_str!("examples/id_ed25519-cert-with-rsa-ca.pub");
/// RSA (4096-bit) OpenSSH Certificate
const RSA_4096_CERT_EXAMPLE: &str = include_str!("examples/id_rsa_4096-cert.pub");
/// Security Key (FIDO/U2F) ECDSA/NIST P-256 OpenSSH Certificate
#[cfg(feature = "ecdsa")]
const SK_ECDSA_P256_CERT_EXAMPLE: &str = include_str!("examples/id_sk_ecdsa_p256-cert.pub");
/// Security Key (FIDO/U2F) Ed25519 OpenSSH Certificate
const SK_ED25519_CERT_EXAMPLE: &str = include_str!("examples/id_sk_ed25519-cert.pub");
/// Example certificate authority fingerprint (matches `id_ed25519.pub` example)
#[cfg(feature = "ed25519")]
const CA_FINGERPRINT: &str = "SHA256:UCUiLr7Pjs9wFFJMDByLgc3NrtdU344OgUM45wZPcIQ";
/// Valid certificate timestamp.
#[cfg(feature = "ed25519")]
const VALID_TIMESTAMP: u64 = 1750000000;
/// Timestamp which is before the validity window.
#[cfg(feature = "ed25519")]
const PAST_TIMESTAMP: u64 = 1500000000;
/// Expired certificate timestamp.
#[cfg(feature = "ed25519")]
const EXPIRED_TIMESTAMP: u64 = 2500000000;
#[test]
fn decode_dsa_openssh() {
let cert = Certificate::from_str(DSA_CERT_EXAMPLE).unwrap();
assert_eq!(Algorithm::Dsa, cert.public_key().algorithm());
let dsa_key = cert.public_key().dsa().unwrap();
assert_eq!(
&hex!(
"00dc3d89250ed9462114cb2c8d4816e3a511aaff1b06b0e01de17c1cb04e581bcab97176471d89fd7ca1817
e3c48e2ccbafd2170f69e8e5c8b6ab69b9c5f45d95e1d9293e965227eee5b879b1123371c21b1db60f14b5e
5c05a4782ceb43a32f449647703063621e7a286bec95b16726c18b5e52383d00b297a6b03489b06068a5"
),
dsa_key.p.as_bytes(),
);
assert_eq!(
&hex!("00891815378597fe42d3fd261fe76df365845bbb87"),
dsa_key.q.as_bytes(),
);
assert_eq!(
&hex!(
"4739b3908a8415466dc7b156fb98ecb71552a170ba0b3b7aa81bd81391de0a7ae7a1b45002dfeadc9225fbc
520a713fe4104a74bed53fd5915da736365afd3f09777bbccfbadf7ac2b087b7f4d95fabe47d72a46e95088
f9cd2a9fbf236b58a6982647f3c00430ad7352d47a25ebbe9477f0c3127da86ad7448644b76de5875c"
),
dsa_key.g.as_bytes(),
);
assert_eq!(
&hex!(
"6042a6b3fd861344cb21ccccd8719e25aa0be0980e79cbabf4877f5ef071f6039770352eac3d4c368f29daf
a57b475c78d44989f16577527e598334be6aae4abd750c36af80489d392697c1f32f3cf3c9a8b99bcddb53d
7a37e1a28fd53d4934131cf41c437c6734d1e04004adcd925b84b3956c30c3a3904eecb31400b0df48"
),
dsa_key.y.as_bytes(),
);
assert_eq!("user@example.com", cert.comment());
}
#[cfg(feature = "ecdsa")]
#[test]
fn decode_ecdsa_p256_openssh() {
let cert = Certificate::from_str(ECDSA_P256_CERT_EXAMPLE).unwrap();
assert_eq!(
Algorithm::Ecdsa {
curve: EcdsaCurve::NistP256
},
cert.public_key().algorithm(),
);
let ecdsa_key = cert.public_key().ecdsa().unwrap();
assert_eq!(EcdsaCurve::NistP256, ecdsa_key.curve());
assert_eq!(
&hex!(
"047c1fd8730ce53457be8d924098ec3648830f92aa8a2363ac656fdd4521fa6313e511f1891b4e9e5aaf8e1
42d06ad15a66a4257f3f051d84e8a0e2f91ba807047"
),
ecdsa_key.as_ref(),
);
assert_eq!("user@example.com", cert.comment());
}
#[test]
fn decode_ed25519_openssh() {
let cert = Certificate::from_str(ED25519_CERT_EXAMPLE).unwrap();
assert_eq!(Algorithm::Ed25519, cert.public_key().algorithm());
assert_eq!(
&hex!("b33eaef37ea2df7caa010defdea34e241f65f1b529a4f43ed14327f5c54aab62"),
cert.public_key().ed25519().unwrap().as_ref(),
);
assert_eq!("user@example.com", cert.comment());
assert_eq!(cert.valid_principals().len(), 1);
assert_eq!(cert.valid_principals()[0], "host.example.com");
}
#[test]
fn decode_ed25519_openssh_with_crit_options() {
let src = "ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIBW/4zLqXWROWmN1sPgdySnH1GUsEFBjFrRwKKw71BoBAAAAIH1MFwI1oRdEifXgBQvWQfCBBtA/Pi8YCUE/I3wXFJo2AAAAAAAAAAAAAAABAAAAA2ZvbwAAAAAAAAAAAAAAAH//////////AAAAIwAAABFoZWxsb0BleGFtcGxlLmNvbQAAAAoAAAAGZm9vYmFyAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIH1MFwI1oRdEifXgBQvWQfCBBtA/Pi8YCUE/I3wXFJo2AAAAUwAAAAtzc2gtZWQyNTUxOQAAAEDRoPdI48KyoaLgaDZsSGs80qBeYQOXBd84CX8GYzFt/L21rxF1EeuPOkgsx7Q39WllXp+FgMMojsHftK/DJHEN";
let cert = Certificate::from_str(src).unwrap();
assert_eq!(Algorithm::Ed25519, cert.public_key().algorithm());
assert_eq!(cert.critical_options().len(), 1);
assert_eq!(
cert.critical_options().get("hello@example.com").unwrap(),
"foobar"
);
let openssh = cert.to_openssh().unwrap();
assert_eq!(openssh, src);
assert_eq!(cert, Certificate::from_str(&openssh).unwrap());
}
#[test]
fn decode_rsa_4096_openssh() {
let cert = Certificate::from_str(RSA_4096_CERT_EXAMPLE).unwrap();
assert_eq!(Algorithm::Rsa { hash: None }, cert.public_key().algorithm());
let rsa_key = cert.public_key().rsa().unwrap();
assert_eq!(&hex!("010001"), rsa_key.e.as_bytes());
assert_eq!(
&hex!(
"00b45911edc6ec5e7d2261a48c46ab889b1858306271123e6f02dc914cf3c0352492e8a6b7a7925added527
e547dcebff6d0c19c0bc9153975199f47f4964ed20f5aceed4e82556b228a0c1fbfaa85e6339ba2ff4094d9
4e2b09d43a3dd68225d0bbc858293cbf167b18d6374ebe79220a633d400176f1f6b46fd626acb252bf294aa
db2acd59626a023a8e5ec53ced8685164c72ca3a2ec646812c6e61ffcba740ff15c054f0691e3a8d52c79c4
4b7c1fc6c9704aed09ee0195bf09c5c5ba1173b7b1179be33fb3711d3b82e98f80521367a84303cb1236ebe
8fc095683420a4de652c071d592759d42a0c9d2e73313cdfb71a071c936659433481a406308820e173b934f
be877d873fec24d31a4d3bb9a3645055ca37bf710e214e5fc250d5964c66f18e4f05a3b93f42aa0753bd044
e45b456c0e62fdcc1fcadef72930dc8a7a96b3e27d8eecea139a00aaf2fe79063ccb78d26d537625bdf0c4c
8a68a04ed6f965eef7a6b1da5d8e26fc57f1047b97e2c594a9e420410977f22d1751b6d9498e8e457034049
3c336bf86563ef03a15bc49b0ba6fe73201f64f0413ddb4d0cc5f6cf43389907e1df29e0cc388040e3371d0
4814140f75cac08079431043222fb91f075d76be55cbe138e3b99a605c561c49dea50e253c8306c4f4f77d9
96f898db64c5d8a0a15c6efa28b0934bf0b6f2b01950d877230fe4401078420fd6dd3"
),
rsa_key.n.as_bytes(),
);
assert_eq!("user@example.com", cert.comment());
}
#[cfg(feature = "ecdsa")]
#[test]
fn decode_sk_ecdsa_p256_openssh() {
let cert = Certificate::from_str(SK_ECDSA_P256_CERT_EXAMPLE).unwrap();
assert_eq!(
Algorithm::SkEcdsaSha2NistP256,
cert.public_key().algorithm()
);
let ecdsa_key = cert.public_key().sk_ecdsa_p256().unwrap();
assert_eq!(
&hex!(
"04810b409d8382f697d72425285a247d6336b2eb9a085236aa9d1e268747ca0e8ee227f17375e944a775392
f1d35842d13f6237574ab03e00e9cc1799ecd8d931e"
),
ecdsa_key.ec_point().as_ref(),
);
assert_eq!("ssh:", ecdsa_key.application());
assert_eq!("user@example.com", cert.comment());
}
#[test]
fn decode_sk_ed25519_openssh() {
let cert = Certificate::from_str(SK_ED25519_CERT_EXAMPLE).unwrap();
assert_eq!(Algorithm::SkEd25519, cert.public_key().algorithm());
let ed25519_key = cert.public_key().sk_ed25519().unwrap();
assert_eq!(
&hex!("2168fe4e4b53cf3adeeeba602f5e50edb5ef441dba884f5119109db2dafdd733"),
ed25519_key.public_key().as_ref(),
);
assert_eq!("ssh:", ed25519_key.application());
assert_eq!("user@example.com", cert.comment());
}
#[test]
fn encode_dsa_openssh() {
let cert = Certificate::from_str(DSA_CERT_EXAMPLE).unwrap();
assert_eq!(DSA_CERT_EXAMPLE.trim_end(), &cert.to_openssh().unwrap());
}
#[cfg(feature = "ecdsa")]
#[test]
fn encode_ecdsa_p256_openssh() {
let cert = Certificate::from_str(ECDSA_P256_CERT_EXAMPLE).unwrap();
assert_eq!(
ECDSA_P256_CERT_EXAMPLE.trim_end(),
&cert.to_openssh().unwrap()
);
}
#[test]
fn encode_ed25519_openssh() {
let cert = Certificate::from_str(ED25519_CERT_EXAMPLE).unwrap();
assert_eq!(ED25519_CERT_EXAMPLE.trim_end(), &cert.to_openssh().unwrap());
}
#[test]
fn encode_rsa_4096_openssh() {
let cert = Certificate::from_str(RSA_4096_CERT_EXAMPLE).unwrap();
assert_eq!(
RSA_4096_CERT_EXAMPLE.trim_end(),
&cert.to_openssh().unwrap()
);
}
#[cfg(feature = "ed25519")]
#[test]
fn verify_ed25519_certificate_signature() {
let cert = Certificate::from_str(ED25519_CERT_EXAMPLE).unwrap();
assert_eq!(Algorithm::Ed25519, cert.signature_key().algorithm());
assert!(cert.verify_signature().is_ok());
}
#[cfg(feature = "ed25519")]
#[test]
fn reject_ed25519_certificate_with_invalid_signature() {
let cert = Certificate::from_str(ED25519_CERT_BADSIG_EXAMPLE).unwrap();
assert!(cert.verify_signature().is_err());
}
#[cfg(feature = "ed25519")]
#[test]
fn validate_certificate() {
let cert = Certificate::from_str(ED25519_CERT_EXAMPLE).unwrap();
let ca = CA_FINGERPRINT.parse().unwrap();
assert!(cert.validate_at(VALID_TIMESTAMP, &[ca]).is_ok());
}
#[cfg(all(feature = "ed25519", feature = "std"))]
#[test]
fn validate_certificate_against_system_clock() {
let cert = Certificate::from_str(ED25519_CERT_EXAMPLE).unwrap();
let ca = CA_FINGERPRINT.parse().unwrap();
assert!(cert.validate(&[ca]).is_ok());
}
#[cfg(feature = "ed25519")]
#[test]
fn reject_certificate_with_invalid_signature() {
let cert = Certificate::from_str(ED25519_CERT_BADSIG_EXAMPLE).unwrap();
let ca = CA_FINGERPRINT.parse().unwrap();
assert!(cert.validate_at(VALID_TIMESTAMP, &[ca]).is_err());
}
#[cfg(feature = "ed25519")]
#[test]
fn reject_certificate_with_untrusted_ca() {
let cert = Certificate::from_str(ED25519_CERT_EXAMPLE).unwrap();
let ca = Certificate::from_str(DSA_CERT_EXAMPLE)
.unwrap()
.public_key()
.fingerprint(Default::default());
assert!(cert.validate_at(VALID_TIMESTAMP, &[ca]).is_err());
}
#[cfg(feature = "ed25519")]
#[test]
fn reject_expired_certificate() {
let cert = Certificate::from_str(ED25519_CERT_EXAMPLE).unwrap();
let ca = CA_FINGERPRINT.parse().unwrap();
assert!(cert.validate_at(EXPIRED_TIMESTAMP, &[ca]).is_err());
}
#[cfg(feature = "ed25519")]
#[test]
fn reject_certificate_with_future_valid_after() {
let cert = Certificate::from_str(ED25519_CERT_EXAMPLE).unwrap();
let ca = CA_FINGERPRINT.parse().unwrap();
assert!(cert.validate_at(PAST_TIMESTAMP, &[ca]).is_err())
}
#[cfg(feature = "p256")]
#[test]
fn verify_p256_certificate_signature() {
let cert = Certificate::from_str(ED25519_CERT_WITH_P256_CA_EXAMPLE).unwrap();
assert_eq!(
Algorithm::Ecdsa {
curve: EcdsaCurve::NistP256
},
cert.signature_key().algorithm()
);
assert!(cert.verify_signature().is_ok());
}
#[cfg(feature = "rsa")]
#[test]
fn verify_rsa_certificate_signature() {
let cert = Certificate::from_str(ED25519_CERT_WITH_RSA_CA_EXAMPLE).unwrap();
assert_eq!(
Algorithm::Rsa { hash: None },
cert.signature_key().algorithm()
);
assert!(cert.verify_signature().is_ok());
assert_eq!(
Algorithm::Rsa {
hash: Some(HashAlg::Sha512)
},
cert.signature().algorithm()
);
}

View File

@@ -0,0 +1,209 @@
//! Certificate builder tests.
#![cfg(all(
feature = "alloc",
feature = "rand_core",
any(feature = "ed25519", feature = "p256")
))]
use hex_literal::hex;
use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
use ssh_key::{certificate, Algorithm, PrivateKey};
#[cfg(feature = "p256")]
use ssh_key::EcdsaCurve;
#[cfg(all(feature = "ed25519", feature = "rsa"))]
use std::str::FromStr;
#[cfg(all(feature = "ed25519", feature = "std"))]
use std::time::{Duration, SystemTime};
/// Example Unix timestamp when a certificate was issued (2020-09-13 12:26:40 UTC).
const ISSUED_AT: u64 = 1600000000;
/// Example Unix timestamp when a certificate is valid (2022-04-15 05:20:00 UTC).
const VALID_AT: u64 = 1650000000;
/// Example Unix timestamp when a certificate expires (2023-11-14 22:13:20 UTC).
const EXPIRES_AT: u64 = 1700000000;
/// Seed to use for PRNG.
const PRNG_SEED: [u8; 32] = [42; 32];
#[cfg(feature = "ed25519")]
#[test]
fn ed25519_sign_and_verify() {
const SERIAL: u64 = 42;
const KEY_ID: &str = "example";
const PRINCIPAL: &str = "nobody";
const CRITICAL_EXTENSION_1: (&str, &str) = ("critical name 1", "critical data 2");
const CRITICAL_EXTENSION_2: (&str, &str) = ("critical name 2", "critical data 2");
const EXTENSION_1: (&str, &str) = ("extension name 1", "extension data 1");
const EXTENSION_2: (&str, &str) = ("extension name 2", "extension data 2");
const COMMENT: &str = "user@example.com";
let mut rng = ChaCha8Rng::from_seed(PRNG_SEED);
let ca_key = PrivateKey::random(&mut rng, Algorithm::Ed25519).unwrap();
let subject_key = PrivateKey::random(&mut rng, Algorithm::Ed25519).unwrap();
let mut cert_builder = certificate::Builder::new_with_random_nonce(
&mut rng,
subject_key.public_key(),
ISSUED_AT,
EXPIRES_AT,
)
.unwrap();
cert_builder.serial(SERIAL).unwrap();
cert_builder.key_id(KEY_ID).unwrap();
cert_builder.valid_principal(PRINCIPAL).unwrap();
cert_builder
.critical_option(CRITICAL_EXTENSION_1.0, CRITICAL_EXTENSION_1.1)
.unwrap();
cert_builder
.critical_option(CRITICAL_EXTENSION_2.0, CRITICAL_EXTENSION_2.1)
.unwrap();
cert_builder
.extension(EXTENSION_1.0, EXTENSION_1.1)
.unwrap();
cert_builder
.extension(EXTENSION_2.0, EXTENSION_2.1)
.unwrap();
cert_builder.comment(COMMENT).unwrap();
let cert = cert_builder.sign(&ca_key).unwrap();
assert_eq!(cert.algorithm(), Algorithm::Ed25519);
assert_eq!(cert.nonce(), &hex!("321fdf7e0a2afe803308f394f54c6abe"));
assert_eq!(cert.public_key(), subject_key.public_key().key_data());
assert_eq!(cert.serial(), SERIAL);
assert_eq!(cert.cert_type(), certificate::CertType::User);
assert_eq!(cert.key_id(), KEY_ID);
assert_eq!(cert.valid_principals().len(), 1);
assert_eq!(cert.valid_principals()[0], PRINCIPAL);
assert_eq!(cert.valid_after(), ISSUED_AT);
assert_eq!(cert.valid_before(), EXPIRES_AT);
assert_eq!(cert.critical_options().len(), 2);
assert_eq!(
cert.critical_options().get(CRITICAL_EXTENSION_1.0).unwrap(),
CRITICAL_EXTENSION_1.1
);
assert_eq!(cert.extensions().get(EXTENSION_2.0).unwrap(), EXTENSION_2.1);
assert_eq!(cert.extensions().len(), 2);
assert_eq!(cert.extensions().get(EXTENSION_1.0).unwrap(), EXTENSION_1.1);
assert_eq!(cert.extensions().get(EXTENSION_2.0).unwrap(), EXTENSION_2.1);
assert_eq!(cert.signature_key(), ca_key.public_key().key_data());
assert_eq!(cert.comment(), COMMENT);
let ca_fingerprint = ca_key.fingerprint(Default::default());
assert!(cert.validate_at(VALID_AT, &[ca_fingerprint]).is_ok());
}
#[cfg(feature = "p256")]
#[test]
fn ecdsa_nistp256_sign_and_verify() {
let mut rng = ChaCha8Rng::from_seed(PRNG_SEED);
let algorithm = Algorithm::Ecdsa {
curve: EcdsaCurve::NistP256,
};
let ca_key = PrivateKey::random(&mut rng, algorithm.clone()).unwrap();
let subject_key = PrivateKey::random(&mut rng, algorithm.clone()).unwrap();
let mut cert_builder = certificate::Builder::new_with_random_nonce(
&mut rng,
subject_key.public_key(),
ISSUED_AT,
EXPIRES_AT,
)
.unwrap();
cert_builder.all_principals_valid().unwrap();
let cert = cert_builder.sign(&ca_key).unwrap();
assert_eq!(cert.algorithm(), algorithm);
assert_eq!(cert.nonce(), &hex!("321fdf7e0a2afe803308f394f54c6abe"));
assert_eq!(cert.public_key(), subject_key.public_key().key_data());
assert_eq!(cert.signature_key(), ca_key.public_key().key_data());
let ca_fingerprint = ca_key.fingerprint(Default::default());
assert!(cert.validate_at(VALID_AT, &[ca_fingerprint]).is_ok());
}
#[cfg(all(feature = "ed25519", feature = "rsa"))]
#[test]
fn rsa_sign_and_verify() {
let ca_key = PrivateKey::from_str(
r#"-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAQEAyng6J3IE5++Ji7EfVNTANDnhYH46LnZW+bwW45etzKswQkc/AvSA
9ih2VAhE8FFUR0Z6pyl4hEn/878x50pGt1FHplbbe4wZ5aornT1hcGGYy313Glt+zyn96M
BTAjO0yULa1RrhBBmeY3yXIEAApUIVdvxcLOvJgltSFmFURtbY5cZkweuspwnHBE/JUPBX
9/Njb+z2R4BTnf0UrudxRKA/TJx9mL3Pb2JjkXfQ07pZqp+oEiUoGMvdfN9vYW4J5LTbXo
n20kRt5UKSxKggBBa0rzGabF+P/BTd39ZrI27WRYhDAzeYJoLq/xfO6qCgAM3TKxe0tDeT
gV4akFJ9CwAAA7hN/dPaTf3T2gAAAAdzc2gtcnNhAAABAQDKeDoncgTn74mLsR9U1MA0Oe
Fgfjoudlb5vBbjl63MqzBCRz8C9ID2KHZUCETwUVRHRnqnKXiESf/zvzHnSka3UUemVtt7
jBnlqiudPWFwYZjLfXcaW37PKf3owFMCM7TJQtrVGuEEGZ5jfJcgQAClQhV2/Fws68mCW1
IWYVRG1tjlxmTB66ynCccET8lQ8Ff382Nv7PZHgFOd/RSu53FEoD9MnH2Yvc9vYmORd9DT
ulmqn6gSJSgYy918329hbgnktNteifbSRG3lQpLEqCAEFrSvMZpsX4/8FN3f1msjbtZFiE
MDN5gmgur/F87qoKAAzdMrF7S0N5OBXhqQUn0LAAAAAwEAAQAAAQAxxSgWdjK6iOl4y0t2
YO32aJv8SksnDLQIo7HEtI5ml1Y/lJ/qrAvfdsbPlVDM+lELTEnuOYWEj2Q5mLA9uMZ1Xa
eNPiCp2CCtkg0yk9oV9AfJTcgvVHpxllLyGgTNr8QrDSIZ7IePqHSE5CWKKfF+riX0n8hQ
yo04XBZrpfU/jDQV8ENKiNQd3Aiy6ppSbnDhyTzZEYIxtvnh1FmvU0Ct1jQRd8p42gurEn
sq6nAPE9pnn0otKmjRdfGCnM9X/ZbUcaUcU/X8pPYG1pW0GZR7eTO+1f9s8TS5LIqz2Eru
L4gBQweASh9mhatsMqJX/ZRrdHvdIuH8N1VDSahf1ZTxAAAAgF1+qA6ZVBEaoCj+fAJZyU
EYf7NMI/nPqEVxiIjg4WKmRYKC9Pb9cuGehOs/XTi3KMEHzYJIKT1K+uO0OG025XVH06qk
9qyWcBwtRbCPVFJPSkKyGBPaUIxMI07x1+434vig6z7iwVROxy3vyhslgiJNpIkaWVUhQN
EGEHX0oWLfAAAAgQDLd25QLAb1kngTsuwQ+xo3S6UcQvOTiDnVRvxWPaW4yn/3qO55+esd
dzxUujFXhUO/POeUJiHv0B1QlDm/sHYL6YVI5+XRaWAst/z0T93mM4ts63Z1OoJbAtE5qH
yGlKVPQ5ZG8SUVElbX+SZE2CcnsPx53trW8qQu/R2bPdDN7QAAAIEA/r7nlgz6D93vMVkn
wq38d49h+PTfyBQ1bum8AhxCEfTaK94YrH9BeizO6Ma5MIjY6WHWbq7Co93J3fl8f4eTCo
CpHJYWfbBqrf/5PUoOIjdMdfFHK6GpUCQNxhbSpnL4l75sxrhkEXtBHVKRXCNR5T4JnOcx
R6qbyo6hPuCiV9cAAAAAAQID
-----END OPENSSH PRIVATE KEY-----"#,
)
.unwrap();
let mut rng = ChaCha8Rng::from_seed(PRNG_SEED);
let subject_key = PrivateKey::random(&mut rng, Algorithm::Ed25519).unwrap();
let mut cert_builder = certificate::Builder::new_with_random_nonce(
&mut rng,
subject_key.public_key(),
ISSUED_AT,
EXPIRES_AT,
)
.unwrap();
cert_builder.all_principals_valid().unwrap();
let cert = cert_builder.sign(&ca_key).unwrap();
assert_eq!(
cert.signature_key().algorithm(),
Algorithm::Rsa { hash: None }
);
assert_eq!(cert.nonce(), &hex!("55742ecb25ee56057b9e35eae54c40a9"));
assert_eq!(cert.public_key(), subject_key.public_key().key_data());
assert_eq!(cert.signature_key(), ca_key.public_key().key_data());
let ca_fingerprint = ca_key.fingerprint(Default::default());
assert!(cert.validate_at(VALID_AT, &[ca_fingerprint]).is_ok());
}
#[cfg(all(feature = "ed25519", feature = "std"))]
#[test]
fn new_with_validity_times() {
let mut rng = ChaCha8Rng::from_seed(PRNG_SEED);
let subject_key = PrivateKey::random(&mut rng, Algorithm::Ed25519).unwrap();
// NOTE: use a random nonce, not an all-zero one!
let nonce = [0u8; certificate::Builder::RECOMMENDED_NONCE_SIZE];
let issued_at = SystemTime::now();
let expires_at = issued_at + Duration::from_secs(3600);
assert!(certificate::Builder::new_with_validity_times(
nonce,
subject_key.public_key(),
issued_at,
expires_at
)
.is_ok());
}

View File

@@ -0,0 +1,495 @@
//! Encrypted SSH private key tests.
#![cfg(feature = "alloc")]
use hex_literal::hex;
use ssh_key::{Algorithm, Cipher, Kdf, KdfAlg, PrivateKey};
/// Unencrypted Ed25519 OpenSSH-formatted private key.
#[cfg(feature = "encryption")]
const OPENSSH_ED25519_EXAMPLE: &str = include_str!("examples/id_ed25519");
/// AES128-CBC encrypted Ed25519 OpenSSH-formatted private key.
///
/// Plaintext is `OPENSSH_ED25519_EXAMPLE`.
#[cfg(feature = "encryption")]
const OPENSSH_AES128_CBC_ED25519_EXAMPLE: &str = include_str!("examples/id_ed25519.aes128-cbc.enc");
/// AES192-CBC encrypted Ed25519 OpenSSH-formatted private key.
///
/// Plaintext is `OPENSSH_ED25519_EXAMPLE`.
#[cfg(feature = "encryption")]
const OPENSSH_AES192_CBC_ED25519_EXAMPLE: &str = include_str!("examples/id_ed25519.aes192-cbc.enc");
/// AES256-CBC encrypted Ed25519 OpenSSH-formatted private key.
///
/// Plaintext is `OPENSSH_ED25519_EXAMPLE`.
#[cfg(feature = "encryption")]
const OPENSSH_AES256_CBC_ED25519_EXAMPLE: &str = include_str!("examples/id_ed25519.aes256-cbc.enc");
/// AES128-CTR encrypted Ed25519 OpenSSH-formatted private key.
///
/// Plaintext is `OPENSSH_ED25519_EXAMPLE`.
#[cfg(feature = "encryption")]
const OPENSSH_AES128_CTR_ED25519_EXAMPLE: &str = include_str!("examples/id_ed25519.aes128-ctr.enc");
/// AES192-CTR encrypted Ed25519 OpenSSH-formatted private key.
///
/// Plaintext is `OPENSSH_ED25519_EXAMPLE`.
#[cfg(feature = "encryption")]
const OPENSSH_AES192_CTR_ED25519_EXAMPLE: &str = include_str!("examples/id_ed25519.aes192-ctr.enc");
/// AES256-CTR encrypted Ed25519 OpenSSH-formatted private key.
///
/// Plaintext is `OPENSSH_ED25519_EXAMPLE`.
const OPENSSH_AES256_CTR_ED25519_EXAMPLE: &str = include_str!("examples/id_ed25519.aes256-ctr.enc");
/// AES256-GCM encrypted Ed25519 OpenSSH-formatted private key.
///
/// Plaintext is `OPENSSH_ED25519_EXAMPLE`.
#[cfg(feature = "encryption")]
const OPENSSH_AES128_GCM_ED25519_EXAMPLE: &str = include_str!("examples/id_ed25519.aes128-gcm.enc");
/// AES256-GCM encrypted Ed25519 OpenSSH-formatted private key.
///
/// Plaintext is `OPENSSH_ED25519_EXAMPLE`.
const OPENSSH_AES256_GCM_ED25519_EXAMPLE: &str = include_str!("examples/id_ed25519.aes256-gcm.enc");
/// ChaCha20-Poly1305 encrypted Ed25519 OpenSSH-formatted private key.
///
/// Plaintext is `OPENSSH_ED25519_EXAMPLE`.
const OPENSSH_CHACHA20_POLY1305_ED25519_EXAMPLE: &str =
include_str!("examples/id_ed25519.chacha20-poly1305.enc");
/// TripleDES-CBC encrypted Ed25519 OpenSSH-formatted private key.
///
/// Plaintext is `OPENSSH_ED25519_EXAMPLE`.
const OPENSSH_3DES_CBC_ED25519_EXAMPLE: &str = include_str!("examples/id_ed25519.3des-cbc.enc");
/// Bad password; don't actually use outside tests!
#[cfg(feature = "encryption")]
const PASSWORD: &[u8] = b"hunter42";
#[test]
fn decode_openssh_aes256_ctr() {
let key = PrivateKey::from_openssh(OPENSSH_AES256_CTR_ED25519_EXAMPLE).unwrap();
assert_eq!(Algorithm::Ed25519, key.algorithm());
assert_eq!(Cipher::Aes256Ctr, key.cipher());
assert_eq!(KdfAlg::Bcrypt, key.kdf().algorithm());
match key.kdf() {
Kdf::Bcrypt { salt, rounds } => {
assert_eq!(salt, &hex!("4a1fdeae8d6ba607afd69d334f8d379a"));
assert_eq!(*rounds, 16);
}
other => panic!("unexpected KDF algorithm: {:?}", other),
}
assert_eq!(
&hex!("b33eaef37ea2df7caa010defdea34e241f65f1b529a4f43ed14327f5c54aab62"),
key.public_key().key_data().ed25519().unwrap().as_ref(),
);
}
#[test]
fn decode_openssh_aes256_gcm() {
let key = PrivateKey::from_openssh(OPENSSH_AES256_GCM_ED25519_EXAMPLE).unwrap();
assert_eq!(Algorithm::Ed25519, key.algorithm());
assert_eq!(Cipher::Aes256Gcm, key.cipher());
assert_eq!(KdfAlg::Bcrypt, key.kdf().algorithm());
match key.kdf() {
Kdf::Bcrypt { salt, rounds } => {
assert_eq!(salt, &hex!("11bdc133ef64644115b176917e47cbaf"));
assert_eq!(*rounds, 16);
}
other => panic!("unexpected KDF algorithm: {:?}", other),
}
assert_eq!(
&hex!("b33eaef37ea2df7caa010defdea34e241f65f1b529a4f43ed14327f5c54aab62"),
key.public_key().key_data().ed25519().unwrap().as_ref(),
);
}
#[test]
fn decode_openssh_chacha20_poly1305() {
let key = PrivateKey::from_openssh(OPENSSH_CHACHA20_POLY1305_ED25519_EXAMPLE).unwrap();
assert_eq!(Algorithm::Ed25519, key.algorithm());
assert_eq!(Cipher::ChaCha20Poly1305, key.cipher());
assert_eq!(KdfAlg::Bcrypt, key.kdf().algorithm());
match key.kdf() {
Kdf::Bcrypt { salt, rounds } => {
assert_eq!(salt, &hex!("f651ca3efb15904d05c216a5041ea89a"));
assert_eq!(*rounds, 16);
}
other => panic!("unexpected KDF algorithm: {:?}", other),
}
assert_eq!(
&hex!("b33eaef37ea2df7caa010defdea34e241f65f1b529a4f43ed14327f5c54aab62"),
key.public_key().key_data().ed25519().unwrap().as_ref(),
);
}
#[test]
fn decode_openssh_3des_cbc() {
let key = PrivateKey::from_openssh(OPENSSH_3DES_CBC_ED25519_EXAMPLE).unwrap();
assert_eq!(Algorithm::Ed25519, key.algorithm());
assert_eq!(Cipher::TDesCbc, key.cipher());
assert_eq!(KdfAlg::Bcrypt, key.kdf().algorithm());
match key.kdf() {
Kdf::Bcrypt { salt, rounds } => {
assert_eq!(salt, &hex!("1afcebea3c598c277e7edc2b78db1e94"));
assert_eq!(*rounds, 16);
}
other => panic!("unexpected KDF algorithm: {:?}", other),
}
assert_eq!(
&hex!("b33eaef37ea2df7caa010defdea34e241f65f1b529a4f43ed14327f5c54aab62"),
key.public_key().key_data().ed25519().unwrap().as_ref(),
);
}
#[cfg(feature = "encryption")]
#[test]
fn decrypt_openssh_aes128_ctr() {
let key_enc = PrivateKey::from_openssh(OPENSSH_AES128_CTR_ED25519_EXAMPLE).unwrap();
assert_eq!(Cipher::Aes128Ctr, key_enc.cipher());
let key_dec = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(
PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap(),
key_dec
);
}
#[cfg(feature = "encryption")]
#[test]
fn decrypt_openssh_aes192_ctr() {
let key_enc = PrivateKey::from_openssh(OPENSSH_AES192_CTR_ED25519_EXAMPLE).unwrap();
assert_eq!(Cipher::Aes192Ctr, key_enc.cipher());
let key_dec = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(
PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap(),
key_dec
);
}
#[cfg(feature = "encryption")]
#[test]
fn decrypt_openssh_aes256_ctr() {
let key_enc = PrivateKey::from_openssh(OPENSSH_AES256_CTR_ED25519_EXAMPLE).unwrap();
assert_eq!(Cipher::Aes256Ctr, key_enc.cipher());
let key_dec = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(
PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap(),
key_dec
);
}
#[cfg(feature = "encryption")]
#[test]
fn decrypt_openssh_aes128_cbc() {
let key_enc = PrivateKey::from_openssh(OPENSSH_AES128_CBC_ED25519_EXAMPLE).unwrap();
assert_eq!(Cipher::Aes128Cbc, key_enc.cipher());
let key_dec = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(
PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap(),
key_dec
);
}
#[cfg(feature = "encryption")]
#[test]
fn decrypt_openssh_aes192_cbc() {
let key_enc = PrivateKey::from_openssh(OPENSSH_AES192_CBC_ED25519_EXAMPLE).unwrap();
assert_eq!(Cipher::Aes192Cbc, key_enc.cipher());
let key_dec = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(
PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap(),
key_dec
);
}
#[cfg(feature = "encryption")]
#[test]
fn decrypt_openssh_aes256_cbc() {
let key_enc = PrivateKey::from_openssh(OPENSSH_AES256_CBC_ED25519_EXAMPLE).unwrap();
assert_eq!(Cipher::Aes256Cbc, key_enc.cipher());
let key_dec = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(
PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap(),
key_dec
);
}
#[cfg(feature = "encryption")]
#[test]
fn decrypt_openssh_aes128_gcm() {
let key_enc = PrivateKey::from_openssh(OPENSSH_AES128_GCM_ED25519_EXAMPLE).unwrap();
assert_eq!(Cipher::Aes128Gcm, key_enc.cipher());
let key_dec = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(
PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap(),
key_dec
);
}
#[cfg(feature = "encryption")]
#[test]
fn decrypt_openssh_aes256_gcm() {
let key_enc = PrivateKey::from_openssh(OPENSSH_AES256_GCM_ED25519_EXAMPLE).unwrap();
assert_eq!(Cipher::Aes256Gcm, key_enc.cipher());
let key_dec = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(
PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap(),
key_dec
);
}
#[cfg(feature = "encryption")]
#[test]
fn decrypt_openssh_chacha20_poly1305() {
let key_enc = PrivateKey::from_openssh(OPENSSH_CHACHA20_POLY1305_ED25519_EXAMPLE).unwrap();
assert_eq!(Cipher::ChaCha20Poly1305, key_enc.cipher());
let key_dec = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(
PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap(),
key_dec
);
}
#[cfg(feature = "tdes")]
#[test]
fn decrypt_openssh_3des() {
let key_enc = PrivateKey::from_openssh(OPENSSH_3DES_CBC_ED25519_EXAMPLE).unwrap();
assert_eq!(Cipher::TDesCbc, key_enc.cipher());
let key_dec = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(
PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap(),
key_dec
);
}
#[test]
fn encode_openssh_aes256_ctr() {
let key = PrivateKey::from_openssh(OPENSSH_AES256_CTR_ED25519_EXAMPLE).unwrap();
assert_eq!(
OPENSSH_AES256_CTR_ED25519_EXAMPLE.trim_end(),
key.to_openssh(Default::default()).unwrap().trim_end()
);
}
#[test]
fn encode_openssh_aes256_gcm() {
let key = PrivateKey::from_openssh(OPENSSH_AES256_GCM_ED25519_EXAMPLE).unwrap();
assert_eq!(
OPENSSH_AES256_GCM_ED25519_EXAMPLE.trim_end(),
key.to_openssh(Default::default()).unwrap().trim_end()
);
}
#[cfg(all(feature = "encryption", feature = "getrandom"))]
#[test]
fn encrypt_openssh_aes128_cbc() {
use rand_core::OsRng;
let key_dec = PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
let key_enc = key_dec
.encrypt_with_cipher(&mut OsRng, Cipher::Aes128Cbc, PASSWORD)
.unwrap();
// Ensure encrypted key round trips through encoder/decoder
let key_enc_str = key_enc.to_openssh(Default::default()).unwrap();
let key_enc2 = PrivateKey::from_openssh(&*key_enc_str).unwrap();
assert_eq!(key_enc, key_enc2);
// Ensure decrypted key matches the original
let key_dec2 = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(key_dec, key_dec2);
}
#[cfg(all(feature = "encryption", feature = "getrandom"))]
#[test]
fn encrypt_openssh_aes192_cbc() {
use rand_core::OsRng;
let key_dec = PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
let key_enc = key_dec
.encrypt_with_cipher(&mut OsRng, Cipher::Aes192Cbc, PASSWORD)
.unwrap();
// Ensure encrypted key round trips through encoder/decoder
let key_enc_str = key_enc.to_openssh(Default::default()).unwrap();
let key_enc2 = PrivateKey::from_openssh(&*key_enc_str).unwrap();
assert_eq!(key_enc, key_enc2);
// Ensure decrypted key matches the original
let key_dec2 = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(key_dec, key_dec2);
}
#[cfg(all(feature = "encryption", feature = "getrandom"))]
#[test]
fn encrypt_openssh_aes256_cbc() {
use rand_core::OsRng;
let key_dec = PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
let key_enc = key_dec
.encrypt_with_cipher(&mut OsRng, Cipher::Aes256Cbc, PASSWORD)
.unwrap();
// Ensure encrypted key round trips through encoder/decoder
let key_enc_str = key_enc.to_openssh(Default::default()).unwrap();
let key_enc2 = PrivateKey::from_openssh(&*key_enc_str).unwrap();
assert_eq!(key_enc, key_enc2);
// Ensure decrypted key matches the original
let key_dec2 = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(key_dec, key_dec2);
}
#[cfg(all(feature = "encryption", feature = "getrandom"))]
#[test]
fn encrypt_openssh_aes128_ctr() {
use rand_core::OsRng;
let key_dec = PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
let key_enc = key_dec
.encrypt_with_cipher(&mut OsRng, Cipher::Aes128Ctr, PASSWORD)
.unwrap();
// Ensure encrypted key round trips through encoder/decoder
let key_enc_str = key_enc.to_openssh(Default::default()).unwrap();
let key_enc2 = PrivateKey::from_openssh(&*key_enc_str).unwrap();
assert_eq!(key_enc, key_enc2);
// Ensure decrypted key matches the original
let key_dec2 = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(key_dec, key_dec2);
}
#[cfg(all(feature = "encryption", feature = "getrandom"))]
#[test]
fn encrypt_openssh_aes192_ctr() {
use rand_core::OsRng;
let key_dec = PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
let key_enc = key_dec
.encrypt_with_cipher(&mut OsRng, Cipher::Aes192Ctr, PASSWORD)
.unwrap();
// Ensure encrypted key round trips through encoder/decoder
let key_enc_str = key_enc.to_openssh(Default::default()).unwrap();
let key_enc2 = PrivateKey::from_openssh(&*key_enc_str).unwrap();
assert_eq!(key_enc, key_enc2);
// Ensure decrypted key matches the original
let key_dec2 = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(key_dec, key_dec2);
}
#[cfg(all(feature = "encryption", feature = "getrandom"))]
#[test]
fn encrypt_openssh_aes256_ctr() {
use rand_core::OsRng;
let key_dec = PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
let key_enc = key_dec.encrypt(&mut OsRng, PASSWORD).unwrap();
// Ensure encrypted key round trips through encoder/decoder
let key_enc_str = key_enc.to_openssh(Default::default()).unwrap();
let key_enc2 = PrivateKey::from_openssh(&*key_enc_str).unwrap();
assert_eq!(key_enc, key_enc2);
// Ensure decrypted key matches the original
let key_dec2 = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(key_dec, key_dec2);
}
#[cfg(all(feature = "encryption", feature = "getrandom"))]
#[test]
fn encrypt_openssh_aes128_gcm() {
use rand_core::OsRng;
let key_dec = PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
let key_enc = key_dec
.encrypt_with_cipher(&mut OsRng, Cipher::Aes128Gcm, PASSWORD)
.unwrap();
// Ensure encrypted key round trips through encoder/decoder
let key_enc_str = key_enc.to_openssh(Default::default()).unwrap();
let key_enc2 = PrivateKey::from_openssh(&*key_enc_str).unwrap();
assert_eq!(key_enc, key_enc2);
// Ensure decrypted key matches the original
let key_dec2 = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(key_dec, key_dec2);
}
#[cfg(all(feature = "encryption", feature = "getrandom"))]
#[test]
fn encrypt_openssh_aes256_gcm() {
use rand_core::OsRng;
let key_dec = PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
let key_enc = key_dec
.encrypt_with_cipher(&mut OsRng, Cipher::Aes256Gcm, PASSWORD)
.unwrap();
// Ensure encrypted key round trips through encoder/decoder
let key_enc_str = key_enc.to_openssh(Default::default()).unwrap();
let key_enc2 = PrivateKey::from_openssh(&*key_enc_str).unwrap();
assert_eq!(key_enc, key_enc2);
// Ensure decrypted key matches the original
let key_dec2 = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(key_dec, key_dec2);
}
#[cfg(all(feature = "encryption", feature = "getrandom"))]
#[test]
fn encrypt_openssh_chacha20_poly1305() {
use rand_core::OsRng;
let key_dec = PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
let key_enc = key_dec
.encrypt_with_cipher(&mut OsRng, Cipher::ChaCha20Poly1305, PASSWORD)
.unwrap();
// Ensure encrypted key round trips through encoder/decoder
let key_enc_str = key_enc.to_openssh(Default::default()).unwrap();
let key_enc2 = PrivateKey::from_openssh(&*key_enc_str).unwrap();
assert_eq!(key_enc, key_enc2);
// Ensure decrypted key matches the original
let key_dec2 = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(key_dec, key_dec2);
}
#[cfg(all(feature = "tdes", feature = "getrandom"))]
#[test]
fn encrypt_openssh_3des() {
use rand_core::OsRng;
let key_dec = PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
let key_enc = key_dec
.encrypt_with_cipher(&mut OsRng, Cipher::TDesCbc, PASSWORD)
.unwrap();
// Ensure encrypted key round trips through encoder/decoder
let key_enc_str = key_enc.to_openssh(Default::default()).unwrap();
let key_enc2 = PrivateKey::from_openssh(&*key_enc_str).unwrap();
assert_eq!(key_enc, key_enc2);
// Ensure decrypted key matches the original
let key_dec2 = key_enc.decrypt(PASSWORD).unwrap();
assert_eq!(key_dec, key_dec2);
}

View File

@@ -0,0 +1,31 @@
# Example authorized keys file
#
# - Comments in these files begin with `#`
# - They can also contain blank lines
# - Lines which are not blank each contain a single public key
# - Maximum line length is 8 kilobytes
#
# Public keys consist of the following space-separated fields:
#
# options, keytype, base64-encoded key, comment
#
# - The options field is optional.
# - The keytype is `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`,
# `ssh-ed25519`, `ssh-dss` or `ssh-rsa`
# - The comment field is not used for anything (but may be convenient for the user to
# identify the key).
# Public key with no options and no comment
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqti
# Public key which can only read the current date
command="/usr/bin/date" ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHwf2HMM5TRXvo2SQJjsNkiDD5KqiiNjrGVv3UUh+mMT5RHxiRtOnlqvjhQtBq0VpmpCV/PwUdhOig4vkbqAcEc= user2@example.com
# Public key which ensures a certain environment is set
environment="PATH=/bin:/usr/bin" ssh-dss AAAAB3NzaC1kc3MAAACBANw9iSUO2UYhFMssjUgW46URqv8bBrDgHeF8HLBOWBvKuXF2Rx2J/XyhgX48SOLMuv0hcPaejlyLarabnF9F2V4dkpPpZSJ+7luHmxEjNxwhsdtg8UteXAWkeCzrQ6MvRJZHcDBjYh56KGvslbFnJsGLXlI4PQCyl6awNImwYGilAAAAFQCJGBU3hZf+QtP9Jh/nbfNlhFu7hwAAAIBHObOQioQVRm3HsVb7mOy3FVKhcLoLO3qoG9gTkd4KeuehtFAC3+rckiX7xSCnE/5BBKdL7VP9WRXac2Nlr9Pwl3e7zPut96wrCHt/TZX6vkfXKkbpUIj5zSqfvyNrWKaYJkfzwAQwrXNS1Hol676Ud/DDEn2oatdEhkS3beWHXAAAAIBgQqaz/YYTRMshzMzYcZ4lqgvgmA55y6v0h39e8HH2A5dwNS6sPUw2jyna+le0dceNRJifFld1J+WYM0vmquSr11DDavgEidOSaXwfMvPPPJqLmbzdtT16N+Gij9U9STQTHPQcQ3xnNNHgQAStzZJbhLOVbDDDo5BO7LMUALDfSA== user3@example.com
# Public key which can only be used from certain source addresses and disallows X11 forwarding
from="10.0.0.?,*.example.com",no-X11-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC0WRHtxuxefSJhpIxGq4ibGFgwYnESPm8C3JFM88A1JJLoprenklrd7VJ+VH3Ov/bQwZwLyRU5dRmfR/SWTtIPWs7tToJVayKKDB+/qoXmM5ui/0CU2U4rCdQ6PdaCJdC7yFgpPL8WexjWN06+eSIKYz1AAXbx9rRv1iasslK/KUqtsqzVliagI6jl7FPO2GhRZMcso6LsZGgSxuYf/Lp0D/FcBU8GkeOo1Sx5xEt8H8bJcErtCe4Blb8JxcW6EXO3sReb4z+zcR07gumPgFITZ6hDA8sSNuvo/AlWg0IKTeZSwHHVknWdQqDJ0uczE837caBxyTZllDNIGkBjCIIOFzuTT76HfYc/7CTTGk07uaNkUFXKN79xDiFOX8JQ1ZZMZvGOTwWjuT9CqgdTvQRORbRWwOYv3MH8re9ykw3Ip6lrPifY7s6hOaAKry/nkGPMt40m1TdiW98MTIpooE7W+WXu96ax2l2OJvxX8QR7l+LFlKnkIEEJd/ItF1G22UmOjkVwNASTwza/hlY+8DoVvEmwum/nMgH2TwQT3bTQzF9s9DOJkH4d8p4Mw4gEDjNx0EgUFA91ysCAeUMQQyIvuR8HXXa+VcvhOOO5mmBcVhxJ3qUOJTyDBsT0932Zb4mNtkxdigoVxu+iiwk0vwtvKwGVDYdyMP5EAQeEIP1t0w== user4@example.com
# Public key with a comment that contains multiple spaces
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN76zuqnjypL54/w4763l7q1Sn3IBYHptJ5wcYfEWkzeNTvpexr05Z18m2yPT2SWRd1JJ8Aj5TYidG9MdSS5J78= hello world this is a long comment

14
vendor/ssh-key/tests/examples/generate.sh vendored Executable file
View File

@@ -0,0 +1,14 @@
# Generator script for test cases
#
# This shouldn't ever need to be run again, but automates and documents how the
# test vectors in this directory were created.
set -eux
ssh-keygen -t dsa -f id_dsa_1024 -C user@example.com
ssh-keygen -t ecdsa -b 256 -f id_ecdsa_p256 -C user@example.com
ssh-keygen -t ecdsa -b 384 -f id_ecdsa_p384 -C user@example.com
ssh-keygen -t ecdsa -b 521 -f id_ecdsa_p521 -C user@example.com
ssh-keygen -t ed25519 -f id_ed25519 -C user@example.com
ssh-keygen -t rsa -b 3072 -f id_rsa_3072 -C user@example.com
ssh-keygen -t rsa -b 4096 -f id_rsa_4096 -C user@example.com

View File

@@ -0,0 +1,21 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsQAAAAdzc2gtZH
NzAAAAgQDcPYklDtlGIRTLLI1IFuOlEar/Gwaw4B3hfBywTlgbyrlxdkcdif18oYF+PEji
zLr9IXD2no5ci2q2m5xfRdleHZKT6WUifu5bh5sRIzccIbHbYPFLXlwFpHgs60OjL0SWR3
AwY2Ieeihr7JWxZybBi15SOD0AspemsDSJsGBopQAAABUAiRgVN4WX/kLT/SYf523zZYRb
u4cAAACARzmzkIqEFUZtx7FW+5jstxVSoXC6Czt6qBvYE5HeCnrnobRQAt/q3JIl+8Ugpx
P+QQSnS+1T/VkV2nNjZa/T8Jd3u8z7rfesKwh7f02V+r5H1ypG6VCI+c0qn78ja1immCZH
88AEMK1zUtR6Jeu+lHfwwxJ9qGrXRIZEt23lh1wAAACAYEKms/2GE0TLIczM2HGeJaoL4J
gOecur9Id/XvBx9gOXcDUurD1MNo8p2vpXtHXHjUSYnxZXdSflmDNL5qrkq9dQw2r4BInT
kml8HzLzzzyai5m83bU9ejfhoo/VPUk0Exz0HEN8ZzTR4EAErc2SW4SzlWwww6OQTuyzFA
Cw30gAAAHo9I0p/vSNKf4AAAAHc3NoLWRzcwAAAIEA3D2JJQ7ZRiEUyyyNSBbjpRGq/xsG
sOAd4XwcsE5YG8q5cXZHHYn9fKGBfjxI4sy6/SFw9p6OXItqtpucX0XZXh2Sk+llIn7uW4
ebESM3HCGx22DxS15cBaR4LOtDoy9ElkdwMGNiHnooa+yVsWcmwYteUjg9ALKXprA0ibBg
aKUAAAAVAIkYFTeFl/5C0/0mH+dt82WEW7uHAAAAgEc5s5CKhBVGbcexVvuY7LcVUqFwug
s7eqgb2BOR3gp656G0UALf6tySJfvFIKcT/kEEp0vtU/1ZFdpzY2Wv0/CXd7vM+633rCsI
e39Nlfq+R9cqRulQiPnNKp+/I2tYppgmR/PABDCtc1LUeiXrvpR38MMSfahq10SGRLdt5Y
dcAAAAgGBCprP9hhNEyyHMzNhxniWqC+CYDnnLq/SHf17wcfYDl3A1Lqw9TDaPKdr6V7R1
x41EmJ8WV3Un5ZgzS+aq5KvXUMNq+ASJ05JpfB8y8888mouZvN21PXo34aKP1T1JNBMc9B
xDfGc00eBABK3NkluEs5VsMMOjkE7ssxQAsN9IAAAAFAw3esRJ53DYmjVXdDy9BQOWEUti
AAAAEHVzZXJAZXhhbXBsZS5jb20BAgM=
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgb6UUNOel9C6CnoLpzrqm3TmZRFmHbkxSmus9tQ35W4UAAACBANw9iSUO2UYhFMssjUgW46URqv8bBrDgHeF8HLBOWBvKuXF2Rx2J/XyhgX48SOLMuv0hcPaejlyLarabnF9F2V4dkpPpZSJ+7luHmxEjNxwhsdtg8UteXAWkeCzrQ6MvRJZHcDBjYh56KGvslbFnJsGLXlI4PQCyl6awNImwYGilAAAAFQCJGBU3hZf+QtP9Jh/nbfNlhFu7hwAAAIBHObOQioQVRm3HsVb7mOy3FVKhcLoLO3qoG9gTkd4KeuehtFAC3+rckiX7xSCnE/5BBKdL7VP9WRXac2Nlr9Pwl3e7zPut96wrCHt/TZX6vkfXKkbpUIj5zSqfvyNrWKaYJkfzwAQwrXNS1Hol676Ud/DDEn2oatdEhkS3beWHXAAAAIBgQqaz/YYTRMshzMzYcZ4lqgvgmA55y6v0h39e8HH2A5dwNS6sPUw2jyna+le0dceNRJifFld1J+WYM0vmquSr11DDavgEidOSaXwfMvPPPJqLmbzdtT16N+Gij9U9STQTHPQcQ3xnNNHgQAStzZJbhLOVbDDDo5BO7LMUALDfSAAAAAAAAAAAAAAAAQAAAANkc2EAAAAAAAAAAGJHj+AAAAAA9NAo4AAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEA9a5kGt2h1rvHnsvHgIHipT0Oa67mkc02hqFGoHiLOAZm7+CA4eo3pyDTJw8x3jZly3L5w9o1TzGvJ4msCtG0E user@example.com

View File

@@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBANw9iSUO2UYhFMssjUgW46URqv8bBrDgHeF8HLBOWBvKuXF2Rx2J/XyhgX48SOLMuv0hcPaejlyLarabnF9F2V4dkpPpZSJ+7luHmxEjNxwhsdtg8UteXAWkeCzrQ6MvRJZHcDBjYh56KGvslbFnJsGLXlI4PQCyl6awNImwYGilAAAAFQCJGBU3hZf+QtP9Jh/nbfNlhFu7hwAAAIBHObOQioQVRm3HsVb7mOy3FVKhcLoLO3qoG9gTkd4KeuehtFAC3+rckiX7xSCnE/5BBKdL7VP9WRXac2Nlr9Pwl3e7zPut96wrCHt/TZX6vkfXKkbpUIj5zSqfvyNrWKaYJkfzwAQwrXNS1Hol676Ud/DDEn2oatdEhkS3beWHXAAAAIBgQqaz/YYTRMshzMzYcZ4lqgvgmA55y6v0h39e8HH2A5dwNS6sPUw2jyna+le0dceNRJifFld1J+WYM0vmquSr11DDavgEidOSaXwfMvPPPJqLmbzdtT16N+Gij9U9STQTHPQcQ3xnNNHgQAStzZJbhLOVbDDDo5BO7LMUALDfSA== user@example.com

View File

@@ -0,0 +1,9 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQR8H9hzDOU0V76NkkCY7DZIgw+Sqooj
Y6xlb91FIfpjE+UR8YkbTp5ar44ULQatFaZqQlfz8FHYTooOL5G6gHBHAAAAsB8RBhUfEQ
YVAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHwf2HMM5TRXvo2S
QJjsNkiDD5KqiiNjrGVv3UUh+mMT5RHxiRtOnlqvjhQtBq0VpmpCV/PwUdhOig4vkbqAcE
cAAAAhAMp4pkd0v643EjIkk38DmJYBiXB6ygqGRc60NZxCO6B5AAAAEHVzZXJAZXhhbXBs
ZS5jb20BAgMEBQYH
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgZBJzVkJPUyTSRHpKR/MzGrek4PEGgKoSP0LhLueu15kAAAAIbmlzdHAyNTYAAABBBHwf2HMM5TRXvo2SQJjsNkiDD5KqiiNjrGVv3UUh+mMT5RHxiRtOnlqvjhQtBq0VpmpCV/PwUdhOig4vkbqAcEcAAAAAAAAAAAAAAAIAAAAOZWNkc2EtbmlzdHAyNTYAAAAUAAAAEGhvc3QuZXhhbXBsZS5jb20AAAAAYkowRgAAAAD00slGAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2XxtSmk9D7RQyf1xUqrYgAAAFMAAAALc3NoLWVkMjU1MTkAAABAMKGSXD1fMVh1N5fqBX20M7U9UPX06h0B+1jGV0soYNiORAUGGAQKWiOslk/xz7hhcnqwaDRG7+5eJTcPbnHqAA== user@example.com

View File

@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHwf2HMM5TRXvo2SQJjsNkiDD5KqiiNjrGVv3UUh+mMT5RHxiRtOnlqvjhQtBq0VpmpCV/PwUdhOig4vkbqAcEc= user@example.com

View File

@@ -0,0 +1,10 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNlY2RzYS
1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQQuboLcVAfxBKERF8fAWxmTw86z2yX6
5ouhaVAqT/k5XZrTa1Q+gBT/FdcI4h8J9YWqbfrVdbeblDQYuGGY2bzZsH//k5mxXUPTTv
rrLla3szz/iAskKz4LWK+Wx1hB7EEAAADY/9Gv3P/Rr9wAAAATZWNkc2Etc2hhMi1uaXN0
cDM4NAAAAAhuaXN0cDM4NAAAAGEELm6C3FQH8QShERfHwFsZk8POs9sl+uaLoWlQKk/5OV
2a02tUPoAU/xXXCOIfCfWFqm361XW3m5Q0GLhhmNm82bB//5OZsV1D00766y5Wt7M8/4gL
JCs+C1ivlsdYQexBAAAAMAN32ekyiyklGWl3Mgor/gE4AYl/oCh4SK+Be9x/QA6IAf0PnA
V9EGkUs4nLFW9gCwAAABB1c2VyQGV4YW1wbGUuY29t
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBC5ugtxUB/EEoREXx8BbGZPDzrPbJfrmi6FpUCpP+TldmtNrVD6AFP8V1wjiHwn1hapt+tV1t5uUNBi4YZjZvNmwf/+TmbFdQ9NO+usuVrezPP+ICyQrPgtYr5bHWEHsQQ== user@example.com

View File

@@ -0,0 +1,12 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNlY2RzYS
1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQBYTaTTxkrI9lh+/RMgYQWYALOosfR
iyCtAY0EbvBo0+glD9Tp8XymaTqFVMMmmm2fV2Ki+aLLh5fUsgHeQh09zFgBA8uUeoWLt3
g9+GP4KVHZb5Gnkl1+K6rSbkfj8vpbB8gnKEikQjt1DXrSuLaS1m3eyuxThQhrH9G2gsop
HIjWN2IAAAEQn8R7O5/EezsAAAATZWNkc2Etc2hhMi1uaXN0cDUyMQAAAAhuaXN0cDUyMQ
AAAIUEAWE2k08ZKyPZYfv0TIGEFmACzqLH0YsgrQGNBG7waNPoJQ/U6fF8pmk6hVTDJppt
n1diovmiy4eX1LIB3kIdPcxYAQPLlHqFi7d4Pfhj+ClR2W+Rp5Jdfiuq0m5H4/L6WwfIJy
hIpEI7dQ160ri2ktZt3srsU4UIax/RtoLKKRyI1jdiAAAAQgHskF8qt6kWnxYfCeVn/Ksi
W75idnJ6XyckU1wrZj162OMlJ9f1mYqZIkDLuQzsPtZ/6QK87ViL65csdxbgknzaggAAAB
B1c2VyQGV4YW1wbGUuY29tAQI=
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAFhNpNPGSsj2WH79EyBhBZgAs6ix9GLIK0BjQRu8GjT6CUP1OnxfKZpOoVUwyaabZ9XYqL5osuHl9SyAd5CHT3MWAEDy5R6hYu3eD34Y/gpUdlvkaeSXX4rqtJuR+Py+lsHyCcoSKRCO3UNetK4tpLWbd7K7FOFCGsf0baCyikciNY3Yg== user@example.com

View File

@@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2XxtSmk9D7RQyf1xUqrYgAAAJgAIAxdACAM
XQAAAAtzc2gtZWQyNTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2XxtSmk9D7RQyf1xUqrYg
AAAEC2BsIi0QwW2uFscKTUUXNHLsYX4FxlaSDSblbAj7WR7bM+rvN+ot98qgEN796jTiQf
ZfG1KaT0PtFDJ/XFSqtiAAAAEHVzZXJAZXhhbXBsZS5jb20BAgMEBQ==
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIAYkJPGaYen7NK8MwZwWmNAyRaFNsc86AU9NObU2cM2uAAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAAAAAAAAAAAACAAAAB2VkMjU1MTkAAAAUAAAAEGhvc3QuZXhhbXBsZS5vcmcAAAAAYkx3NwAAAAB8DuY3AAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2XxtSmk9D7RQyf1xUqrYgAAAFMAAAALc3NoLWVkMjU1MTkAAABApVXBNiYPlPoa1BYH5G4NP9XtjTMZlm7HO5GdbLSvvAw5Vdob7Ka+23hB7isJKHYtzFGGSKXAqxp/Zi8REbCaAw== user@example.com

View File

@@ -0,0 +1 @@
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIE7x9ln6uZLLkfXM8iatrnAAuytVHeCznU8VlEgx7TvLAAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAAAAAAAAAAAABAAAAFGVkMjU1MTktd2l0aC1wMjU2LWNhAAAAAAAAAABiUZm7AAAAAPTaMrsAAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAaAAAABNlY2RzYS1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQR8H9hzDOU0V76NkkCY7DZIgw+SqoojY6xlb91FIfpjE+UR8YkbTp5ar44ULQatFaZqQlfz8FHYTooOL5G6gHBHAAAAZAAAABNlY2RzYS1zaGEyLW5pc3RwMjU2AAAASQAAACEA/0Cwxhkac5AeNYE958j8GgvmkIESDH1TE7QYIqxsFsIAAAAgTEw8WVjlz8AnvyaKGOUELMpyFFJagtD2JFAIAJvilrc= user@example.com

View File

@@ -0,0 +1 @@
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIDG45tSWpvNVTj7LUy9Vqz+LBxVsVsj5km8OIl+yUctjAAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAAAAAAAAAAAABAAAAE2VkMjU1MTktd2l0aC1yc2EtY2EAAAAAAAAAAGJRmeoAAAAA9Noy6gAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAIXAAAAB3NzaC1yc2EAAAADAQABAAACAQC0WRHtxuxefSJhpIxGq4ibGFgwYnESPm8C3JFM88A1JJLoprenklrd7VJ+VH3Ov/bQwZwLyRU5dRmfR/SWTtIPWs7tToJVayKKDB+/qoXmM5ui/0CU2U4rCdQ6PdaCJdC7yFgpPL8WexjWN06+eSIKYz1AAXbx9rRv1iasslK/KUqtsqzVliagI6jl7FPO2GhRZMcso6LsZGgSxuYf/Lp0D/FcBU8GkeOo1Sx5xEt8H8bJcErtCe4Blb8JxcW6EXO3sReb4z+zcR07gumPgFITZ6hDA8sSNuvo/AlWg0IKTeZSwHHVknWdQqDJ0uczE837caBxyTZllDNIGkBjCIIOFzuTT76HfYc/7CTTGk07uaNkUFXKN79xDiFOX8JQ1ZZMZvGOTwWjuT9CqgdTvQRORbRWwOYv3MH8re9ykw3Ip6lrPifY7s6hOaAKry/nkGPMt40m1TdiW98MTIpooE7W+WXu96ax2l2OJvxX8QR7l+LFlKnkIEEJd/ItF1G22UmOjkVwNASTwza/hlY+8DoVvEmwum/nMgH2TwQT3bTQzF9s9DOJkH4d8p4Mw4gEDjNx0EgUFA91ysCAeUMQQyIvuR8HXXa+VcvhOOO5mmBcVhxJ3qUOJTyDBsT0932Zb4mNtkxdigoVxu+iiwk0vwtvKwGVDYdyMP5EAQeEIP1t0wAAAhQAAAAMcnNhLXNoYTItNTEyAAACAAIskD6OCWhvsEzV6U+gq1c1XH3In7YWlNQjPc4LaeRiDeVzUq2Wx/Cimf/7Azq95fbbO0h7x/M63uzu7Ui5hFkIB0ok6MocdU46qayF9K7i5ealdMU39bG5YwWGQUMBZUWe3y6aRCk0KWIBiFICOMFWkTqiGhUISwecRXPbC2TBXgFnmfsGPUJLn+829iuKF5kN+llN0FInYKdVYRPuMKy1SQ0NFgr6OSbgelK58cYYC3I+/0TuG1gwSEOGIHs2akvMwQJ2Z8AmZHj857m44NA2pdHpq411GqD/IGMDsSSt3MrG4D/gNaU7R7n3/7y5Lx92PCnUh95Q978/YIlsHnzW2t8LpP8PvT7NhRp0RPnvyCdeWrUrmNOC04DIwnxVlV+BOa2KpcEBoH40IOMPHKyA6TQPV9B29vuUMBXvDZtn2ECQ0/GQAQGfukgaQqPP8pkezOlfMPup8itA3y2aS63WodfTMy0jvNFHU3DPocl4rtiayXAXx/nuAGKb52mBQF6+nx7sVF1SKuii3lclJqFK66vSYlKtVvRqxaLl37LlBNqkG/jHp8yf4HGjvcRzAMPo5qw+92cU1Xc4DHEIwoUiecSQYVhG0DaCVujYLnZ79/2cS+YU0XjwUWbQlJvYrqh+7FngV2WraWkF+Sd1bxRdyuB5Hrw4tmdoKw6KWTAT user@example.com

View File

@@ -0,0 +1 @@
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIAYkJPGaYen7NK8MwZwWmNAyRaFNsc86AU9NObU2cM2uAAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAAAAAAAAAAAACAAAAB2VkMjU1MTkAAAAUAAAAEGhvc3QuZXhhbXBsZS5jb20AAAAAYkx3NwAAAAB8DuY3AAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2XxtSmk9D7RQyf1xUqrYgAAAFMAAAALc3NoLWVkMjU1MTkAAABApVXBNiYPlPoa1BYH5G4NP9XtjTMZlm7HO5GdbLSvvAw5Vdob7Ka+23hB7isJKHYtzFGGSKXAqxp/Zi8REbCaAw== user@example.com

View File

@@ -0,0 +1,8 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACDNkZXMtY2JjAAAABmJjcnlwdAAAABgAAAAQGvzr6jxZjC
d+ftwreNselAAAABAAAAABAAAAMwAAAAtzc2gtZWQyNTUxOQAAACCzPq7zfqLffKoBDe/e
o04kH2XxtSmk9D7RQyf1xUqrYgAAAJg/4GdFw1boDlKQK5tYsHQUUIyHIYR91BH6LfVhG1
gj+b6Cj3dm1ESAUdg1qhKac4oZS6AYx6L3m7M4rHXYi2SncRqPoa+DODCxcvUqUNQOrT54
6PjbIx6P7Ewam4PtXENekmx0gOsBshNkQyzP8XA86DtorA+kW0VU1YUTmJrqwAzZrrg2Nf
Rueif44KC5+spnhieuaDf6Lg==
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1,8 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczEyOC1jYmMAAAAGYmNyeXB0AAAAGAAAABDfKCxn9E
flgqvP7Uxtpmp5AAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN
796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAoEVNJyfF6Jecws0dSosXLdcRh4doAv07rra0K7
4BxIFyzyoMqFpEdb0jNgyNlMiiIzglU3W9Nd5JQgA06YMtv5bdfJKu9Z9/nxmfTOmPSMlN
hjsXJdmKJjJmJ9ZeMeh2wzOFRewbQ3mtyroK1dXPbiIH601aW00/LYc/HqxnoA0HRkXqwj
nKUyE9vGurvcGySgo1+n7/1u+b9NbqEmt9f+g=
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1,8 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczEyOC1jdHIAAAAGYmNyeXB0AAAAGAAAABDQaLR2sa
YpWEjw/HUGyEGmAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN
796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAoN+GP4jh5KCPGL/0OcFfYZBkS1vtY0QsSd++FF
qMaww+pOEru2QYaEu6VYDeHNDsYRbvSgLRTP5pdyIzY2WSxmKMkRAYTj57LQmokRjLwmHV
mKQKOQ901sAocIq/40ZCwxVXBNu49seU8u6kEgifckpjjraZ/p908QlQFtArVZrwSYvCQT
q2bFsEkyp+3e5QvkidZWbL3/f41uxirt3L28Y=
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1,9 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAAFmFlczEyOC1nY21Ab3BlbnNzaC5jb20AAAAGYmNyeXB0AA
AAGAAAABCiZCxATdLothFeOkNhDdB0AAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAA
ILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAoAni5wCWsx/J4HXd/6UeSH
+me0c0b5CtvJiHk37UXf+tH2f+byjhNqWSyJLgrBlR7waruc5XtsM6HPRo+HeA6VjcYqnP
r8SIipPyLAPtmNttsnc0KZRnzAri4xVIoLLRCJOmL6lzdDBCEKzrXmHZBd/MfLpZRCCoT6
rKuxoSbFrteXAQ6bLHSLid+I+Zm2RgrT+Q9oxLHgrKifLwS1pdE9ER2FYC79hshy83fAlG
i05w
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1,8 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczE5Mi1jYmMAAAAGYmNyeXB0AAAAGAAAABCAILpRu7
oyyiJZTIy4qfJTAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN
796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAoC6RbA0+5zoA0g4f/g04BxpoymbgU2wX83rrdW
E3C+IGJTdYrf/wTJ+ubtQ4JpfESA7Gr2i3mIv9NTtd54y5XzvLpe9S/NfBoFfGz2INvbD8
BnFovA0tPHUrmy6BiUatdpoFEeBwwScB3nw+65DhngCydM2WIsUe1juIq1qpsyZRy0UI0Q
hVgHTGTC4QadWtWtanI93tSyObzke4LClIoiw=
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1,8 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczE5Mi1jdHIAAAAGYmNyeXB0AAAAGAAAABDI/chiIV
ViHJOdrglsLV1pAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN
796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAoNAcEUO0a1eQXgZ6S/m4XoPuo3o+F9S7P795C+
qggI+pDNisImcblRTLhpEBwT9JErq5+zj8qZ2rhCSN+UuvLa28AF2tSZmqAcRXcUNrvgCw
VcqKDR3SgHtifeCB5i32+PT9kLQc7jKQIgZNFv4zF0bmYtEZ9fboDNQZgwvu36Gegv+WNa
g2RecYJ3E7Nmte1H0qjk2aPYKtEfoo/CGl7Dw=
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1,8 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABC596ibeu
zBIwgxU2VhAfNPAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN
796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAoBfqsNSTaDbJdvexzf9ykDWUG6XCqprKijfHka
YCIWuNs/8rjXwRWolpUIGTdThAlZVyrG7t7wjyr3m2jZQ8Xr4KesY7ODJ25Cz4dVBoqj9c
DdPMlIuimygqHZQgpNG7YVie669nyNuHJHFLhfAcNQCz03hhAB2NpEidzIqWZOgqch0qst
tbX5XgVeGiK6YZqYK53vAA44pFkYMGdP/iEBY=
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1,8 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBKH96ujW
umB6/WnTNPjTeaAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN
796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAoFzvbvyFMhAiwBOXF0mhUUacPUCMZXivG2up2c
hEnAw1b6BLRPyWbY5cC2n9ggD4ivJ1zSts6sBgjyiXQAReyrP35myYvT/OIB/NpwZM/xIJ
N7MHSUzlkX4adBrga3f7GS4uv4ChOoxC4XsE5HsxtGsq1X8jzqLlZTmOcxkcEneYQexrUc
bQP0o+gL5aKK8cQgiIlXeDbRjqhc4+h4EF6lY=
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1,9 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAAFmFlczI1Ni1nY21Ab3BlbnNzaC5jb20AAAAGYmNyeXB0AA
AAGAAAABARvcEz72RkQRWxdpF+R8uvAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAA
ILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAoIJQm81qpEdHOG7cGK5d27
FAelmbS6xxp7YaqYnD+9agVk6KsbAM8SMDF6AEiVaxoVPX/+HRV1HwA5BRpWijXmC6meyV
604UAY1ubJKemubnSrNSa4slV/r6wLut1vqFD8ro6nobT+wCgUrwDsL7ZI/9i6nQYXFdDS
vKbSu+2Nwh3B78JQoZXyetXQy3fOZKqrvy/6BFRDsOTKckfRCiAaTcNzfq+DH3OG5x+brH
Yl4J
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1,9 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAAHWNoYWNoYTIwLXBvbHkxMzA1QG9wZW5zc2guY29tAAAABm
JjcnlwdAAAABgAAAAQ9lHKPvsVkE0FwhalBB6omgAAABAAAAABAAAAMwAAAAtzc2gtZWQy
NTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2XxtSmk9D7RQyf1xUqrYgAAAJiRvYDd00XU/W
BkZ93ZW52HNwvM2m3z/MHuqD8q/tk16rKKtBNOc95wo4gyRzkdGYhKnF1RFCJYcdvlw6zo
kctfmmhQ6W54G6u9Eh9bIJtHt3l4FQgzriuIsBTUKZIlvvk6Fo5ItNPHM00r2ehuX81lcZ
QHMaims6Blw8Esl6G3NYCAa2NKyqlmM5LIfkga/Ymydvrbc7EQmN2hbii0c0aMUdYQclyk
F4o=
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqti user@example.com

View File

@@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAOAAAABBuYW1lQG
V4YW1wbGUuY29tAAAAIIiPJO4Xrf7QCR5n5IX7mETP7WByysHQY5DkAF9QFbRPAAAAgH7Q
MVF+0DFRAAAAEG5hbWVAZXhhbXBsZS5jb20AAAAgiI8k7het/tAJHmfkhfuYRM/tYHLKwd
BjkOQAX1AVtE8AAAAgmGyVO0te+zKF/yB8HKXuOaWQR7xIj7w7HvA278dXXHUAAAATY29t
bWVudEBleGFtcGxlLmNvbQECAwQF
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1 @@
name@example.com AAAAEG5hbWVAZXhhbXBsZS5jb20AAAAgiI8k7het/tAJHmfkhfuYRM/tYHLKwdBjkOQAX1AVtE8= comment@example.com

View File

@@ -0,0 +1,38 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEApo5HjJvJNyZDa39enm+aRuG3O+wejLd1TeLGpbbEVfLwEqclmvz5
QYHWnpXTmjSeTStIKlNysolDcx23XHPOe9nuyFAQyUv65WlgEYki+GqLNlWzV9JOemec2K
fZv26uZvf5pW/j0JDQYyIYpoKWDYqtk8AYmHgOrS2+/XD7RwNHF+QS5P2uaFKS7IkeJCP3
/kPfL1QymrCl11YeWC5C6G667gwenq9gPXznCFBdDuCQkS4fw3NetYBN30K2EzEHp26aWc
38a2X0PGMCz7yo56pvl0V/qW07Wibo9BIE0s1CvhGcaEsPAjcImaca48HnEzFUPMP7K0Jo
eAARrk6pNMD/B3CO4YPn6Qb+5Ino4eV/znocbfj7rvObvRlV29WtGr/74Sb1AgXLiErwgP
89cFSdMXS4W9f2Ykw3U88jW2UNDkIo8yvntUpZDYaft3hlWbt6TWb506acCF798IOpFdR6
HZFhoIdWsmOwbnOdmfKJA2KryWreQszo+TmkDa/5AAAFiD9lruM/Za7jAAAAB3NzaC1yc2
EAAAGBAKaOR4ybyTcmQ2t/Xp5vmkbhtzvsHoy3dU3ixqW2xFXy8BKnJZr8+UGB1p6V05o0
nk0rSCpTcrKJQ3Mdt1xzznvZ7shQEMlL+uVpYBGJIvhqizZVs1fSTnpnnNin2b9urmb3+a
Vv49CQ0GMiGKaClg2KrZPAGJh4Dq0tvv1w+0cDRxfkEuT9rmhSkuyJHiQj9/5D3y9UMpqw
pddWHlguQuhuuu4MHp6vYD185whQXQ7gkJEuH8NzXrWATd9CthMxB6dumlnN/Gtl9DxjAs
+8qOeqb5dFf6ltO1om6PQSBNLNQr4RnGhLDwI3CJmnGuPB5xMxVDzD+ytCaHgAEa5OqTTA
/wdwjuGD5+kG/uSJ6OHlf856HG34+67zm70ZVdvVrRq/++Em9QIFy4hK8ID/PXBUnTF0uF
vX9mJMN1PPI1tlDQ5CKPMr57VKWQ2Gn7d4ZVm7ek1m+dOmnAhe/fCDqRXUeh2RYaCHVrJj
sG5znZnyiQNiq8lq3kLM6Pk5pA2v+QAAAAMBAAEAAAGAa2MLEMaVCsDZ8WJzEDYmw5LewH
zyCYpz0J7ps4jOuBfl4DDy1yZKU4kyZpd1klRgyKKiad/Z8PD9kyhSxAJK3KHcCj1NRWx+
vRGfBk9kQ8T2Mzc4ZeRMAzHw9+PpSjtDqVIzHQ6yVRQ5t+ERAbLqqpqCZeQSN6QY2mHHZc
NF0Dh1yxqbcBd8Lvkmj+msjGLAj6kVKn/gDMrecqOs9vAE5bYXQkqAJ5ItvBdfIoYmKeRy
cZjKlAs7wkySaOOrX15ZZbg4fhRwZ5s+poCWX4FZPLFBMQ1MQVaeJbN2otxO2S+RSbdelw
6CJHMJRswg81H4EVsbv8uzj2vQbGIEcrdtZB01gCre8VIgq5sqV+NZGP4n4TgRnMpWqYzP
PA/Gg6GfJyGodm7N2cV2d2YmVvPT4FMl8/s3MmYj277GOz2YSDCy3Se+u2vS7VNF3/8Y3x
gGrevO2phFgElokwaBrD5SMTjFIWyxNZl+PhQ6eBasw9h0HqzsfhX1PaDwgQaRcI2dAAAA
wFRAWqZjrp4IADWnEAL0w1HX0ALDUgByXm3A/22QGjBLEDouoBZQeZbTGTWLW+pP60CY9T
BSjxK5jFDH3fyF/Er5JXuvmqcjXN9GdzSbd+UqQKXi9EEi0YzkCUGRTpkWnEi3CImNKYaW
VmB7fi62NUHgu9Vo5Pd0vsMTfQKlkcjHey4Yjdb3Lu9c/xknzeVzpMoNQ8K2xqlXIURRIu
HPaqXwW2XLnIYST595+inwXj8G87g+3KmUH1cWUOD7RoquTAAAAMEA0R564khkDTsgKTaR
iGVEzf4HeamqtWyPlia/HmZIv9mIvbCsfRGnPjQFYzbUrTkA/3GE7kBLhLrrEaKjAvmC2U
7vt1cDDsbXfZEV6u+Aq1dJoPW1kLKZ/96U+ZMN7bqyrzMwlbCKUEubMPERLc5R837QDQQz
Q9Qg0uL7iL1/iBt8iZDki5P9HShPzIwcB/vvwE0CklsvFZqan1Zwc+HJT9xuRy9IljvhbF
xUU4Vq0r95FuQsNudaUBiRDY2tA41zAAAAwQDL5Q5+zfXiyG52ypS+iwwFsJBB0rzd7rRn
LnEg6syDgOXWt3yFWDxQj47o1VfKvLbfroxyOF8PaTRevBWl3+yUnAdw0C15Rd01klYtpz
iGYuBTxUVNJpDeKmPMVV4aAQ4toK4wfRwR+FKpx1aOAvk9SbKo+Se3mUOykgytMhqiCEEJ
0TbQhcHQXDn0w2z4n9w8ZqdV5j9EbhYwKxNZlADwqDMhoua5FT3wLwPeMY6gkDkoKFPyAR
4JBdEVdmfK8eMAAAAQdXNlckBleGFtcGxlLmNvbQECAw==
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCmjkeMm8k3JkNrf16eb5pG4bc77B6Mt3VN4saltsRV8vASpyWa/PlBgdaeldOaNJ5NK0gqU3KyiUNzHbdcc8572e7IUBDJS/rlaWARiSL4aos2VbNX0k56Z5zYp9m/bq5m9/mlb+PQkNBjIhimgpYNiq2TwBiYeA6tLb79cPtHA0cX5BLk/a5oUpLsiR4kI/f+Q98vVDKasKXXVh5YLkLobrruDB6er2A9fOcIUF0O4JCRLh/Dc161gE3fQrYTMQenbppZzfxrZfQ8YwLPvKjnqm+XRX+pbTtaJuj0EgTSzUK+EZxoSw8CNwiZpxrjwecTMVQ8w/srQmh4ABGuTqk0wP8HcI7hg+fpBv7kiejh5X/Oehxt+Puu85u9GVXb1a0av/vhJvUCBcuISvCA/z1wVJ0xdLhb1/ZiTDdTzyNbZQ0OQijzK+e1SlkNhp+3eGVZu3pNZvnTppwIXv3wg6kV1HodkWGgh1ayY7Buc52Z8okDYqvJat5CzOj5OaQNr/k= user@example.com

View File

@@ -0,0 +1,49 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAgEAtFkR7cbsXn0iYaSMRquImxhYMGJxEj5vAtyRTPPANSSS6Ka3p5Ja
3e1SflR9zr/20MGcC8kVOXUZn0f0lk7SD1rO7U6CVWsiigwfv6qF5jObov9AlNlOKwnUOj
3WgiXQu8hYKTy/FnsY1jdOvnkiCmM9QAF28fa0b9YmrLJSvylKrbKs1ZYmoCOo5exTztho
UWTHLKOi7GRoEsbmH/y6dA/xXAVPBpHjqNUsecRLfB/GyXBK7QnuAZW/CcXFuhFzt7EXm+
M/s3EdO4Lpj4BSE2eoQwPLEjbr6PwJVoNCCk3mUsBx1ZJ1nUKgydLnMxPN+3Ggcck2ZZQz
SBpAYwiCDhc7k0++h32HP+wk0xpNO7mjZFBVyje/cQ4hTl/CUNWWTGbxjk8Fo7k/QqoHU7
0ETkW0VsDmL9zB/K3vcpMNyKepaz4n2O7OoTmgCq8v55BjzLeNJtU3YlvfDEyKaKBO1vll
7vemsdpdjib8V/EEe5fixZSp5CBBCXfyLRdRttlJjo5FcDQEk8M2v4ZWPvA6FbxJsLpv5z
IB9k8EE9200MxfbPQziZB+HfKeDMOIBA4zcdBIFBQPdcrAgHlDEEMiL7kfB112vlXL4Tjj
uZpgXFYcSd6lDiU8gwbE9Pd9mW+JjbZMXYoKFcbvoosJNL8LbysBlQ2HcjD+RAEHhCD9bd
MAAAdI79BESO/QREgAAAAHc3NoLXJzYQAAAgEAtFkR7cbsXn0iYaSMRquImxhYMGJxEj5v
AtyRTPPANSSS6Ka3p5Ja3e1SflR9zr/20MGcC8kVOXUZn0f0lk7SD1rO7U6CVWsiigwfv6
qF5jObov9AlNlOKwnUOj3WgiXQu8hYKTy/FnsY1jdOvnkiCmM9QAF28fa0b9YmrLJSvylK
rbKs1ZYmoCOo5exTzthoUWTHLKOi7GRoEsbmH/y6dA/xXAVPBpHjqNUsecRLfB/GyXBK7Q
nuAZW/CcXFuhFzt7EXm+M/s3EdO4Lpj4BSE2eoQwPLEjbr6PwJVoNCCk3mUsBx1ZJ1nUKg
ydLnMxPN+3Ggcck2ZZQzSBpAYwiCDhc7k0++h32HP+wk0xpNO7mjZFBVyje/cQ4hTl/CUN
WWTGbxjk8Fo7k/QqoHU70ETkW0VsDmL9zB/K3vcpMNyKepaz4n2O7OoTmgCq8v55BjzLeN
JtU3YlvfDEyKaKBO1vll7vemsdpdjib8V/EEe5fixZSp5CBBCXfyLRdRttlJjo5FcDQEk8
M2v4ZWPvA6FbxJsLpv5zIB9k8EE9200MxfbPQziZB+HfKeDMOIBA4zcdBIFBQPdcrAgHlD
EEMiL7kfB112vlXL4TjjuZpgXFYcSd6lDiU8gwbE9Pd9mW+JjbZMXYoKFcbvoosJNL8Lby
sBlQ2HcjD+RAEHhCD9bdMAAAADAQABAAACAHDWOa13hHQp/tTwywN8V2ASfzrmnLA5d+Nm
dVKcP2oAlBoUFVw26btovPBllMFCwf4i5KtLCIiGh51su88/SZZpzoYTVOB0w4tzwnl9C4
HYUExPP+zheVLcN3ipMAkF9+9FjkNeyoAaTJPazt3FlFLDfJMLV4xUOtiuOExc1gDcqOi8
nf6Uj14qcYZJsrX8GGi0kRmQ2GLm/2agI2NoEJCFWRGmEKefp7z+g3E8K65hg1KNe5OLXu
qG8pv+rZOZT7lih871A+oVn6CYa+Fo+/FALbqgKPIggsGmz4DdZvhjfPPRjGd/1y6pfUhJ
OHZwsbPch/IpXmt3qg42voo3zIZPJ4bfqjxFIoNuRDPY3ZxGTBVaeKwZ5JsB9WlZADuqzV
GDwK7vH/DamYj+qh23qt/V4kPqUJXTRI9UEeGY/yniuv2hwmAH7/42loYXFhViWvVjTcmM
6B7QJOpVnYv+/G5xcqnRQJJz+U0CNbLna7QaUy22zp8KKNTrDbcKvO2VRi7sXiItOz5hwz
CpyXkTp95ihSTj2qJM6T0qz5RA4DxXBj48dQkzKt3zfVyEA3Wgud4daIIs3PiLRM1q6ov8
ZGzlL50F5+hnoy1GLjWhY8FbffAOnAqHA0W4bniClxtNedQlB63nwm5tsp9S++WEMPkVxV
QUX6qVCua25Ph78kphAAABAFgPNYCirVT35DkKmaBbN3cwrr5jHNQfZFJCTgN2PS1DrzJ/
kZqpa/dIowQf1vdrRxtLgCnrrAHfGGkrFhLF0EZkAIOrEjVGSVu/q3fV+aS46+/86ZdBfq
ViWwcL4c+MWyU+3YJr5gQu4fcaE7cujfb9y3+KlF71kppMeQgDvDH+/yT48UiSbqOqAsaQ
iJuu6x5ycpVkLxOVUGf+5ACyMIdiUv2dzx9WpDB9PXF88CNYM/3JOUeitO1F1D31EIfZHV
nrC/Cf5vRQNrI8lErdzil2uAVCXGhBEpvlsXxNzEHWLaoFPQah+/08IFQ6YwZq1pkzrmRT
jDBa5kXYFVem88kAAAEBAOK3qpViHsBlrNG57dRgkMcV4dIS8RrCT2HDAWpLQRolxjUAdl
TcGaFFUx+dSfeWlloo9nV1pam/hStTR0xDRc9gTUC2FOMdUPDKVkFPFStJ1rkth2fUcKWh
CvtuVGGJ1umXOa7/eggdlv1cFkbFq7uEgd+TbGWq1RpVNZbhb0mwn4gXXSyTj5LsrMxhMT
Uj/WeFMwB/Bcq1Hf0Wz680OQM706TYRcCONAl7b37NBhMILn0YMPk24px4ZcK4rNMIcN0g
Z5eI4LKqoihdNepzR8QIPi7pyS3LEe6hFCRcXyLXr+udUcvAyhcRYmH6yKjzwwVNofU60p
f4zhhGY+xOYX0AAAEBAMukNjMmN77P297CSdvBIeUwnJlk8gU8IhtYtgGEav18yLeI1r+b
cTRbG93ns2cgTgEO5gwhJjUkds6YiZtyA1618q6N2XVN1QA1TEGMu/dd/UvyApqaPI4Jfv
2zNOgiinOLHD+sQ7SCI2SlS0w0gEI2m1nPCGsl2yMib3Ht6uWOd/xvEEk2QcQlTCiZm+Vi
jNdOJZ1f5dOcmKnAuFQ71YyJuzTqGeGK9xTxRG4pPQmIHtf6X0mzdLyrl9r6Bn6OtjvJ3f
Jmi/PrsrtYXXsS/1keb/NIiRlrnlKTgJ8WjWgbt7CWgP7wk8iijvDSVWj85Kteh5/uIadS
WsCMr576LY8AAAAQdXNlckBleGFtcGxlLmNvbQECAw==
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgN1C5LY0DdJp9w6/4w9zr8W1MrjF3Wl5kt8s3N5G8ZkIAAAADAQABAAACAQC0WRHtxuxefSJhpIxGq4ibGFgwYnESPm8C3JFM88A1JJLoprenklrd7VJ+VH3Ov/bQwZwLyRU5dRmfR/SWTtIPWs7tToJVayKKDB+/qoXmM5ui/0CU2U4rCdQ6PdaCJdC7yFgpPL8WexjWN06+eSIKYz1AAXbx9rRv1iasslK/KUqtsqzVliagI6jl7FPO2GhRZMcso6LsZGgSxuYf/Lp0D/FcBU8GkeOo1Sx5xEt8H8bJcErtCe4Blb8JxcW6EXO3sReb4z+zcR07gumPgFITZ6hDA8sSNuvo/AlWg0IKTeZSwHHVknWdQqDJ0uczE837caBxyTZllDNIGkBjCIIOFzuTT76HfYc/7CTTGk07uaNkUFXKN79xDiFOX8JQ1ZZMZvGOTwWjuT9CqgdTvQRORbRWwOYv3MH8re9ykw3Ip6lrPifY7s6hOaAKry/nkGPMt40m1TdiW98MTIpooE7W+WXu96ax2l2OJvxX8QR7l+LFlKnkIEEJd/ItF1G22UmOjkVwNASTwza/hlY+8DoVvEmwum/nMgH2TwQT3bTQzF9s9DOJkH4d8p4Mw4gEDjNx0EgUFA91ysCAeUMQQyIvuR8HXXa+VcvhOOO5mmBcVhxJ3qUOJTyDBsT0932Zb4mNtkxdigoVxu+iiwk0vwtvKwGVDYdyMP5EAQeEIP1t0wAAAAAAAAAAAAAAAQAAAANyc2EAAAAAAAAAAGJHkAUAAAAA9NApBQAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEB5WnlZ0Gu6EX+BUDsyV0Ty/7iLsZ39LEe1v1nWKuqteIbgEt2MFwoenLpCyn83uKXqtc8HkeV0UJ0kpTZM1NQG user@example.com

View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC0WRHtxuxefSJhpIxGq4ibGFgwYnESPm8C3JFM88A1JJLoprenklrd7VJ+VH3Ov/bQwZwLyRU5dRmfR/SWTtIPWs7tToJVayKKDB+/qoXmM5ui/0CU2U4rCdQ6PdaCJdC7yFgpPL8WexjWN06+eSIKYz1AAXbx9rRv1iasslK/KUqtsqzVliagI6jl7FPO2GhRZMcso6LsZGgSxuYf/Lp0D/FcBU8GkeOo1Sx5xEt8H8bJcErtCe4Blb8JxcW6EXO3sReb4z+zcR07gumPgFITZ6hDA8sSNuvo/AlWg0IKTeZSwHHVknWdQqDJ0uczE837caBxyTZllDNIGkBjCIIOFzuTT76HfYc/7CTTGk07uaNkUFXKN79xDiFOX8JQ1ZZMZvGOTwWjuT9CqgdTvQRORbRWwOYv3MH8re9ykw3Ip6lrPifY7s6hOaAKry/nkGPMt40m1TdiW98MTIpooE7W+WXu96ax2l2OJvxX8QR7l+LFlKnkIEEJd/ItF1G22UmOjkVwNASTwza/hlY+8DoVvEmwum/nMgH2TwQT3bTQzF9s9DOJkH4d8p4Mw4gEDjNx0EgUFA91ysCAeUMQQyIvuR8HXXa+VcvhOOO5mmBcVhxJ3qUOJTyDBsT0932Zb4mNtkxdigoVxu+iiwk0vwtvKwGVDYdyMP5EAQeEIP1t0w== user@example.com

View File

@@ -0,0 +1 @@
sk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAguiTG3xznoyOCvoGoekia/u/JJZ51Hmy5fcHDBXA/atwAAAAIbmlzdHAyNTYAAABBBIELQJ2DgvaX1yQlKFokfWM2suuaCFI2qp0eJodHyg6O4ifxc3XpRKd1OS8dNYQtE/YjdXSrA+AOnMF5ns2Nkx4AAAAEc3NoOgAAAAAAAAAAAAAAAQAAABFzay1lY2RzYS1uaXN0cDI1NgAAAAAAAAAAYk3NggAAAAD01maCAAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgsz6u836i33yqAQ3v3qNOJB9l8bUppPQ+0UMn9cVKq2IAAABTAAAAC3NzaC1lZDI1NTE5AAAAQPv0I2T2ypcmZjff59v0lTUPllGxc+Cn5mACERgsHM9sSxsBq7WLiuzV+31JYh9B3CiavhI4Tl6CYGijdX1M4wo= user@example.com

View File

@@ -0,0 +1 @@
sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBIELQJ2DgvaX1yQlKFokfWM2suuaCFI2qp0eJodHyg6O4ifxc3XpRKd1OS8dNYQtE/YjdXSrA+AOnMF5ns2Nkx4AAAAEc3NoOg== user@example.com

View File

@@ -0,0 +1 @@
sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBNdo6XfhTK080uz5UbGyOcNMo+R3nPXMBxurwH2M1bDtQYbDT6qBE7EdQGkcy/EJDXbzT0KlU9rROjcX+JsgtGAAAAAEc3NoOg== user@example.com

View File

@@ -0,0 +1 @@
sk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIG/VTdX1zj24l7+wPGYDN/QPXBDyBjGwUj7wTk1vgC9iAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoAAAAAAAAAAAAAAAEAAAAKc2stZWQyNTUxOQAAAAAAAAAAYk3NxAAAAAD01mbEAAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgsz6u836i33yqAQ3v3qNOJB9l8bUppPQ+0UMn9cVKq2IAAABTAAAAC3NzaC1lZDI1NTE5AAAAQFnv46uyvpzZFXBXGRkGEgp/HsMM4iYexEfU+rHJFi25s4RfVktxwJptE6QaUzm5TcZW9pyP8+DHkJp20QItuwg= user@example.com

View File

@@ -0,0 +1 @@
sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDo= user@example.com

View File

@@ -0,0 +1 @@
sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAINSoElFleH+nN83FoLqqepJjN+y7Gs5lrn7qXjBqQZyuAAAABHNzaDo= user@example.com

View File

@@ -0,0 +1,34 @@
# Example authorized keys file
#
# - Comments in these files begin with `#`
# - They can also contain blank lines
# - Lines which are not blank each contain a single host-pattern's public key
# - Maximum line length is 8 kilobytes
#
# Known hosts consist of the following space-separated fields:
#
# marker, hostnames, keytype, base64-encoded key, comment
#
# - The marker field is optional, but if present begins with an `@`. Known markers are `@cert-authority`
# and `@revoked`.
# - The hostnames is a comma-separated list of patterns (with `*` and '?' as glob-style wildcards)
# against which hosts are matched. If it begins with a `!` it is a negation of the pattern. If the
# pattern starts with `[` and ends with `]`, it contains a hostname pattern and a port number separated
# by a `:`. If it begins with `|1|`, the hostname is hashed. In that case, there can only be one exact
# hostname and it can't also be negated (ie. `!|1|x|y` is not legal and you can't hash `*.example.org`).
# - The keytype is `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`,
# `ssh-ed25519`, `ssh-dss` or `ssh-rsa`
# - The comment field is not used for anything (but may be convenient for the user to identify
# the key).
# Single simple patterned hostname with no comment in the key
test.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqti
# Multiple hostnames with various patterns and a comment
cvs.example.net,!test.example.???,[*.example.net]:999 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHwf2HMM5TRXvo2SQJjsNkiDD5KqiiNjrGVv3UUh+mMT5RHxiRtOnlqvjhQtBq0VpmpCV/PwUdhOig4vkbqAcEc= example.com
# A revoked, hashed hostname
@revoked |1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-dss AAAAB3NzaC1kc3MAAACBANw9iSUO2UYhFMssjUgW46URqv8bBrDgHeF8HLBOWBvKuXF2Rx2J/XyhgX48SOLMuv0hcPaejlyLarabnF9F2V4dkpPpZSJ+7luHmxEjNxwhsdtg8UteXAWkeCzrQ6MvRJZHcDBjYh56KGvslbFnJsGLXlI4PQCyl6awNImwYGilAAAAFQCJGBU3hZf+QtP9Jh/nbfNlhFu7hwAAAIBHObOQioQVRm3HsVb7mOy3FVKhcLoLO3qoG9gTkd4KeuehtFAC3+rckiX7xSCnE/5BBKdL7VP9WRXac2Nlr9Pwl3e7zPut96wrCHt/TZX6vkfXKkbpUIj5zSqfvyNrWKaYJkfzwAQwrXNS1Hol676Ud/DDEn2oatdEhkS3beWHXAAAAIBgQqaz/YYTRMshzMzYcZ4lqgvgmA55y6v0h39e8HH2A5dwNS6sPUw2jyna+le0dceNRJifFld1J+WYM0vmquSr11DDavgEidOSaXwfMvPPPJqLmbzdtT16N+Gij9U9STQTHPQcQ3xnNNHgQAStzZJbhLOVbDDDo5BO7LMUALDfSA==
# A certificate authority with a comment
@cert-authority *.example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC0WRHtxuxefSJhpIxGq4ibGFgwYnESPm8C3JFM88A1JJLoprenklrd7VJ+VH3Ov/bQwZwLyRU5dRmfR/SWTtIPWs7tToJVayKKDB+/qoXmM5ui/0CU2U4rCdQ6PdaCJdC7yFgpPL8WexjWN06+eSIKYz1AAXbx9rRv1iasslK/KUqtsqzVliagI6jl7FPO2GhRZMcso6LsZGgSxuYf/Lp0D/FcBU8GkeOo1Sx5xEt8H8bJcErtCe4Blb8JxcW6EXO3sReb4z+zcR07gumPgFITZ6hDA8sSNuvo/AlWg0IKTeZSwHHVknWdQqDJ0uczE837caBxyTZllDNIGkBjCIIOFzuTT76HfYc/7CTTGk07uaNkUFXKN79xDiFOX8JQ1ZZMZvGOTwWjuT9CqgdTvQRORbRWwOYv3MH8re9ykw3Ip6lrPifY7s6hOaAKry/nkGPMt40m1TdiW98MTIpooE7W+WXu96ax2l2OJvxX8QR7l+LFlKnkIEEJd/ItF1G22UmOjkVwNASTwza/hlY+8DoVvEmwum/nMgH2TwQT3bTQzF9s9DOJkH4d8p4Mw4gEDjNx0EgUFA91ysCAeUMQQyIvuR8HXXa+VcvhOOO5mmBcVhxJ3qUOJTyDBsT0932Zb4mNtkxdigoVxu+iiwk0vwtvKwGVDYdyMP5EAQeEIP1t0w== authority@example.com

View File

@@ -0,0 +1,13 @@
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAAbEAAAAHc3NoLWRzcwAAAIEA3D2JJQ7ZRiEUyyyNSBbjpRGq/xsGsO
Ad4XwcsE5YG8q5cXZHHYn9fKGBfjxI4sy6/SFw9p6OXItqtpucX0XZXh2Sk+llIn7uW4eb
ESM3HCGx22DxS15cBaR4LOtDoy9ElkdwMGNiHnooa+yVsWcmwYteUjg9ALKXprA0ibBgaK
UAAAAVAIkYFTeFl/5C0/0mH+dt82WEW7uHAAAAgEc5s5CKhBVGbcexVvuY7LcVUqFwugs7
eqgb2BOR3gp656G0UALf6tySJfvFIKcT/kEEp0vtU/1ZFdpzY2Wv0/CXd7vM+633rCsIe3
9Nlfq+R9cqRulQiPnNKp+/I2tYppgmR/PABDCtc1LUeiXrvpR38MMSfahq10SGRLdt5Ydc
AAAAgGBCprP9hhNEyyHMzNhxniWqC+CYDnnLq/SHf17wcfYDl3A1Lqw9TDaPKdr6V7R1x4
1EmJ8WV3Un5ZgzS+aq5KvXUMNq+ASJ05JpfB8y8888mouZvN21PXo34aKP1T1JNBMc9BxD
fGc00eBABK3NkluEs5VsMMOjkE7ssxQAsN9IAAAAB2V4YW1wbGUAAAAAAAAABnNoYTUxMg
AAADcAAAAHc3NoLWRzcwAAACgpmje+ZfkBQr6VEub3uY2yZNOwXSdFsEtmylVrgY2cEr39
gGnpa50C
-----END SSH SIGNATURE-----

View File

@@ -0,0 +1,7 @@
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAAGgAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAE
EEfB/YcwzlNFe+jZJAmOw2SIMPkqqKI2OsZW/dRSH6YxPlEfGJG06eWq+OFC0GrRWmakJX
8/BR2E6KDi+RuoBwRwAAAAdleGFtcGxlAAAAAAAAAAZzaGE1MTIAAABjAAAAE2VjZHNhLX
NoYTItbmlzdHAyNTYAAABIAAAAID884rM9MmiHWlfwoX+JY6rrivMILmCEganDbXs6ShAB
AAAAIEYXgcOegKAJkfP1P7kw2AnlEIY0hRwtUm7moeouFySh
-----END SSH SIGNATURE-----

View File

@@ -0,0 +1,8 @@
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAAIgAAAATZWNkc2Etc2hhMi1uaXN0cDM4NAAAAAhuaXN0cDM4NAAAAG
EELm6C3FQH8QShERfHwFsZk8POs9sl+uaLoWlQKk/5OV2a02tUPoAU/xXXCOIfCfWFqm36
1XW3m5Q0GLhhmNm82bB//5OZsV1D00766y5Wt7M8/4gLJCs+C1ivlsdYQexBAAAAB2V4YW
1wbGUAAAAAAAAABnNoYTUxMgAAAIQAAAATZWNkc2Etc2hhMi1uaXN0cDM4NAAAAGkAAAAw
WRSBydn20NFbMvdQGNRgO+e/AFdDm9eaT/AqQk3rFKKyuyC71gaiGXke3BWByW57AAAAMQ
DshCxIODastNeRULgAtklWgLC/6i1JQeelDPMFVD/T4tvQKBy2tnpUf1+9FKpoB34=
-----END SSH SIGNATURE-----

View File

@@ -0,0 +1,6 @@
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgsz6u836i33yqAQ3v3qNOJB9l8b
UppPQ+0UMn9cVKq2IAAAAHZXhhbXBsZQAAAAAAAAAGc2hhNTEyAAAAUwAAAAtzc2gtZWQy
NTUxOQAAAEBPEav+tMGNnox4MuzM7rlHyVBajCn8B0kAyiOWwPKprNsG3i6X+voz/WCSik
/FowYwqhgCABUJSvRX3AERVBUP
-----END SSH SIGNATURE-----

View File

@@ -0,0 +1,19 @@
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAAZcAAAAHc3NoLXJzYQAAAAMBAAEAAAGBAKaOR4ybyTcmQ2t/Xp5vmk
bhtzvsHoy3dU3ixqW2xFXy8BKnJZr8+UGB1p6V05o0nk0rSCpTcrKJQ3Mdt1xzznvZ7shQ
EMlL+uVpYBGJIvhqizZVs1fSTnpnnNin2b9urmb3+aVv49CQ0GMiGKaClg2KrZPAGJh4Dq
0tvv1w+0cDRxfkEuT9rmhSkuyJHiQj9/5D3y9UMpqwpddWHlguQuhuuu4MHp6vYD185whQ
XQ7gkJEuH8NzXrWATd9CthMxB6dumlnN/Gtl9DxjAs+8qOeqb5dFf6ltO1om6PQSBNLNQr
4RnGhLDwI3CJmnGuPB5xMxVDzD+ytCaHgAEa5OqTTA/wdwjuGD5+kG/uSJ6OHlf856HG34
+67zm70ZVdvVrRq/++Em9QIFy4hK8ID/PXBUnTF0uFvX9mJMN1PPI1tlDQ5CKPMr57VKWQ
2Gn7d4ZVm7ek1m+dOmnAhe/fCDqRXUeh2RYaCHVrJjsG5znZnyiQNiq8lq3kLM6Pk5pA2v
+QAAAAdleGFtcGxlAAAAAAAAAAZzaGE1MTIAAAGUAAAADHJzYS1zaGEyLTUxMgAAAYBgAr
3zDww5X0fRn4fSzHi0okXxU8N4R0qJp2GJ/z9MlwIbxJ+NuWV9MbCRc27lBxklvos69kJ0
zD0yXfpBHB+ABPO+7GPOm/8cj1ldy7AvjfGYb+UOwppAwGueaRGoeYXdiM5d9obpDLpX0u
UOoPkvLoXT/RHC8H+imHvDDfWTAvTe2a4Dukf78VA0ZGOI0BDO7ZIkcNL9t380cggEEzgj
Dj5215DG1Bk9cSw2P2WozuOeaTBuJttY+8/yhO7B9LVVJIPkxDewmbhQs5ycWWuUSUzGZC
YyHPTVbEu0zJSStQBUELR7qneFfHPpFO43L05yKmHOf+wtpo5Cp2JXV3+lpOtjdsP1Odu6
/Gu7MX2qXgNEeTa9tFlybWxzTGKGMb0jrAHO4ivVlfYl+gjpd5URxf8pllnOaHQutPBTZX
UR1izJqucaJyQdyuI4Q2B7jl20zQlpwEqM6GiCbct7BJ3i38DgBXdcrz735+Tmuf+6LPMV
S9OHR3RCWZBFnFyt7dA=
-----END SSH SIGNATURE-----

View File

@@ -0,0 +1,7 @@
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAAEoAAAAac2stc3NoLWVkMjU1MTlAb3BlbnNzaC5jb20AAAAg1KgSUW
V4f6c3zcWguqp6kmM37LsazmWufupeMGpBnK4AAAAEc3NoOgAAAAdleGFtcGxlAAAAAAAA
AAZzaGE1MTIAAABnAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAQC9WcLb5NG
XRdCOHinQIS/MxdnAx7SQMYnyOt5q4+huTWh/Zk/UvWhP+wXl/ikNPlDpgliRq6o3VyKqS
LLo9lQYBAAAACQ==
-----END SSH SIGNATURE-----

63
vendor/ssh-key/tests/known_hosts.rs vendored Normal file
View File

@@ -0,0 +1,63 @@
//! Tests for parsing `known_hosts` files.
#![cfg(all(feature = "ecdsa", feature = "std"))]
use ssh_key::known_hosts::{HostPatterns, KnownHosts, Marker};
// TODO(tarcieri): test file permissions
#[test]
fn read_example_file() {
let known_hosts = KnownHosts::read_file("./tests/examples/known_hosts").unwrap();
assert_eq!(known_hosts.len(), 4);
assert_eq!(known_hosts[0].marker(), None);
assert_eq!(
known_hosts[0].host_patterns(),
&HostPatterns::Patterns(vec!["test.example.com".to_string()])
);
assert_eq!(
known_hosts[0].public_key().to_string(),
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqti"
);
assert_eq!(known_hosts[0].public_key().comment(), "");
assert_eq!(known_hosts[1].marker(), None);
assert_eq!(
known_hosts[1].host_patterns(),
&HostPatterns::Patterns(vec![
"cvs.example.net".to_string(),
"!test.example.???".to_string(),
"[*.example.net]:999".to_string(),
])
);
assert_eq!(known_hosts[1].public_key().to_string(), "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHwf2HMM5TRXvo2SQJjsNkiDD5KqiiNjrGVv3UUh+mMT5RHxiRtOnlqvjhQtBq0VpmpCV/PwUdhOig4vkbqAcEc= example.com");
assert_eq!(known_hosts[1].public_key().comment(), "example.com");
assert_eq!(known_hosts[2].marker(), Some(&Marker::Revoked));
assert_eq!(
known_hosts[2].host_patterns(),
&HostPatterns::HashedName {
salt: vec![
37, 242, 147, 116, 24, 123, 172, 214, 215, 145, 80, 16, 9, 26, 120, 57, 10, 15,
126, 98
],
hash: [
81, 33, 2, 175, 116, 150, 127, 82, 84, 62, 201, 172, 228, 10, 159, 15, 148, 31,
198, 67
],
}
);
assert_eq!(known_hosts[2].public_key().to_string(), "ssh-dss AAAAB3NzaC1kc3MAAACBANw9iSUO2UYhFMssjUgW46URqv8bBrDgHeF8HLBOWBvKuXF2Rx2J/XyhgX48SOLMuv0hcPaejlyLarabnF9F2V4dkpPpZSJ+7luHmxEjNxwhsdtg8UteXAWkeCzrQ6MvRJZHcDBjYh56KGvslbFnJsGLXlI4PQCyl6awNImwYGilAAAAFQCJGBU3hZf+QtP9Jh/nbfNlhFu7hwAAAIBHObOQioQVRm3HsVb7mOy3FVKhcLoLO3qoG9gTkd4KeuehtFAC3+rckiX7xSCnE/5BBKdL7VP9WRXac2Nlr9Pwl3e7zPut96wrCHt/TZX6vkfXKkbpUIj5zSqfvyNrWKaYJkfzwAQwrXNS1Hol676Ud/DDEn2oatdEhkS3beWHXAAAAIBgQqaz/YYTRMshzMzYcZ4lqgvgmA55y6v0h39e8HH2A5dwNS6sPUw2jyna+le0dceNRJifFld1J+WYM0vmquSr11DDavgEidOSaXwfMvPPPJqLmbzdtT16N+Gij9U9STQTHPQcQ3xnNNHgQAStzZJbhLOVbDDDo5BO7LMUALDfSA==");
assert_eq!(known_hosts[2].public_key().comment(), "");
assert_eq!(known_hosts[3].marker(), Some(&Marker::CertAuthority));
assert_eq!(
known_hosts[3].host_patterns(),
&HostPatterns::Patterns(vec!["*.example.com".to_string()])
);
assert_eq!(known_hosts[3].public_key().to_string(), "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC0WRHtxuxefSJhpIxGq4ibGFgwYnESPm8C3JFM88A1JJLoprenklrd7VJ+VH3Ov/bQwZwLyRU5dRmfR/SWTtIPWs7tToJVayKKDB+/qoXmM5ui/0CU2U4rCdQ6PdaCJdC7yFgpPL8WexjWN06+eSIKYz1AAXbx9rRv1iasslK/KUqtsqzVliagI6jl7FPO2GhRZMcso6LsZGgSxuYf/Lp0D/FcBU8GkeOo1Sx5xEt8H8bJcErtCe4Blb8JxcW6EXO3sReb4z+zcR07gumPgFITZ6hDA8sSNuvo/AlWg0IKTeZSwHHVknWdQqDJ0uczE837caBxyTZllDNIGkBjCIIOFzuTT76HfYc/7CTTGk07uaNkUFXKN79xDiFOX8JQ1ZZMZvGOTwWjuT9CqgdTvQRORbRWwOYv3MH8re9ykw3Ip6lrPifY7s6hOaAKry/nkGPMt40m1TdiW98MTIpooE7W+WXu96ax2l2OJvxX8QR7l+LFlKnkIEEJd/ItF1G22UmOjkVwNASTwza/hlY+8DoVvEmwum/nMgH2TwQT3bTQzF9s9DOJkH4d8p4Mw4gEDjNx0EgUFA91ysCAeUMQQyIvuR8HXXa+VcvhOOO5mmBcVhxJ3qUOJTyDBsT0932Zb4mNtkxdigoVxu+iiwk0vwtvKwGVDYdyMP5EAQeEIP1t0w== authority@example.com");
assert_eq!(
known_hosts[3].public_key().comment(),
"authority@example.com"
);
}

504
vendor/ssh-key/tests/private_key.rs vendored Normal file
View File

@@ -0,0 +1,504 @@
//! SSH private key tests.
use hex_literal::hex;
use ssh_key::{Algorithm, Cipher, KdfAlg, PrivateKey};
#[cfg(feature = "ecdsa")]
use ssh_key::EcdsaCurve;
#[cfg(all(feature = "alloc"))]
use ssh_key::LineEnding;
#[cfg(all(feature = "std"))]
use {
ssh_key::PublicKey,
std::{io, path::PathBuf, process},
};
/// DSA OpenSSH-formatted public key
#[cfg(feature = "alloc")]
const OPENSSH_DSA_EXAMPLE: &str = include_str!("examples/id_dsa_1024");
/// ECDSA/P-256 OpenSSH-formatted public key
#[cfg(feature = "ecdsa")]
const OPENSSH_ECDSA_P256_EXAMPLE: &str = include_str!("examples/id_ecdsa_p256");
/// ECDSA/P-384 OpenSSH-formatted public key
#[cfg(feature = "ecdsa")]
const OPENSSH_ECDSA_P384_EXAMPLE: &str = include_str!("examples/id_ecdsa_p384");
/// ECDSA/P-521 OpenSSH-formatted public key
#[cfg(feature = "ecdsa")]
const OPENSSH_ECDSA_P521_EXAMPLE: &str = include_str!("examples/id_ecdsa_p521");
/// Ed25519 OpenSSH-formatted private key
const OPENSSH_ED25519_EXAMPLE: &str = include_str!("examples/id_ed25519");
/// RSA (3072-bit) OpenSSH-formatted public key
#[cfg(feature = "alloc")]
const OPENSSH_RSA_3072_EXAMPLE: &str = include_str!("examples/id_rsa_3072");
/// RSA (4096-bit) OpenSSH-formatted public key
#[cfg(feature = "alloc")]
const OPENSSH_RSA_4096_EXAMPLE: &str = include_str!("examples/id_rsa_4096");
/// OpenSSH-formatted private key with a custom algorithm name
#[cfg(feature = "alloc")]
const OPENSSH_OPAQUE_EXAMPLE: &str = include_str!("examples/id_opaque");
/// Get a path into the `tests/scratch` directory.
#[cfg(feature = "std")]
pub fn scratch_path(filename: &str) -> PathBuf {
PathBuf::from(&format!("tests/scratch/{}", filename))
}
#[cfg(feature = "alloc")]
#[test]
fn decode_dsa_openssh() {
let key = PrivateKey::from_openssh(OPENSSH_DSA_EXAMPLE).unwrap();
assert_eq!(Algorithm::Dsa, key.algorithm());
assert_eq!(Cipher::None, key.cipher());
assert_eq!(KdfAlg::None, key.kdf().algorithm());
assert!(key.kdf().is_none());
let dsa_keypair = key.key_data().dsa().unwrap();
assert_eq!(
&hex!(
"00dc3d89250ed9462114cb2c8d4816e3a511aaff1b06b0e01de17c1cb04e581bcab97176471d89fd7ca1817
e3c48e2ccbafd2170f69e8e5c8b6ab69b9c5f45d95e1d9293e965227eee5b879b1123371c21b1db60f14b5e
5c05a4782ceb43a32f449647703063621e7a286bec95b16726c18b5e52383d00b297a6b03489b06068a5"
),
dsa_keypair.public.p.as_bytes(),
);
assert_eq!(
&hex!("00891815378597fe42d3fd261fe76df365845bbb87"),
dsa_keypair.public.q.as_bytes(),
);
assert_eq!(
&hex!(
"4739b3908a8415466dc7b156fb98ecb71552a170ba0b3b7aa81bd81391de0a7ae7a1b45002dfeadc9225fbc
520a713fe4104a74bed53fd5915da736365afd3f09777bbccfbadf7ac2b087b7f4d95fabe47d72a46e95088
f9cd2a9fbf236b58a6982647f3c00430ad7352d47a25ebbe9477f0c3127da86ad7448644b76de5875c"
),
dsa_keypair.public.g.as_bytes(),
);
assert_eq!(
&hex!(
"6042a6b3fd861344cb21ccccd8719e25aa0be0980e79cbabf4877f5ef071f6039770352eac3d4c368f29daf
a57b475c78d44989f16577527e598334be6aae4abd750c36af80489d392697c1f32f3cf3c9a8b99bcddb53d
7a37e1a28fd53d4934131cf41c437c6734d1e04004adcd925b84b3956c30c3a3904eecb31400b0df48"
),
dsa_keypair.public.y.as_bytes(),
);
assert_eq!(
&hex!("0c377ac449e770d89a3557743cbd050396114b62"),
dsa_keypair.private.as_bytes()
);
assert_eq!("user@example.com", key.comment());
}
#[cfg(feature = "ecdsa")]
#[test]
fn decode_ecdsa_p256_openssh() {
let key = PrivateKey::from_openssh(OPENSSH_ECDSA_P256_EXAMPLE).unwrap();
assert_eq!(
Algorithm::Ecdsa {
curve: EcdsaCurve::NistP256
},
key.algorithm(),
);
assert_eq!(Cipher::None, key.cipher());
assert_eq!(KdfAlg::None, key.kdf().algorithm());
assert!(key.kdf().is_none());
let ecdsa_keypair = key.key_data().ecdsa().unwrap();
assert_eq!(EcdsaCurve::NistP256, ecdsa_keypair.curve());
assert_eq!(
&hex!(
"047c1fd8730ce53457be8d924098ec3648830f92aa8a2363ac656fdd4521fa6313e511f1891b4e9e5aaf8e1
42d06ad15a66a4257f3f051d84e8a0e2f91ba807047"
),
ecdsa_keypair.public_key_bytes(),
);
assert_eq!(
&hex!("ca78a64774bfae37123224937f0398960189707aca0a8645ceb4359c423ba079"),
ecdsa_keypair.private_key_bytes(),
);
#[cfg(feature = "alloc")]
assert_eq!("user@example.com", key.comment());
}
#[cfg(feature = "ecdsa")]
#[test]
fn decode_ecdsa_p384_openssh() {
let key = PrivateKey::from_openssh(OPENSSH_ECDSA_P384_EXAMPLE).unwrap();
assert_eq!(
Algorithm::Ecdsa {
curve: EcdsaCurve::NistP384
},
key.algorithm()
);
assert_eq!(Cipher::None, key.cipher());
assert_eq!(KdfAlg::None, key.kdf().algorithm());
assert!(key.kdf().is_none());
let ecdsa_keypair = key.key_data().ecdsa().unwrap();
assert_eq!(EcdsaCurve::NistP384, ecdsa_keypair.curve());
assert_eq!(
&hex!(
"042e6e82dc5407f104a11117c7c05b1993c3ceb3db25fae68ba169502a4ff9395d9ad36b543e8014ff15d70
8e21f09f585aa6dfad575b79b943418b86198d9bcd9b07fff9399b15d43d34efaeb2e56b7b33cff880b242b
3e0b58af96c75841ec41"
),
ecdsa_keypair.public_key_bytes(),
);
assert_eq!(
&hex!(
"0377d9e9328b2925196977320a2bfe013801897fa0287848af817bdc7f400e8801fd0f9c057d106914b389c
b156f600b"
),
ecdsa_keypair.private_key_bytes(),
);
#[cfg(feature = "alloc")]
assert_eq!("user@example.com", key.comment());
}
#[cfg(feature = "ecdsa")]
#[test]
fn decode_ecdsa_p521_openssh() {
let key = PrivateKey::from_openssh(OPENSSH_ECDSA_P521_EXAMPLE).unwrap();
assert_eq!(
Algorithm::Ecdsa {
curve: EcdsaCurve::NistP521
},
key.algorithm()
);
assert_eq!(Cipher::None, key.cipher());
assert_eq!(KdfAlg::None, key.kdf().algorithm());
assert!(key.kdf().is_none());
let ecdsa_keypair = key.key_data().ecdsa().unwrap();
assert_eq!(EcdsaCurve::NistP521, ecdsa_keypair.curve());
assert_eq!(
&hex!(
"04016136934f192b23d961fbf44c8184166002cea2c7d18b20ad018d046ef068d3e8250fd4e9f17ca6693a8
554c3269a6d9f5762a2f9a2cb8797d4b201de421d3dcc580103cb947a858bb7783df863f82951d96f91a792
5d7e2baad26e47e3f2fa5b07c8272848a4423b750d7ad2b8b692d66ddecaec5385086b1fd1b682ca291c88d
63762"
),
ecdsa_keypair.public_key_bytes(),
);
assert_eq!(
&hex!(
"01ec905f2ab7a9169f161f09e567fcab225bbe6276727a5f2724535c2b663d7ad8e32527d7f5998a992240c
bb90cec3ed67fe902bced588beb972c7716e0927cda82"
),
ecdsa_keypair.private_key_bytes(),
);
#[cfg(feature = "alloc")]
assert_eq!("user@example.com", key.comment());
}
#[test]
fn decode_ed25519_openssh() {
let key = PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
assert_eq!(Algorithm::Ed25519, key.algorithm());
assert_eq!(Cipher::None, key.cipher());
assert_eq!(KdfAlg::None, key.kdf().algorithm());
assert!(key.kdf().is_none());
let ed25519_keypair = key.key_data().ed25519().unwrap();
assert_eq!(
&hex!("b33eaef37ea2df7caa010defdea34e241f65f1b529a4f43ed14327f5c54aab62"),
ed25519_keypair.public.as_ref(),
);
assert_eq!(
&hex!("b606c222d10c16dae16c70a4d45173472ec617e05c656920d26e56c08fb591ed"),
ed25519_keypair.private.as_ref(),
);
#[cfg(feature = "alloc")]
assert_eq!(key.comment(), "user@example.com");
}
#[cfg(feature = "alloc")]
#[test]
fn decode_rsa_3072_openssh() {
let key = PrivateKey::from_openssh(OPENSSH_RSA_3072_EXAMPLE).unwrap();
assert_eq!(Algorithm::Rsa { hash: None }, key.algorithm());
assert_eq!(Cipher::None, key.cipher());
assert_eq!(KdfAlg::None, key.kdf().algorithm());
assert!(key.kdf().is_none());
let rsa_keypair = key.key_data().rsa().unwrap();
assert_eq!(&hex!("010001"), rsa_keypair.public.e.as_bytes());
assert_eq!(
&hex!(
"00a68e478c9bc93726436b7f5e9e6f9a46e1b73bec1e8cb7754de2c6a5b6c455f2f012a7259afcf94181d69
e95d39a349e4d2b482a5372b28943731db75c73ce7bd9eec85010c94bfae56960118922f86a8b3655b357d2
4e7a679cd8a7d9bf6eae66f7f9a56fe3d090d0632218a682960d8aad93c01898780ead2dbefd70fb4703471
7e412e4fdae685292ec891e2423f7fe43df2f54329ab0a5d7561e582e42e86ebaee0c1e9eaf603d7ce70850
5d0ee090912e1fc3735eb5804ddf42b6133107a76e9a59cdfc6b65f43c6302cfbca8e7aa6f97457fa96d3b5
a26e8f41204d2cd42be119c684b0f02370899a71ae3c1e71331543cc3fb2b4268780011ae4ea934c0ff0770
8ee183e7e906fee489e8e1e57fce7a1c6df8fbaef39bbd1955dbd5ad1abffbe126f50205cb884af080ff3d7
0549d3174b85bd7f6624c3753cf235b650d0e4228f32be7b54a590d869fb7786559bb7a4d66f9d3a69c085e
fdf083a915d47a1d9161a08756b263b06e739d99f2890362abc96ade42cce8f939a40daff9"
),
rsa_keypair.public.n.as_bytes(),
);
assert_eq!(
&hex!(
"6b630b10c6950ac0d9f16273103626c392dec07cf2098a73d09ee9b388ceb817e5e030f2d7264a538932669
775925460c8a2a269dfd9f0f0fd932852c4024adca1dc0a3d4d456c7ebd119f064f6443c4f633373865e44c
0331f0f7e3e94a3b43a952331d0eb2551439b7e11101b2eaaa9a8265e41237a418da61c765c345d03875cb1
a9b70177c2ef9268fe9ac8c62c08fa9152a7fe00ccade72a3acf6f004e5b617424a8027922dbc175f228626
29e4727198ca940b3bc24c9268e3ab5f5e5965b8387e1470679b3ea680965f81593cb141310d4c41569e25b
376a2dc4ed92f9149b75e970e8224730946cc20f351f8115b1bbfcbb38f6bd06c620472b76d641d35802ade
f15220ab9b2a57e35918fe27e138119cca56a98ccf3c0fc683a19f2721a8766ecdd9c57677662656f3d3e05
325f3fb37326623dbbec63b3d984830b2dd27bebb6bd2ed5345dfff18df1806adebceda9845804968930681
ac3e523138c5216cb135997e3e143a7816acc3d8741eacec7e15f53da0f0810691708d9d"
),
rsa_keypair.private.d.as_bytes()
);
assert_eq!(
&hex!(
"54405aa663ae9e080035a71002f4c351d7d002c35200725e6dc0ff6d901a304b103a2ea016507996d319358
b5bea4feb4098f530528f12b98c50c7ddfc85fc4af9257baf9aa7235cdf4677349b77e52a40a5e2f44122d1
8ce40941914e99169c48b708898d29869656607b7e2eb63541e0bbd568e4f774bec3137d02a591c8c77b2e1
88dd6f72eef5cff1927cde573a4ca0d43c2b6c6a95721445122e1cf6aa5f05b65cb9c86124f9f79fa29f05e
3f06f3b83edca9941f571650e0fb468aae4c"
),
rsa_keypair.private.iqmp.as_bytes()
);
assert_eq!(
&hex!(
"00d11e7ae248640d3b20293691886544cdfe0779a9aab56c8f9626bf1e6648bfd988bdb0ac7d11a73e34056
336d4ad3900ff7184ee404b84baeb11a2a302f982d94eefb757030ec6d77d9115eaef80ab5749a0f5b590b2
99ffde94f9930dedbab2af333095b08a504b9b30f1112dce51f37ed00d043343d420d2e2fb88bd7f881b7c8
990e48b93fd1d284fcc8c1c07fbefc04d02925b2f159a9a9f567073e1c94fdc6e472f48963be16c5c545385
6ad2bf7916e42c36e75a5018910d8dad038d73"
),
rsa_keypair.private.p.as_bytes()
);
assert_eq!(
&hex!(
"00cbe50e7ecdf5e2c86e76ca94be8b0c05b09041d2bcddeeb4672e7120eacc8380e5d6b77c85583c508f8ee
8d557cabcb6dfae8c72385f0f69345ebc15a5dfec949c0770d02d7945dd3592562da7388662e053c5454d26
90de2a63cc555e1a010e2da0ae307d1c11f852a9c7568e02f93d49b2a8f927b79943b2920cad321aa208410
9d136d085c1d05c39f4c36cf89fdc3c66a755e63f446e16302b13599400f0a83321a2e6b9153df02f03de31
8ea09039282853f2011e0905d1157667caf1e3"
),
rsa_keypair.private.q.as_bytes()
);
assert_eq!("user@example.com", key.comment());
}
#[cfg(feature = "alloc")]
#[test]
fn decode_rsa_4096_openssh() {
let key = PrivateKey::from_openssh(OPENSSH_RSA_4096_EXAMPLE).unwrap();
assert_eq!(Algorithm::Rsa { hash: None }, key.algorithm());
assert_eq!(Cipher::None, key.cipher());
assert_eq!(KdfAlg::None, key.kdf().algorithm());
assert!(key.kdf().is_none());
let rsa_keypair = key.key_data().rsa().unwrap();
assert_eq!(&hex!("010001"), rsa_keypair.public.e.as_bytes());
assert_eq!(
&hex!(
"00b45911edc6ec5e7d2261a48c46ab889b1858306271123e6f02dc914cf3c0352492e8a6b7a7925added527
e547dcebff6d0c19c0bc9153975199f47f4964ed20f5aceed4e82556b228a0c1fbfaa85e6339ba2ff4094d9
4e2b09d43a3dd68225d0bbc858293cbf167b18d6374ebe79220a633d400176f1f6b46fd626acb252bf294aa
db2acd59626a023a8e5ec53ced8685164c72ca3a2ec646812c6e61ffcba740ff15c054f0691e3a8d52c79c4
4b7c1fc6c9704aed09ee0195bf09c5c5ba1173b7b1179be33fb3711d3b82e98f80521367a84303cb1236ebe
8fc095683420a4de652c071d592759d42a0c9d2e73313cdfb71a071c936659433481a406308820e173b934f
be877d873fec24d31a4d3bb9a3645055ca37bf710e214e5fc250d5964c66f18e4f05a3b93f42aa0753bd044
e45b456c0e62fdcc1fcadef72930dc8a7a96b3e27d8eecea139a00aaf2fe79063ccb78d26d537625bdf0c4c
8a68a04ed6f965eef7a6b1da5d8e26fc57f1047b97e2c594a9e420410977f22d1751b6d9498e8e457034049
3c336bf86563ef03a15bc49b0ba6fe73201f64f0413ddb4d0cc5f6cf43389907e1df29e0cc388040e3371d0
4814140f75cac08079431043222fb91f075d76be55cbe138e3b99a605c561c49dea50e253c8306c4f4f77d9
96f898db64c5d8a0a15c6efa28b0934bf0b6f2b01950d877230fe4401078420fd6dd3"
),
rsa_keypair.public.n.as_bytes(),
);
assert_eq!(
&hex!(
"70d639ad77847429fed4f0cb037c5760127f3ae69cb03977e36675529c3f6a00941a14155c36e9bb68bcf06
594c142c1fe22e4ab4b088886879d6cbbcf3f499669ce861354e074c38b73c2797d0b81d8504c4f3fece179
52dc3778a9300905f7ef458e435eca801a4c93daceddc59452c37c930b578c543ad8ae384c5cd600dca8e8b
c9dfe948f5e2a718649b2b5fc1868b4911990d862e6ff66a02363681090855911a610a79fa7bcfe83713c2b
ae6183528d7b938b5eea86f29bfead93994fb96287cef503ea159fa0986be168fbf1402dbaa028f22082c1a
6cf80dd66f8637cf3d18c677fd72ea97d4849387670b1b3dc87f2295e6b77aa0e36be8a37cc864f2786dfaa
3c4522836e4433d8dd9c464c155a78ac19e49b01f56959003baacd5183c0aeef1ff0da9988feaa1db7aadfd
5e243ea5095d3448f5411e198ff29e2bafda1c26007effe369686171615625af5634dc98ce81ed024ea559d
8bfefc6e7172a9d1409273f94d0235b2e76bb41a532db6ce9f0a28d4eb0db70abced95462eec5e222d3b3e6
1c330a9c97913a7de628524e3daa24ce93d2acf9440e03c57063e3c7509332addf37d5c840375a0b9de1d68
822cdcf88b44cd6aea8bfc646ce52f9d05e7e867a32d462e35a163c15b7df00e9c0a870345b86e7882971b4
d79d42507ade7c26e6db29f52fbe58430f915c554145faa950ae6b6e4f87bf24a61"
),
rsa_keypair.private.d.as_bytes()
);
assert_eq!(
&hex!(
"580f3580a2ad54f7e4390a99a05b377730aebe631cd41f6452424e03763d2d43af327f919aa96bf748a3041
fd6f76b471b4b8029ebac01df18692b1612c5d046640083ab123546495bbfab77d5f9a4b8ebeffce997417e
a5625b070be1cf8c5b253edd826be6042ee1f71a13b72e8df6fdcb7f8a945ef5929a4c790803bc31feff24f
8f148926ea3aa02c690889baeeb1e727295642f13955067fee400b230876252fd9dcf1f56a4307d3d717cf0
235833fdc93947a2b4ed45d43df51087d91d59eb0bf09fe6f45036b23c944addce2976b805425c6841129be
5b17c4dcc41d62daa053d06a1fbfd3c20543a63066ad69933ae64538c305ae645d81557a6f3c9"
),
rsa_keypair.private.iqmp.as_bytes()
);
assert_eq!(
&hex!(
"00e2b7aa95621ec065acd1b9edd46090c715e1d212f11ac24f61c3016a4b411a25c635007654dc19a145531
f9d49f796965a28f67575a5a9bf852b53474c4345cf604d40b614e31d50f0ca56414f152b49d6b92d8767d4
70a5a10afb6e546189d6e99739aeff7a081d96fd5c1646c5abbb8481df936c65aad51a553596e16f49b09f8
8175d2c938f92ecaccc61313523fd678533007f05cab51dfd16cfaf3439033bd3a4d845c08e34097b6f7ecd
0613082e7d1830f936e29c7865c2b8acd30870dd20679788e0b2aaa2285d35ea7347c4083e2ee9c92dcb11e
ea114245c5f22d7afeb9d51cbc0ca17116261fac8a8f3c3054da1f53ad297f8ce184663ec4e617d"
),
rsa_keypair.private.p.as_bytes()
);
assert_eq!(
&hex!(
"00cba436332637becfdbdec249dbc121e5309c9964f2053c221b58b601846afd7cc8b788d6bf9b71345b1bd
de7b367204e010ee60c2126352476ce98899b72035eb5f2ae8dd9754dd500354c418cbbf75dfd4bf2029a9a
3c8e097efdb334e8228a738b1c3fac43b4822364a54b4c348042369b59cf086b25db23226f71edeae58e77f
c6f10493641c4254c28999be5628cd74e259d5fe5d39c98a9c0b8543bd58c89bb34ea19e18af714f1446e29
3d09881ed7fa5f49b374bcab97dafa067e8eb63bc9ddf2668bf3ebb2bb585d7b12ff591e6ff34889196b9e5
293809f168d681bb7b09680fef093c8a28ef0d25568fce4ab5e879fee21a7525ac08caf9efa2d8f"
),
rsa_keypair.private.q.as_bytes()
);
assert_eq!("user@example.com", key.comment());
}
#[cfg(all(feature = "alloc"))]
#[test]
fn decode_custom_algorithm_openssh() {
let key = PrivateKey::from_openssh(OPENSSH_OPAQUE_EXAMPLE).unwrap();
assert!(
matches!(key.algorithm(), Algorithm::Other(name) if name.as_str() == "name@example.com")
);
assert_eq!(Cipher::None, key.cipher());
assert_eq!(KdfAlg::None, key.kdf().algorithm());
assert!(key.kdf().is_none());
let opaque_keypair = key.key_data().other().unwrap();
assert_eq!(
&hex!("888f24ee17adfed0091e67e485fb9844cfed6072cac1d06390e4005f5015b44f"),
opaque_keypair.public.as_ref(),
);
assert_eq!(
&hex!("986c953b4b5efb3285ff207c1ca5ee39a59047bc488fbc3b1ef036efc7575c75"),
opaque_keypair.private.as_ref(),
);
assert_eq!(key.comment(), "comment@example.com");
}
#[cfg(all(feature = "alloc"))]
#[test]
fn encode_dsa_openssh() {
encoding_test(OPENSSH_DSA_EXAMPLE)
}
#[cfg(all(feature = "alloc", feature = "ecdsa"))]
#[test]
fn encode_ecdsa_p256_openssh() {
encoding_test(OPENSSH_ECDSA_P256_EXAMPLE)
}
#[cfg(all(feature = "alloc", feature = "ecdsa"))]
#[test]
fn encode_ecdsa_p384_openssh() {
encoding_test(OPENSSH_ECDSA_P384_EXAMPLE)
}
#[cfg(all(feature = "alloc", feature = "ecdsa"))]
#[test]
fn encode_ecdsa_p521_openssh() {
encoding_test(OPENSSH_ECDSA_P521_EXAMPLE)
}
#[cfg(all(feature = "alloc"))]
#[test]
fn encode_ed25519_openssh() {
encoding_test(OPENSSH_ED25519_EXAMPLE)
}
#[cfg(all(feature = "alloc"))]
#[test]
fn encode_rsa_3072_openssh() {
encoding_test(OPENSSH_RSA_3072_EXAMPLE)
}
#[cfg(all(feature = "alloc"))]
#[test]
fn encode_rsa_4096_openssh() {
encoding_test(OPENSSH_RSA_4096_EXAMPLE)
}
#[cfg(all(feature = "alloc"))]
#[test]
fn encode_custom_algorithm_openssh() {
encoding_test(OPENSSH_OPAQUE_EXAMPLE)
}
/// Common behavior of all encoding tests
#[cfg(all(feature = "alloc"))]
fn encoding_test(private_key: &str) {
let key = PrivateKey::from_openssh(private_key).unwrap();
// Ensure key round-trips
let pem = key.to_openssh(LineEnding::LF).unwrap();
let key2 = PrivateKey::from_openssh(&*pem).unwrap();
assert_eq!(key, key2);
#[cfg(feature = "std")]
if !matches!(key.algorithm(), Algorithm::Other(_)) {
encoding_integration_test(key)
}
}
/// Parse PEM encoded using `PrivateKey::to_openssh` using the `ssh-keygen` utility.
#[cfg(all(feature = "std"))]
fn encoding_integration_test(private_key: PrivateKey) {
let fingerprint = private_key
.fingerprint(Default::default())
.to_string()
.replace(':', "-")
.replace('/', "_");
let path = scratch_path(&fingerprint);
private_key
.write_openssh_file(&path, LineEnding::LF)
.unwrap();
let public_key = match process::Command::new("ssh-keygen")
.args(["-y", "-f", path.to_str().unwrap()])
.output()
{
Ok(output) => {
assert_eq!(output.status.code().unwrap(), 0);
let ssh_keygen_output = std::str::from_utf8(&output.stdout).unwrap();
PublicKey::from_openssh(ssh_keygen_output).unwrap()
}
Err(err) => {
if err.kind() == io::ErrorKind::NotFound {
eprintln!("couldn't find 'ssh-keygen'! skipping test");
return;
} else {
panic!("error invoking ssh-keygen: {}", err)
}
}
};
// Ensure ssh-keygen successfully parsed our public key
assert_eq!(&public_key, private_key.public_key());
}

455
vendor/ssh-key/tests/public_key.rs vendored Normal file
View File

@@ -0,0 +1,455 @@
//! SSH public key tests.
use hex_literal::hex;
#[cfg(feature = "alloc")]
use ssh_key::public::{Ed25519PublicKey, SkEd25519};
use ssh_key::{Algorithm, PublicKey};
use std::collections::HashSet;
#[cfg(all(feature = "ecdsa", feature = "alloc"))]
use {sec1::consts::U32, ssh_key::public::SkEcdsaSha2NistP256};
#[cfg(feature = "ecdsa")]
use ssh_key::EcdsaCurve;
#[cfg(feature = "std")]
use std::{fs, path::PathBuf};
/// DSA OpenSSH-formatted public key
#[cfg(feature = "alloc")]
const OPENSSH_DSA_EXAMPLE: &str = include_str!("examples/id_dsa_1024.pub");
/// ECDSA/NIST P-256 OpenSSH-formatted public key
#[cfg(feature = "ecdsa")]
const OPENSSH_ECDSA_P256_EXAMPLE: &str = include_str!("examples/id_ecdsa_p256.pub");
/// ECDSA/NIST P-384 OpenSSH-formatted public key
#[cfg(feature = "ecdsa")]
const OPENSSH_ECDSA_P384_EXAMPLE: &str = include_str!("examples/id_ecdsa_p384.pub");
/// ECDSA/NIST P-521 OpenSSH-formatted public key
#[cfg(feature = "ecdsa")]
const OPENSSH_ECDSA_P521_EXAMPLE: &str = include_str!("examples/id_ecdsa_p521.pub");
/// Ed25519 OpenSSH-formatted public key
const OPENSSH_ED25519_EXAMPLE: &str = include_str!("examples/id_ed25519.pub");
/// RSA (3072-bit) OpenSSH-formatted public key
#[cfg(feature = "alloc")]
const OPENSSH_RSA_3072_EXAMPLE: &str = include_str!("examples/id_rsa_3072.pub");
/// RSA (4096-bit) OpenSSH-formatted public key
#[cfg(feature = "alloc")]
const OPENSSH_RSA_4096_EXAMPLE: &str = include_str!("examples/id_rsa_4096.pub");
/// Security Key (FIDO/U2F) ECDSA/NIST P-256 OpenSSH-formatted public key
#[cfg(feature = "ecdsa")]
const OPENSSH_SK_ECDSA_P256_EXAMPLE: &str = include_str!("examples/id_sk_ecdsa_p256.pub");
/// Security Key (FIDO/U2F) Ed25519 OpenSSH-formatted public key
const OPENSSH_SK_ED25519_EXAMPLE: &str = include_str!("examples/id_sk_ed25519.pub");
/// OpenSSH-formatted public key with a custom algorithm name
#[cfg(feature = "alloc")]
const OPENSSH_OPAQUE_EXAMPLE: &str = include_str!("examples/id_opaque.pub");
/// Get a path into the `tests/scratch` directory.
#[cfg(feature = "std")]
pub fn scratch_path(filename: &str) -> PathBuf {
PathBuf::from(&format!("tests/scratch/{}.pub", filename))
}
#[cfg(feature = "alloc")]
#[test]
fn decode_dsa_openssh() {
let key = PublicKey::from_openssh(OPENSSH_DSA_EXAMPLE).unwrap();
assert_eq!(Algorithm::Dsa, key.key_data().algorithm());
let dsa_key = key.key_data().dsa().unwrap();
assert_eq!(
&hex!(
"00dc3d89250ed9462114cb2c8d4816e3a511aaff1b06b0e01de17c1cb04e581bcab97176471d89fd7ca1817
e3c48e2ccbafd2170f69e8e5c8b6ab69b9c5f45d95e1d9293e965227eee5b879b1123371c21b1db60f14b5e
5c05a4782ceb43a32f449647703063621e7a286bec95b16726c18b5e52383d00b297a6b03489b06068a5"
),
dsa_key.p.as_bytes(),
);
assert_eq!(
&hex!("00891815378597fe42d3fd261fe76df365845bbb87"),
dsa_key.q.as_bytes(),
);
assert_eq!(
&hex!(
"4739b3908a8415466dc7b156fb98ecb71552a170ba0b3b7aa81bd81391de0a7ae7a1b45002dfeadc9225fbc
520a713fe4104a74bed53fd5915da736365afd3f09777bbccfbadf7ac2b087b7f4d95fabe47d72a46e95088
f9cd2a9fbf236b58a6982647f3c00430ad7352d47a25ebbe9477f0c3127da86ad7448644b76de5875c"
),
dsa_key.g.as_bytes(),
);
assert_eq!(
&hex!(
"6042a6b3fd861344cb21ccccd8719e25aa0be0980e79cbabf4877f5ef071f6039770352eac3d4c368f29daf
a57b475c78d44989f16577527e598334be6aae4abd750c36af80489d392697c1f32f3cf3c9a8b99bcddb53d
7a37e1a28fd53d4934131cf41c437c6734d1e04004adcd925b84b3956c30c3a3904eecb31400b0df48"
),
dsa_key.y.as_bytes(),
);
assert_eq!("user@example.com", key.comment());
assert_eq!(
"SHA256:Nh0Me49Zh9fDw/VYUfq43IJmI1T+XrjiYONPND8GzaM",
&key.fingerprint(Default::default()).to_string(),
);
}
#[cfg(feature = "ecdsa")]
#[test]
fn decode_ecdsa_p256_openssh() {
let key = PublicKey::from_openssh(OPENSSH_ECDSA_P256_EXAMPLE).unwrap();
assert_eq!(
Algorithm::Ecdsa {
curve: EcdsaCurve::NistP256
},
key.key_data().algorithm(),
);
let ecdsa_key = key.key_data().ecdsa().unwrap();
assert_eq!(EcdsaCurve::NistP256, ecdsa_key.curve());
assert_eq!(
&hex!(
"047c1fd8730ce53457be8d924098ec3648830f92aa8a2363ac656fdd4521fa6313e511f1891b4e9e5aaf8e1
42d06ad15a66a4257f3f051d84e8a0e2f91ba807047"
),
ecdsa_key.as_ref(),
);
#[cfg(feature = "alloc")]
assert_eq!("user@example.com", key.comment());
assert_eq!(
"SHA256:JQ6FV0rf7qqJHZqIj4zNH8eV0oB8KLKh9Pph3FTD98g",
&key.fingerprint(Default::default()).to_string(),
);
}
#[cfg(feature = "ecdsa")]
#[test]
fn decode_ecdsa_p384_openssh() {
let key = PublicKey::from_openssh(OPENSSH_ECDSA_P384_EXAMPLE).unwrap();
assert_eq!(
Algorithm::Ecdsa {
curve: EcdsaCurve::NistP384
},
key.key_data().algorithm(),
);
let ecdsa_key = key.key_data().ecdsa().unwrap();
assert_eq!(EcdsaCurve::NistP384, ecdsa_key.curve());
assert_eq!(
&hex!(
"042e6e82dc5407f104a11117c7c05b1993c3ceb3db25fae68ba169502a4ff9395d9ad36b543e8014ff15d70
8e21f09f585aa6dfad575b79b943418b86198d9bcd9b07fff9399b15d43d34efaeb2e56b7b33cff880b242b
3e0b58af96c75841ec41"
),
ecdsa_key.as_ref(),
);
#[cfg(feature = "alloc")]
assert_eq!("user@example.com", key.comment());
assert_eq!(
"SHA256:nkGE8oV7pHvOiPKHtQRs67WUPiVLRxbNu//gV/k4Vjw",
&key.fingerprint(Default::default()).to_string(),
);
}
#[cfg(feature = "ecdsa")]
#[test]
fn decode_ecdsa_p521_openssh() {
let key = PublicKey::from_openssh(OPENSSH_ECDSA_P521_EXAMPLE).unwrap();
assert_eq!(
Algorithm::Ecdsa {
curve: EcdsaCurve::NistP521
},
key.key_data().algorithm(),
);
let ecdsa_key = key.key_data().ecdsa().unwrap();
assert_eq!(ecdsa_key.curve(), EcdsaCurve::NistP521);
assert_eq!(
&hex!(
"04016136934f192b23d961fbf44c8184166002cea2c7d18b20ad018d046ef068d3e8250fd4e9f17ca6693a8
554c3269a6d9f5762a2f9a2cb8797d4b201de421d3dcc580103cb947a858bb7783df863f82951d96f91a792
5d7e2baad26e47e3f2fa5b07c8272848a4423b750d7ad2b8b692d66ddecaec5385086b1fd1b682ca291c88d
63762"
),
ecdsa_key.as_ref(),
);
#[cfg(feature = "alloc")]
assert_eq!("user@example.com", key.comment());
assert_eq!(
"SHA256:l3AUUMK6Q2BbuiqvMx2fs97f8LUYq7sWCAx7q5m3S6M",
&key.fingerprint(Default::default()).to_string(),
);
}
#[test]
fn decode_ed25519_openssh() {
let key = PublicKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
assert_eq!(Algorithm::Ed25519, key.key_data().algorithm());
assert_eq!(
&hex!("b33eaef37ea2df7caa010defdea34e241f65f1b529a4f43ed14327f5c54aab62"),
key.key_data().ed25519().unwrap().as_ref(),
);
#[cfg(feature = "alloc")]
assert_eq!("user@example.com", key.comment());
assert_eq!(
"SHA256:UCUiLr7Pjs9wFFJMDByLgc3NrtdU344OgUM45wZPcIQ",
&key.fingerprint(Default::default()).to_string(),
);
}
#[cfg(feature = "alloc")]
#[test]
fn decode_rsa_3072_openssh() {
let key = PublicKey::from_openssh(OPENSSH_RSA_3072_EXAMPLE).unwrap();
assert_eq!(Algorithm::Rsa { hash: None }, key.key_data().algorithm());
let rsa_key = key.key_data().rsa().unwrap();
assert_eq!(&hex!("010001"), rsa_key.e.as_bytes());
assert_eq!(
&hex!(
"00a68e478c9bc93726436b7f5e9e6f9a46e1b73bec1e8cb7754de2c6a5b6c455f2f012a7259afcf94181d69
e95d39a349e4d2b482a5372b28943731db75c73ce7bd9eec85010c94bfae56960118922f86a8b3655b357d2
4e7a679cd8a7d9bf6eae66f7f9a56fe3d090d0632218a682960d8aad93c01898780ead2dbefd70fb4703471
7e412e4fdae685292ec891e2423f7fe43df2f54329ab0a5d7561e582e42e86ebaee0c1e9eaf603d7ce70850
5d0ee090912e1fc3735eb5804ddf42b6133107a76e9a59cdfc6b65f43c6302cfbca8e7aa6f97457fa96d3b5
a26e8f41204d2cd42be119c684b0f02370899a71ae3c1e71331543cc3fb2b4268780011ae4ea934c0ff0770
8ee183e7e906fee489e8e1e57fce7a1c6df8fbaef39bbd1955dbd5ad1abffbe126f50205cb884af080ff3d7
0549d3174b85bd7f6624c3753cf235b650d0e4228f32be7b54a590d869fb7786559bb7a4d66f9d3a69c085e
fdf083a915d47a1d9161a08756b263b06e739d99f2890362abc96ade42cce8f939a40daff9"
),
rsa_key.n.as_bytes(),
);
assert_eq!("user@example.com", key.comment());
assert_eq!(
"SHA256:Fmxts/GcV77PakFnf1Ueki5mpU4ZjUQWGRjZGAo3n/I",
&key.fingerprint(Default::default()).to_string(),
);
}
#[cfg(feature = "alloc")]
#[test]
fn decode_rsa_4096_openssh() {
let key = PublicKey::from_openssh(OPENSSH_RSA_4096_EXAMPLE).unwrap();
assert_eq!(Algorithm::Rsa { hash: None }, key.key_data().algorithm());
let rsa_key = key.key_data().rsa().unwrap();
assert_eq!(&hex!("010001"), rsa_key.e.as_bytes());
assert_eq!(
&hex!(
"00b45911edc6ec5e7d2261a48c46ab889b1858306271123e6f02dc914cf3c0352492e8a6b7a7925added527
e547dcebff6d0c19c0bc9153975199f47f4964ed20f5aceed4e82556b228a0c1fbfaa85e6339ba2ff4094d9
4e2b09d43a3dd68225d0bbc858293cbf167b18d6374ebe79220a633d400176f1f6b46fd626acb252bf294aa
db2acd59626a023a8e5ec53ced8685164c72ca3a2ec646812c6e61ffcba740ff15c054f0691e3a8d52c79c4
4b7c1fc6c9704aed09ee0195bf09c5c5ba1173b7b1179be33fb3711d3b82e98f80521367a84303cb1236ebe
8fc095683420a4de652c071d592759d42a0c9d2e73313cdfb71a071c936659433481a406308820e173b934f
be877d873fec24d31a4d3bb9a3645055ca37bf710e214e5fc250d5964c66f18e4f05a3b93f42aa0753bd044
e45b456c0e62fdcc1fcadef72930dc8a7a96b3e27d8eecea139a00aaf2fe79063ccb78d26d537625bdf0c4c
8a68a04ed6f965eef7a6b1da5d8e26fc57f1047b97e2c594a9e420410977f22d1751b6d9498e8e457034049
3c336bf86563ef03a15bc49b0ba6fe73201f64f0413ddb4d0cc5f6cf43389907e1df29e0cc388040e3371d0
4814140f75cac08079431043222fb91f075d76be55cbe138e3b99a605c561c49dea50e253c8306c4f4f77d9
96f898db64c5d8a0a15c6efa28b0934bf0b6f2b01950d877230fe4401078420fd6dd3"
),
rsa_key.n.as_bytes(),
);
assert_eq!("user@example.com", key.comment());
assert_eq!(
"SHA256:FKAyeywtQNZLl1YTzIzCV/ThadBlnWMaD7jHQYDseEY",
&key.fingerprint(Default::default()).to_string(),
);
}
#[cfg(feature = "ecdsa")]
#[test]
fn decode_sk_ecdsa_p256_openssh() {
let key = PublicKey::from_openssh(OPENSSH_SK_ECDSA_P256_EXAMPLE).unwrap();
assert_eq!(Algorithm::SkEcdsaSha2NistP256, key.key_data().algorithm());
let ecdsa_key = key.key_data().sk_ecdsa_p256().unwrap();
assert_eq!(
&hex!(
"04810b409d8382f697d72425285a247d6336b2eb9a085236aa9d1e268747ca0e8ee227f17375e944a775392
f1d35842d13f6237574ab03e00e9cc1799ecd8d931e"
),
ecdsa_key.ec_point().as_ref(),
);
assert_eq!("ssh:", ecdsa_key.application());
#[cfg(feature = "alloc")]
assert_eq!("user@example.com", key.comment());
assert_eq!(
"SHA256:UINe2WXFh3SiqwLxsBv34fBO2ei+g7uOeJJXVEK95iE",
&key.fingerprint(Default::default()).to_string(),
);
}
#[cfg(all(feature = "ecdsa", feature = "alloc"))]
#[test]
fn new_sk_ecdsa_p256() {
const EXAMPLE_EC_POINT: [u8; 65] = [
0x04, 0x81, 0x0b, 0x40, 0x9d, 0x83, 0x82, 0xf6, 0x97, 0xd7, 0x24, 0x25, 0x28, 0x5a, 0x24,
0x7d, 0x63, 0x36, 0xb2, 0xeb, 0x9a, 0x08, 0x52, 0x36, 0xaa, 0x9d, 0x1e, 0x26, 0x87, 0x47,
0xca, 0x0e, 0x8e, 0xe2, 0x27, 0xf1, 0x73, 0x75, 0xe9, 0x44, 0xa7, 0x75, 0x39, 0x2f, 0x1d,
0x35, 0x84, 0x2d, 0x13, 0xf6, 0x23, 0x75, 0x74, 0xab, 0x03, 0xe0, 0x0e, 0x9c, 0xc1, 0x79,
0x9e, 0xcd, 0x8d, 0x93, 0x1e,
];
let ec_point = sec1::EncodedPoint::<U32>::from_bytes(&EXAMPLE_EC_POINT).unwrap();
let sk_key = SkEcdsaSha2NistP256::new(ec_point, "ssh:".to_string());
let key = PublicKey::from_openssh(OPENSSH_SK_ECDSA_P256_EXAMPLE).unwrap();
let ecdsa_key = key.key_data().sk_ecdsa_p256().unwrap();
assert_eq!(&sk_key, ecdsa_key);
}
#[test]
fn decode_sk_ed25519_openssh() {
let key = PublicKey::from_openssh(OPENSSH_SK_ED25519_EXAMPLE).unwrap();
assert_eq!(Algorithm::SkEd25519, key.key_data().algorithm());
let ed25519_key = key.key_data().sk_ed25519().unwrap();
assert_eq!(
&hex!("2168fe4e4b53cf3adeeeba602f5e50edb5ef441dba884f5119109db2dafdd733"),
ed25519_key.public_key().as_ref(),
);
assert_eq!("ssh:", ed25519_key.application());
#[cfg(feature = "alloc")]
assert_eq!("user@example.com", key.comment());
assert_eq!(
"SHA256:6WZVJ44bqhAWLVP4Ns0TDkoSQSsZo/h2K+mEvOaNFbw",
&key.fingerprint(Default::default()).to_string(),
);
}
#[cfg(feature = "alloc")]
#[test]
fn new_sk_ed25519_openssh() {
const EXAMPLE_PUBKEY: Ed25519PublicKey = Ed25519PublicKey {
0: [
0x21, 0x68, 0xfe, 0x4e, 0x4b, 0x53, 0xcf, 0x3a, 0xde, 0xee, 0xba, 0x60, 0x2f, 0x5e,
0x50, 0xed, 0xb5, 0xef, 0x44, 0x1d, 0xba, 0x88, 0x4f, 0x51, 0x19, 0x10, 0x9d, 0xb2,
0xda, 0xfd, 0xd7, 0x33,
],
};
let sk_key = SkEd25519::new(EXAMPLE_PUBKEY, "ssh:".to_string());
let key = PublicKey::from_openssh(OPENSSH_SK_ED25519_EXAMPLE).unwrap();
let ed25519_key = key.key_data().sk_ed25519().unwrap();
assert_eq!(&sk_key, ed25519_key);
}
#[cfg(all(feature = "alloc"))]
#[test]
fn decode_custom_algorithm_openssh() {
let key = PublicKey::from_openssh(OPENSSH_OPAQUE_EXAMPLE).unwrap();
assert!(
matches!(key.algorithm(), Algorithm::Other(name) if name.as_str() == "name@example.com")
);
let opaque_key = key.key_data().other().unwrap();
assert_eq!(
&hex!("888f24ee17adfed0091e67e485fb9844cfed6072cac1d06390e4005f5015b44f"),
opaque_key.as_ref(),
);
assert_eq!("comment@example.com", key.comment());
assert_eq!(
"SHA256:8GV7v5qOHG9invseKCx0NVwFocNL0MwdyRC9bfjTFGs",
&key.fingerprint(Default::default()).to_string(),
);
}
#[cfg(feature = "alloc")]
#[test]
fn encode_dsa_openssh() {
let key = PublicKey::from_openssh(OPENSSH_DSA_EXAMPLE).unwrap();
assert_eq!(OPENSSH_DSA_EXAMPLE.trim_end(), &key.to_string());
}
#[cfg(all(feature = "alloc", feature = "ecdsa"))]
#[test]
fn encode_ecdsa_p256_openssh() {
let key = PublicKey::from_openssh(OPENSSH_ECDSA_P256_EXAMPLE).unwrap();
assert_eq!(OPENSSH_ECDSA_P256_EXAMPLE.trim_end(), &key.to_string());
}
#[cfg(all(feature = "alloc", feature = "ecdsa"))]
#[test]
fn encode_ecdsa_p384_openssh() {
let key = PublicKey::from_openssh(OPENSSH_ECDSA_P384_EXAMPLE).unwrap();
assert_eq!(OPENSSH_ECDSA_P384_EXAMPLE.trim_end(), &key.to_string());
}
#[cfg(all(feature = "alloc", feature = "ecdsa"))]
#[test]
fn encode_ecdsa_p521_openssh() {
let key = PublicKey::from_openssh(OPENSSH_ECDSA_P521_EXAMPLE).unwrap();
assert_eq!(OPENSSH_ECDSA_P521_EXAMPLE.trim_end(), &key.to_string());
}
#[cfg(feature = "alloc")]
#[test]
fn encode_ed25519_openssh() {
let key = PublicKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
assert_eq!(OPENSSH_ED25519_EXAMPLE.trim_end(), &key.to_string());
}
#[cfg(feature = "alloc")]
#[test]
fn encode_rsa_3072_openssh() {
let key = PublicKey::from_openssh(OPENSSH_RSA_3072_EXAMPLE).unwrap();
assert_eq!(OPENSSH_RSA_3072_EXAMPLE.trim_end(), &key.to_string());
}
#[cfg(feature = "alloc")]
#[test]
fn encode_rsa_4096_openssh() {
let key = PublicKey::from_openssh(OPENSSH_RSA_4096_EXAMPLE).unwrap();
assert_eq!(OPENSSH_RSA_4096_EXAMPLE.trim_end(), &key.to_string());
}
#[test]
fn public_keys_are_hashable() {
let key = PublicKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
let set = HashSet::from([&key]);
assert_eq!(true, set.contains(&key));
}
#[cfg(feature = "std")]
#[test]
fn write_openssh_file() {
let example_key = OPENSSH_ED25519_EXAMPLE;
let key = PublicKey::from_openssh(example_key).unwrap();
let fingerprint = key
.fingerprint(Default::default())
.to_string()
.replace(':', "-")
.replace('/', "_");
let path = scratch_path(&fingerprint);
key.write_openssh_file(&path).unwrap();
assert_eq!(example_key, fs::read_to_string(&path).unwrap());
}

0
vendor/ssh-key/tests/scratch/.gitkeep vendored Normal file
View File

341
vendor/ssh-key/tests/sshsig.rs vendored Normal file
View File

@@ -0,0 +1,341 @@
//! `sshsig` signature tests.
#![cfg(feature = "alloc")]
use hex_literal::hex;
use ssh_key::{Algorithm, HashAlg, LineEnding, PublicKey, SshSig};
#[cfg(any(
feature = "dsa",
feature = "ed25519",
feature = "p256",
feature = "rsa"
))]
use {encoding::Decode, signature::Verifier, ssh_key::PrivateKey, ssh_key::Signature};
#[cfg(feature = "ed25519")]
use ssh_key::Error;
/// DSA OpenSSH-formatted private key.
#[cfg(feature = "dsa")]
const DSA_PRIVATE_KEY: &str = include_str!("examples/id_dsa_1024");
/// DSA OpenSSH-formatted public key.
#[cfg(feature = "dsa")]
const DSA_PUBLIC_KEY: &str = include_str!("examples/id_dsa_1024.pub");
/// ECDSA/P-256 OpenSSH-formatted private key.
#[cfg(feature = "p256")]
const ECDSA_P256_PRIVATE_KEY: &str = include_str!("examples/id_ecdsa_p256");
/// ECDSA/P-256 OpenSSH-formatted public key.
#[cfg(feature = "p256")]
const ECDSA_P256_PUBLIC_KEY: &str = include_str!("examples/id_ecdsa_p256.pub");
/// Ed25519 OpenSSH-formatted private key.
#[cfg(feature = "ed25519")]
const ED25519_PRIVATE_KEY: &str = include_str!("examples/id_ed25519");
/// Ed25519 OpenSSH-formatted public key.
const ED25519_PUBLIC_KEY: &str = include_str!("examples/id_ed25519.pub");
/// `sshsig`-encoded signature.
const ED25519_SIGNATURE: &str = include_str!("examples/sshsig_ed25519");
/// Bytes of the raw Ed25519 signature.
const ED25519_SIGNATURE_BYTES: [u8; 64] = hex!(
"4f11abfeb4c18d9e8c7832eccceeb947c9505a8c29fc074900ca2396c0f2a9ac"
"db06de2e97fafa33fd60928a4fc5a30630aa18020015094af457dc011154150f"
);
/// SkEd25519 OpenSSH-formatted public key.
const SK_ED25519_PUBLIC_KEY: &str = include_str!("examples/id_sk_ed25519_2.pub");
#[cfg(feature = "p256")]
const SK_ECDSA_P256_PUBLIC_KEY: &str = include_str!("examples/id_sk_ecdsa_p256_2.pub");
/// `sshsig`-encoded signature.
const SK_ED25519_SIGNATURE: &str = include_str!("examples/sshsig_sk_ed25519");
/// Bytes of the raw SkEd25519 signature.
const SK_ED25519_SIGNATURE_BYTES: [u8; 69] = hex!(
"2f5670b6f93465d17423878a74084bf331767031ed240c627c8eb79ab8fa1b93"
"5a1fd993f52f5a13fec1797f8a434f943a6096246aea8dd5c8aa922cba3d9506"
"0100000009"
);
/// RSA OpenSSH-formatted private key.
#[cfg(feature = "rsa")]
const RSA_PRIVATE_KEY: &str = include_str!("examples/id_rsa_3072");
/// RSA OpenSSH-formatted public key.
#[cfg(feature = "rsa")]
const RSA_PUBLIC_KEY: &str = include_str!("examples/id_rsa_3072.pub");
/// Example message to be signed/verified.
#[allow(dead_code)]
const MSG_EXAMPLE: &[u8] = b"testing";
/// Example domain/namespace used for the message.
const NAMESPACE_EXAMPLE: &str = "example";
#[cfg(feature = "p256")]
const SK_ECDSA_SIGNATURE_OPENSSH_WIRE: [u8; 120] = hex!(
"00000022736b2d65636473612d736861322d6e69737470323536406f70656e73"
"73682e636f6d00000049000000201b35a1c6469a43a3d09d490d6ff8ca1bc248"
"6a2edeb8aa7d119e4c70b9c1811000000021009724a2a4449a90357485ed1df0"
"161274d20083342b02756794bc3f068fcdc15e01000000ec"
);
/// An ssh-agent signature response signing MSG_EXAMPLE with DSA_PRIVATE_KEY
#[cfg(feature = "dsa")]
const DSA_SIGNATURE_OPENSSH_WIRE: [u8; 55] = hex!(
"000000077373682d647373000000282d0c9613d9745c6088ae4d9e8dbf35a557"
"7bd0e6796acccb22ab4809d569e86ec619510ec48b6950"
);
/// An ssh-agent signature response signing MSG_EXAMPLE with RSA_PRIVATE_KEY
#[cfg(feature = "rsa")]
const RSA_SIGNATURE_OPENSSH_WIRE: [u8; 404] = hex!(
"0000000c7273612d736861322d353132000001804ebc4f9fe2bfa1badd9f6b80"
"df806e6f93a31d4af7b15637d4b15e0ac180271467d5ab7a864fc48dedabf6dd"
"8f318a9f36824f84cba1353f453c23d6a60431aa9cc243c849cc33c9e358418b"
"9fe833bb8985ac35d6b72a7960097bff5e02263c4076f31eb0e64bf2a02fc85f"
"d75a569e13e167e29543e101e1f84254e60f0841f7843cf6e461a1ce06d1f590"
"c9446358ef04dfa25ec98b2c14393c9267684c6a568425bb6245d0a0dd44f9fd"
"bf352cb70eba53c6b2aaff8890a22d8769fd253b3d4c6a19237d2b7f6ae08557"
"a7e7cca3e78bef33f3f8a86adbce79713221911c9647c126d5511b0f5c1f9133"
"0a6015f3bf9a27d5afea84a499e9e4a1c058355c09d2ce5ff441638596b4447c"
"717db04b6365dff0d6f9a0123e9304b033c404b2f4709446c71adc0acc3c042b"
"f221ae7446f2371bd40937be31da77c04027c3be1bbd4ec8ac77cd5d453fbca1"
"c9805d54f4b8348549bf480892cc6430ba13f9483361632b82ae54829bdfa435"
"4d7ac8daa4f05b03039d140ff4fb88f5e5499ee5"
);
/// An ssh-agent signature response signing MSG_EXAMPLE with ECDSA_P256_PRIVATE_KEY
#[cfg(feature = "p256")]
const ECDSA_P256_SIGNATURE_OPENSSH_WIRE: [u8; 100] = hex!(
"0000001365636473612d736861322d6e69737470323536000000490000002100"
"f8291cf8859e0776394431c2a20d9efe80938844decfb7f29617475bc739c832"
"0000002038228f9c5cde47a7daf510f423ab6b8457fff1907c13af4cabf27a8f"
"3df7d99c"
);
/// An ssh-agent signature response signing MSG_EXAMPLE with ED25519_PRIVATE_KEY
#[cfg(feature = "ed25519")]
const ED25519_SIGNATURE_OPENSSH_WIRE: [u8; 83] = hex!(
"0000000b7373682d6564323535313900000040e4d03342608fdb46fb6ab5b0aa"
"07dfecae8ee2a7ce8514065f580aec85c325795e9f65415d7554ee7929f43b5a"
"9fc9f13874d8f2e2158c22dfd66d3ab92ede0d"
);
#[test]
fn decode_ed25519() {
let sshsig = ED25519_SIGNATURE.parse::<SshSig>().unwrap();
let public_key = ED25519_PUBLIC_KEY.parse::<PublicKey>().unwrap();
assert_eq!(sshsig.algorithm(), Algorithm::Ed25519);
assert_eq!(sshsig.version(), 1);
assert_eq!(sshsig.public_key(), public_key.key_data());
assert_eq!(sshsig.namespace(), NAMESPACE_EXAMPLE);
assert_eq!(sshsig.reserved(), &[]);
assert_eq!(sshsig.hash_alg(), HashAlg::Sha512);
assert_eq!(sshsig.signature_bytes(), ED25519_SIGNATURE_BYTES);
}
#[test]
fn encode_ed25519() {
let sshsig = ED25519_SIGNATURE.parse::<SshSig>().unwrap();
let sshsig_pem = sshsig.to_pem(LineEnding::LF).unwrap();
assert_eq!(&sshsig_pem, ED25519_SIGNATURE);
}
#[test]
fn decode_sk_ed25519() {
let sshsig = SK_ED25519_SIGNATURE.parse::<SshSig>().unwrap();
let public_key = SK_ED25519_PUBLIC_KEY.parse::<PublicKey>().unwrap();
assert_eq!(sshsig.algorithm(), Algorithm::SkEd25519);
assert_eq!(sshsig.version(), 1);
assert_eq!(sshsig.public_key(), public_key.key_data());
assert_eq!(sshsig.namespace(), NAMESPACE_EXAMPLE);
assert_eq!(sshsig.reserved(), &[]);
assert_eq!(sshsig.hash_alg(), HashAlg::Sha512);
assert_eq!(sshsig.signature_bytes(), SK_ED25519_SIGNATURE_BYTES);
}
#[test]
fn encode_sk_ed25519() {
let sshsig = SK_ED25519_SIGNATURE.parse::<SshSig>().unwrap();
let sshsig_pem = sshsig.to_pem(LineEnding::LF).unwrap();
assert_eq!(&sshsig_pem, SK_ED25519_SIGNATURE);
}
#[test]
#[cfg(feature = "dsa")]
fn sign_dsa() {
let signing_key = PrivateKey::from_openssh(DSA_PRIVATE_KEY).unwrap();
let verifying_key = DSA_PUBLIC_KEY.parse::<PublicKey>().unwrap();
let signature = signing_key
.sign(NAMESPACE_EXAMPLE, HashAlg::Sha512, MSG_EXAMPLE)
.unwrap();
assert_eq!(
verifying_key.verify(NAMESPACE_EXAMPLE, MSG_EXAMPLE, &signature),
Ok(())
);
}
#[test]
#[cfg(feature = "p256")]
fn verify_sk_ecdsa_openssh_wire_format() {
let signature = Signature::decode(&mut SK_ECDSA_SIGNATURE_OPENSSH_WIRE.as_ref()).unwrap();
let verifying_key = SK_ECDSA_P256_PUBLIC_KEY.parse::<PublicKey>().unwrap();
verifying_key
.key_data()
.verify(MSG_EXAMPLE, &signature)
.expect("failed to validate valid signature");
verifying_key
.key_data()
.verify(b"Bogus!", &signature)
.expect_err("good signature from bogus data");
}
#[test]
#[cfg(feature = "dsa")]
fn verify_dsa_openssh_wire_format() {
let signature = Signature::decode(&mut DSA_SIGNATURE_OPENSSH_WIRE.as_ref()).unwrap();
let verifying_key = DSA_PUBLIC_KEY.parse::<PublicKey>().unwrap();
verifying_key
.key_data()
.verify(MSG_EXAMPLE, &signature)
.unwrap();
}
#[test]
#[cfg(feature = "p256")]
fn sign_ecdsa_p256() {
let signing_key = PrivateKey::from_openssh(ECDSA_P256_PRIVATE_KEY).unwrap();
let verifying_key = ECDSA_P256_PUBLIC_KEY.parse::<PublicKey>().unwrap();
let signature = signing_key
.sign(NAMESPACE_EXAMPLE, HashAlg::Sha512, MSG_EXAMPLE)
.unwrap();
assert_eq!(
verifying_key.verify(NAMESPACE_EXAMPLE, MSG_EXAMPLE, &signature),
Ok(())
);
}
#[test]
#[cfg(feature = "p256")]
fn verify_ecdsa_p256_openssh_wire_format() {
let signature = Signature::decode(&mut ECDSA_P256_SIGNATURE_OPENSSH_WIRE.as_ref()).unwrap();
let verifying_key = ECDSA_P256_PUBLIC_KEY.parse::<PublicKey>().unwrap();
verifying_key
.key_data()
.verify(MSG_EXAMPLE, &signature)
.unwrap();
}
#[test]
#[cfg(feature = "ed25519")]
fn sign_ed25519() {
let signing_key = PrivateKey::from_openssh(ED25519_PRIVATE_KEY).unwrap();
let signature = signing_key
.sign(NAMESPACE_EXAMPLE, HashAlg::Sha512, MSG_EXAMPLE)
.unwrap();
assert_eq!(signature, ED25519_SIGNATURE.parse::<SshSig>().unwrap());
}
#[test]
#[cfg(feature = "ed25519")]
fn verify_ed25519_openssh_wire_format() {
let signature = Signature::decode(&mut ED25519_SIGNATURE_OPENSSH_WIRE.as_ref()).unwrap();
let verifying_key = ED25519_PUBLIC_KEY.parse::<PublicKey>().unwrap();
verifying_key
.key_data()
.verify(MSG_EXAMPLE, &signature)
.unwrap();
}
#[test]
#[cfg(feature = "rsa")]
fn sign_rsa() {
let signing_key = PrivateKey::from_openssh(RSA_PRIVATE_KEY).unwrap();
let verifying_key = RSA_PUBLIC_KEY.parse::<PublicKey>().unwrap();
let signature = signing_key
.sign(NAMESPACE_EXAMPLE, HashAlg::Sha512, MSG_EXAMPLE)
.unwrap();
assert_eq!(
verifying_key.verify(NAMESPACE_EXAMPLE, MSG_EXAMPLE, &signature),
Ok(())
);
}
#[test]
#[cfg(feature = "rsa")]
fn verify_rsa_openssh_wire_format() {
let signature = Signature::decode(&mut RSA_SIGNATURE_OPENSSH_WIRE.as_ref()).unwrap();
let verifying_key = RSA_PUBLIC_KEY.parse::<PublicKey>().unwrap();
verifying_key
.key_data()
.verify(MSG_EXAMPLE, &signature)
.unwrap();
}
#[test]
#[cfg(feature = "ed25519")]
fn verify_ed25519() {
let verifying_key = ED25519_PUBLIC_KEY.parse::<PublicKey>().unwrap();
let signature = ED25519_SIGNATURE.parse::<SshSig>().unwrap();
// valid
assert_eq!(
verifying_key.verify(NAMESPACE_EXAMPLE, MSG_EXAMPLE, &signature),
Ok(())
);
// bad namespace
assert_eq!(
verifying_key.verify("bogus namespace", MSG_EXAMPLE, &signature),
Err(Error::Namespace)
);
// invalid message
assert_eq!(
verifying_key.verify(NAMESPACE_EXAMPLE, b"bogus!", &signature),
Err(Error::Crypto)
);
}
#[test]
#[cfg(feature = "ed25519")]
fn verify_sk_ed25519() {
let verifying_key = SK_ED25519_PUBLIC_KEY.parse::<PublicKey>().unwrap();
let signature = SK_ED25519_SIGNATURE.parse::<SshSig>().unwrap();
// valid
assert_eq!(
verifying_key.verify(NAMESPACE_EXAMPLE, MSG_EXAMPLE, &signature),
Ok(())
);
// bad namespace
assert_eq!(
verifying_key.verify("bogus namespace", MSG_EXAMPLE, &signature),
Err(Error::Namespace)
);
// invalid message
assert_eq!(
verifying_key.verify(NAMESPACE_EXAMPLE, b"bogus!", &signature),
Err(Error::Crypto)
);
}