russh_keys/
key.rs

1// Copyright 2016 Pierre-Étienne Meunier
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15use ssh_encoding::Decode;
16use ssh_key::public::KeyData;
17use ssh_key::{Algorithm, EcdsaCurve, HashAlg, PublicKey};
18
19use crate::Error;
20
21pub trait PublicKeyExt {
22    fn decode(bytes: &[u8]) -> Result<PublicKey, Error>;
23}
24
25impl PublicKeyExt for PublicKey {
26    fn decode(mut bytes: &[u8]) -> Result<PublicKey, Error> {
27        let key = KeyData::decode(&mut bytes)?;
28        Ok(PublicKey::new(key, ""))
29    }
30}
31
32#[doc(hidden)]
33pub trait Verify {
34    fn verify_client_auth(&self, buffer: &[u8], sig: &[u8]) -> bool;
35    fn verify_server_auth(&self, buffer: &[u8], sig: &[u8]) -> bool;
36}
37
38/// Parse a public key from a byte slice.
39pub fn parse_public_key(mut p: &[u8]) -> Result<PublicKey, Error> {
40    use ssh_encoding::Decode;
41    Ok(ssh_key::public::KeyData::decode(&mut p)?.into())
42}
43
44/// Obtain a cryptographic-safe random number generator.
45pub fn safe_rng() -> impl rand::CryptoRng + rand::RngCore {
46    rand::thread_rng()
47}
48
49mod private_key_with_hash_alg {
50    use std::ops::Deref;
51    use std::sync::Arc;
52
53    use ssh_key::Algorithm;
54
55    use crate::helpers::AlgorithmExt;
56
57    /// Helper structure to correlate a key and (in case of RSA) a hash algorithm.
58    /// Only used for authentication, not key storage as RSA keys do not inherently
59    /// have a hash algorithm associated with them.
60    #[derive(Clone, Debug)]
61    pub struct PrivateKeyWithHashAlg {
62        key: Arc<crate::PrivateKey>,
63        hash_alg: Option<crate::HashAlg>,
64    }
65
66    impl PrivateKeyWithHashAlg {
67        pub fn new(
68            key: Arc<crate::PrivateKey>,
69            hash_alg: Option<crate::HashAlg>,
70        ) -> Result<Self, crate::Error> {
71            if hash_alg.is_some() && !key.algorithm().is_rsa() {
72                return Err(crate::Error::InvalidParameters);
73            }
74            Ok(Self { key, hash_alg })
75        }
76
77        pub fn algorithm(&self) -> Algorithm {
78            self.key.algorithm().with_hash_alg(self.hash_alg)
79        }
80
81        pub fn hash_alg(&self) -> Option<crate::HashAlg> {
82            self.hash_alg
83        }
84    }
85
86    impl Deref for PrivateKeyWithHashAlg {
87        type Target = crate::PrivateKey;
88
89        fn deref(&self) -> &Self::Target {
90            &self.key
91        }
92    }
93}
94
95pub use private_key_with_hash_alg::PrivateKeyWithHashAlg;
96
97pub const ALL_KEY_TYPES: &[Algorithm] = &[
98    Algorithm::Dsa,
99    Algorithm::Ecdsa {
100        curve: EcdsaCurve::NistP256,
101    },
102    Algorithm::Ecdsa {
103        curve: EcdsaCurve::NistP384,
104    },
105    Algorithm::Ecdsa {
106        curve: EcdsaCurve::NistP521,
107    },
108    Algorithm::Ed25519,
109    Algorithm::Rsa { hash: None },
110    Algorithm::Rsa {
111        hash: Some(HashAlg::Sha256),
112    },
113    Algorithm::Rsa {
114        hash: Some(HashAlg::Sha512),
115    },
116    Algorithm::SkEcdsaSha2NistP256,
117    Algorithm::SkEd25519,
118];