ssh_key/private/
opaque.rs

1//! Opaque private keys.
2//!
3//! [`OpaqueKeypair`] represents a keypair meant to be used with an algorithm unknown to this
4//! crate, i.e. keypairs that use a custom algorithm as specified in [RFC4251 § 6].
5//!
6//! They are said to be opaque, because the meaning of their underlying byte representation is not
7//! specified.
8//!
9//! [RFC4251 § 6]: https://www.rfc-editor.org/rfc/rfc4251.html#section-6
10
11use crate::{
12    public::{OpaquePublicKey, OpaquePublicKeyBytes},
13    Algorithm, Error, Result,
14};
15use alloc::vec::Vec;
16use core::fmt;
17use encoding::{CheckedSum, Decode, Encode, Reader, Writer};
18use subtle::{Choice, ConstantTimeEq};
19
20/// An opaque private key.
21///
22/// The encoded representation of an `OpaquePrivateKeyBytes` consists of a 4-byte length prefix,
23/// followed by its byte representation.
24#[derive(Clone)]
25pub struct OpaquePrivateKeyBytes(Vec<u8>);
26
27/// An opaque keypair.
28///
29/// The encoded representation of an `OpaqueKeypair` consists of the encoded representation of its
30/// [`OpaquePublicKey`] followed by the encoded representation of its [`OpaquePrivateKeyBytes`].
31#[derive(Clone)]
32pub struct OpaqueKeypair {
33    /// The opaque private key
34    pub private: OpaquePrivateKeyBytes,
35    /// The opaque public key
36    pub public: OpaquePublicKey,
37}
38
39/// The underlying representation of an [`OpaqueKeypair`].
40///
41/// The encoded representation of an `OpaqueKeypairBytes` consists of the encoded representation of
42/// its [`OpaquePublicKeyBytes`] followed by the encoded representation of its
43/// [`OpaquePrivateKeyBytes`].
44pub struct OpaqueKeypairBytes {
45    /// The opaque private key
46    pub private: OpaquePrivateKeyBytes,
47    /// The opaque public key
48    pub public: OpaquePublicKeyBytes,
49}
50
51impl OpaqueKeypair {
52    /// Create a new `OpaqueKeypair`.
53    pub fn new(private_key: Vec<u8>, public: OpaquePublicKey) -> Self {
54        Self {
55            private: OpaquePrivateKeyBytes(private_key),
56            public,
57        }
58    }
59
60    /// Get the [`Algorithm`] for this key type.
61    pub fn algorithm(&self) -> Algorithm {
62        self.public.algorithm()
63    }
64
65    /// Decode [`OpaqueKeypair`] for the specified algorithm.
66    pub(super) fn decode_as(reader: &mut impl Reader, algorithm: Algorithm) -> Result<Self> {
67        let key = OpaqueKeypairBytes::decode(reader)?;
68        let public = OpaquePublicKey {
69            algorithm,
70            key: key.public,
71        };
72
73        Ok(Self {
74            public,
75            private: key.private,
76        })
77    }
78}
79
80impl Decode for OpaquePrivateKeyBytes {
81    type Error = Error;
82
83    fn decode(reader: &mut impl Reader) -> Result<Self> {
84        let len = usize::decode(reader)?;
85        let mut bytes = vec![0; len];
86        reader.read(&mut bytes)?;
87        Ok(Self(bytes))
88    }
89}
90
91impl Decode for OpaqueKeypairBytes {
92    type Error = Error;
93
94    fn decode(reader: &mut impl Reader) -> Result<Self> {
95        let public = OpaquePublicKeyBytes::decode(reader)?;
96        let private = OpaquePrivateKeyBytes::decode(reader)?;
97
98        Ok(Self { public, private })
99    }
100}
101
102impl Encode for OpaqueKeypair {
103    fn encoded_len(&self) -> encoding::Result<usize> {
104        [self.public.encoded_len()?, self.private.encoded_len()?].checked_sum()
105    }
106
107    fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
108        self.public.encode(writer)?;
109        self.private.encode(writer)?;
110
111        Ok(())
112    }
113}
114
115impl ConstantTimeEq for OpaqueKeypair {
116    fn ct_eq(&self, other: &Self) -> Choice {
117        Choice::from((self.public == other.public) as u8) & self.private.ct_eq(&other.private)
118    }
119}
120
121impl Encode for OpaquePrivateKeyBytes {
122    fn encoded_len(&self) -> encoding::Result<usize> {
123        self.0.encoded_len()
124    }
125
126    fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
127        self.0.encode(writer)
128    }
129}
130
131impl From<&OpaqueKeypair> for OpaquePublicKey {
132    fn from(keypair: &OpaqueKeypair) -> OpaquePublicKey {
133        keypair.public.clone()
134    }
135}
136
137impl fmt::Debug for OpaqueKeypair {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        f.debug_struct("OpaqueKeypair")
140            .field("public", &self.public)
141            .finish_non_exhaustive()
142    }
143}
144
145impl ConstantTimeEq for OpaquePrivateKeyBytes {
146    fn ct_eq(&self, other: &Self) -> Choice {
147        self.as_ref().ct_eq(other.as_ref())
148    }
149}
150
151impl AsRef<[u8]> for OpaquePrivateKeyBytes {
152    fn as_ref(&self) -> &[u8] {
153        &self.0
154    }
155}