1use ssh_key::PublicKey;
4
5#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
7#[non_exhaustive]
8pub enum SshKeyError {
9 #[error("Malformed or invalid OpenSSH public key: {0}")]
10 InvalidFormat(String),
11
12 #[error("Unsupported key type: expected ssh-ed25519 or ecdsa-sha2-nistp256")]
13 UnsupportedKeyType,
14}
15
16impl crate::AuthsErrorInfo for SshKeyError {
17 fn error_code(&self) -> &'static str {
18 match self {
19 Self::InvalidFormat(_) => "AUTHS-E1301",
20 Self::UnsupportedKeyType => "AUTHS-E1302",
21 }
22 }
23
24 fn suggestion(&self) -> Option<&'static str> {
25 match self {
26 Self::InvalidFormat(_) => Some("Check that the public key is a valid OpenSSH format"),
27 Self::UnsupportedKeyType => {
28 Some("Supported key types: ssh-ed25519, ecdsa-sha2-nistp256")
29 }
30 }
31 }
32}
33
34pub fn openssh_pub_to_raw(openssh_pub: &str) -> Result<(crate::CurveType, Vec<u8>), SshKeyError> {
49 let public_key = PublicKey::from_openssh(openssh_pub)
50 .map_err(|e| SshKeyError::InvalidFormat(e.to_string()))?;
51
52 if let Some(ed) = public_key.key_data().ed25519() {
53 return Ok((crate::CurveType::Ed25519, ed.0.to_vec()));
54 }
55
56 if let Some(ssh_key::public::EcdsaPublicKey::NistP256(point)) = public_key.key_data().ecdsa() {
57 return Ok((crate::CurveType::P256, point.as_ref().to_vec()));
58 }
59
60 Err(SshKeyError::UnsupportedKeyType)
61}