UHAEQPZUODJ5YVBZJPPJVLO7EBW6DC2JXHQBN26ARELAVULG3JUQC LDEEJH5L2QGDPOAASR6FZ7NYHZF56ZPUYMXVCKXCRGTICVCJU4EAC TAOFQAIISOBF3NJ5BG72NRG5JSTIJN4X2QZXFPB75US6WTFSK7DQC 7FRJYUI62VW257VVFQXND6OKSAILVTHGEJCXFE6CG6FIOIUTDVYAC MCS77Y4VJGB6TU2HOLASGSRW4B6MT74XABD4KYALIRS54GGN2DDQC 2WEO7OZLWJJPUYK4WXLT5FD46G2MAEIHEYMDW5GASCBUNKOPXCVAC ORSEEVB5ZBACWJH7J3BPQOLZVNNHBQU3A24VNQXI4TU4SUEVQ2JQC WXZWQLGLNQ3QRHMBH7YPTHKSPUST4HD34H3PW5E4LHQYH3KLNHYAC NHOSLQGG4CIWBE7VKL5MB7PSY3RZ5IVDFENMGZG6X755GGZ6B3VQC KGIUIQYIBBUEGBOQIFYJJNZGGSPV3KERBPYTKKCOBKZZ5CHIJ24AC -----END OPENSSH PRIVATE KEY-----";#[cfg(feature = "p256")]const P256_KEY: &'static str = "-----BEGIN OPENSSH PRIVATE KEY-----b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABAhkrrfr9PH+vNievobev0EAAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHtLt3JSpJSWyg7Tvx7LNuWEjX8lFJDupLh14RwWzy5TaiVMM4iF+gZlzM12r6mVwWdQq9fTcN/QhElyR4m34oIAAACwe18misSLWNBpkWsNwQD9+wZx6w4YHykv/hA1v4B1iavk176z4JwtzwnS0sDSW+ME2HEpO7uJMlAc1ZItX9W+dRdFjPkKYibMCCcylOIUrjqWkhFnFOpHrTsiyuIwBFwSrfis8r2AX5xbEsDf+t3612/JMMTJMUvqsK9hxR6SrT73CS2W4/UbAQ1O0b7eDShH9zMyiMC4lYecRu6GNGRltIpY3hqCB6di+lzu6iPrMEE=
#[cfg(feature = "p256")]pub const PKCS8_P256: &'static str = "-----BEGIN ENCRYPTED PRIVATE KEY-----MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAh155uUbhbyFQICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEL4PGMOq8KM573vkRzh8GSMEgZBt6UPxhwgoiSqXdlfe/1hTzVKFjpFQNe5UUXxPHlw1a7+24sPzHwqY39tVWlbNO4QR0bwebnTG8/pMR2X/3Hch2d/okVlfpeqYTyiBcbW1nXAJtK+eorZ80P2UCHD/X7sjiLhibttN17vvg7HZPqf9wQm+Mef97nmP13oEFU3s856haS3T0OVVh+d+dpLuntM=-----END ENCRYPTED PRIVATE KEY-----";
#[cfg(feature = "p256")]fn test_client_agent_p256() {let key = decode_secret_key(PKCS8_P256, Some("blabla")).unwrap();test_client_agent(key)}#[test]#[cfg(feature = "p256")]fn test_client_agent_openssh_p256() {let key = decode_secret_key(P256_KEY, Some("blabla")).unwrap();test_client_agent(key)}#[test]
b"ecdsa-sha2-nistp256" if cfg!(feature = "p256") => {#[cfg(feature = "p256")]{let mut p = pubkey.reader(0);let key_algo = p.read_string()?;let identifier = p.read_string()?;if key_algo != b"ecdsa-sha2-nistp256" || identifier != b"nistp256" {debug!("Rejecting {identifier:?} for not being nistp256");return Err(Error::CouldNotReadKey.into());}let sec1_bytes = p.read_string()?;return p256::PublicKey::from_sec1_bytes(sec1_bytes).map(PublicKey::P256).map_err(|e| {debug!("from_sec1_bytes failure: {e:?}");Error::CouldNotReadKey});}#[cfg(not(feature = "p256"))]unreachable!();}
}#[cfg(feature = "p256")]&PublicKey::P256(ref public) => {let mut reader = sig.reader(0);let mut concat = [0u8; 64];// Ad-hoc reading of mpints:// - We only consider the last 32 bytes => leading 0 is still treated fine// - We implicitly pad missing leading bytes as 0, which is also fine for a modular valuematch reader.read_mpint() {Ok(r) => r.into_iter().rev().enumerate().for_each(|(i, b)| {if i < 32 {concat[31 - i] = *b;}}),Err(_) => {debug!("Malformed scalar: r");return false;}};match reader.read_mpint() {Ok(s) => s.into_iter().rev().enumerate().for_each(|(i, b)| {if i < 32 {concat[63 - i] = *b;}}),Err(_) => {debug!("Malformed scalar: s");return false;}};p256::ecdsa::Signature::from_slice(&concat).and_then(|sig| {p256::ecdsa::VerifyingKey::from(public).verify(buffer, &sig).map(|()| true)}).unwrap_or(false)
#[cfg(feature = "p256")]&KeyPair::P256(ref secret) => {let sig = p256::ecdsa::SigningKey::from(secret).sign_recoverable(to_sign)?.0;let mut bytes = vec![];bytes.extend_ssh_mpint(&sig.r().as_ref().to_bytes());bytes.extend_ssh_mpint(&sig.s().as_ref().to_bytes());Ok(Signature::P256(bytes))}
}#[cfg(feature = "p256")]&KeyPair::P256(ref secret) => {let sig = p256::ecdsa::SigningKey::from(secret).sign_recoverable(to_sign.as_ref())?.0.to_bytes();buffer.push_u32_be((ECDSA_SHA2_NISTP256.0.len() + sig.len() + 8) as u32);buffer.extend_ssh_string(ECDSA_SHA2_NISTP256.0.as_bytes());buffer.extend_ssh_string(&sig);
#[cfg(feature = "p256")]&KeyPair::P256(ref secret) => {let sig = p256::ecdsa::SigningKey::from(secret).sign_recoverable(&buffer)?.0.to_bytes();buffer.push_u32_be((ECDSA_SHA2_NISTP256.0.len() + sig.len() + 8) as u32);buffer.extend_ssh_string(ECDSA_SHA2_NISTP256.0.as_bytes());buffer.extend_ssh_string(&sig);}
if oid.components().as_slice() == RSA {let seq = &reader.next().read_bytes()?;let rsa: Result<Rsa<Private>, Error> = yasna::parse_der(seq, |reader| {reader.read_sequence(|reader| {let version = reader.next().read_u32()?;if version != 0 {return Ok(Err(Error::CouldNotReadKey.into()));}use openssl::bn::BigNum;let mut read_key = || -> Result<Rsa<Private>, Error> {Ok(Rsa::from_private_components(BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,)?)};Ok(read_key())
if oid.components().as_slice() == RSA && cfg!(feature = "openssl") {#[cfg(feature = "openssl")]{let seq = &reader.next().read_bytes()?;let rsa: Result<Rsa<Private>, Error> = yasna::parse_der(seq, |reader| {reader.read_sequence(|reader| {let version = reader.next().read_u32()?;if version != 0 {return Ok(Err(Error::CouldNotReadKey.into()));}use openssl::bn::BigNum;let mut read_key = || -> Result<Rsa<Private>, Error> {Ok(Rsa::from_private_components(BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,BigNum::from_slice(&reader.next().read_biguint()?.to_bytes_be())?,)?)};Ok(read_key())})})?;Ok(key::KeyPair::RSA {key: rsa?,hash: SignatureHash::SHA2_256,
})?;Ok(key::KeyPair::RSA {key: rsa?,hash: SignatureHash::SHA2_256,})
}#[cfg(not(feature = "openssl"))]unreachable!()} else if oid.components().as_slice() == P256 && cfg!(feature = "p256") {#[cfg(feature = "p256")]{let bytes = &reader.next().read_bytes()?;Ok(key::KeyPair::P256(p256::SecretKey::from_sec1_der(bytes)?))}#[cfg(not(feature = "p256"))]unreachable!()
});}} else if key_type == KEYTYPE_P256 && cfg!(feature = "p256") {#[cfg(feature = "p256")]{let _nistp256 = position.read_string()?;let pub_bytes = position.read_string()?;let sec_bytes = position.read_mpint()?;let _comment = position.read_string()?;let mut key_bytes = [0u8; 32];// Reading mpints in a naive way, but sufficient for modular values heresec_bytes.into_iter().rev().enumerate().for_each(|(i, b)| {if i < 32 {key_bytes[31 - i] = *b;}
#[cfg(feature = "p256")]b"ecdsa-sha2-nistp256" => {let public_ = r.read_string()?;let pos1 = r.position;let priv_ = r.read_mpint()?;let _comment = r.read_string()?;let mut priv_bytes = [0u8; 32];priv_.into_iter().rev().enumerate().for_each(|(i, b)| {if i < 32 {priv_bytes[31 - i] = *b;}});let key =crate::key::KeyPair::P256(p256::SecretKey::from_bytes(&priv_bytes.into())?);if public_ != crate::PublicKeyBase64::public_key_bytes(&key) {return Ok(false);}(self.buf[pos0..pos1].to_vec(), key)}
self.buf.extend_ssh_string(b"");}#[cfg(feature = "p256")]key::KeyPair::P256(ref key) => {self.buf.extend_ssh_string(b"ecdsa-sha2-nistp256");self.buf.extend_ssh_string(b"nistp256");let bytes = key.public_key().to_sec1_bytes();self.buf.extend_ssh_string(&bytes);self.buf.extend_ssh_mpint(&key.to_bytes());
#[cfg(feature = "p256")]PublicKey::P256(ref key) => {buf.extend(&[0, 0, 0, 0]);let len0 = buf.len();buf.extend_ssh_string(b"ecdsa-sha2-nistp256");let mut inner_buf = vec![];inner_buf.extend_ssh_string(b"nistp256");inner_buf.extend_ssh_string(&key.to_sec1_bytes());buf.extend(&inner_buf);let len1 = buf.len();BigEndian::write_u32(&mut buf[5..], (len1 - len0) as u32);}
#[cfg(feature = "openssl")]
#[cfg(all(feature = "openssl", feature = "p256"))]pub const DEFAULT: Preferred = Preferred {kex: &[kex::CURVE25519],key: &[key::ED25519,key::ECDSA_SHA2_NISTP256,key::RSA_SHA2_256,key::RSA_SHA2_512,],cipher: &[cipher::chacha20poly1305::NAME],mac: &["none"],compression: &["none", "zlib", "zlib@openssh.com"],};#[cfg(all(not(feature = "openssl"), feature = "p256"))]pub const DEFAULT: Preferred = Preferred {kex: &[kex::CURVE25519],key: &[key::ED25519, key::ECDSA_SHA2_NISTP256],cipher: &[cipher::chacha20poly1305::NAME],mac: &["none"],compression: &["none", "zlib", "zlib@openssh.com"],};#[cfg(all(feature = "openssl", not(feature = "p256")))]