ssh_key/private/
opaque.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//! Opaque private keys.
//!
//! [`OpaqueKeypair`] represents a keypair meant to be used with an algorithm unknown to this
//! crate, i.e. keypairs that use a custom algorithm as specified in [RFC4251 § 6].
//!
//! They are said to be opaque, because the meaning of their underlying byte representation is not
//! specified.
//!
//! [RFC4251 § 6]: https://www.rfc-editor.org/rfc/rfc4251.html#section-6

use crate::{
    public::{OpaquePublicKey, OpaquePublicKeyBytes},
    Algorithm, Error, Result,
};
use alloc::vec::Vec;
use core::fmt;
use encoding::{CheckedSum, Decode, Encode, Reader, Writer};
use subtle::{Choice, ConstantTimeEq};

/// An opaque private key.
///
/// The encoded representation of an `OpaquePrivateKeyBytes` consists of a 4-byte length prefix,
/// followed by its byte representation.
#[derive(Clone)]
pub struct OpaquePrivateKeyBytes(Vec<u8>);

/// An opaque keypair.
///
/// The encoded representation of an `OpaqueKeypair` consists of the encoded representation of its
/// [`OpaquePublicKey`] followed by the encoded representation of its [`OpaquePrivateKeyBytes`].
#[derive(Clone)]
pub struct OpaqueKeypair {
    /// The opaque private key
    pub private: OpaquePrivateKeyBytes,
    /// The opaque public key
    pub public: OpaquePublicKey,
}

/// The underlying representation of an [`OpaqueKeypair`].
///
/// The encoded representation of an `OpaqueKeypairBytes` consists of the encoded representation of
/// its [`OpaquePublicKeyBytes`] followed by the encoded representation of its
/// [`OpaquePrivateKeyBytes`].
pub struct OpaqueKeypairBytes {
    /// The opaque private key
    pub private: OpaquePrivateKeyBytes,
    /// The opaque public key
    pub public: OpaquePublicKeyBytes,
}

impl OpaqueKeypair {
    /// Create a new `OpaqueKeypair`.
    pub fn new(private_key: Vec<u8>, public: OpaquePublicKey) -> Self {
        Self {
            private: OpaquePrivateKeyBytes(private_key),
            public,
        }
    }

    /// Get the [`Algorithm`] for this key type.
    pub fn algorithm(&self) -> Algorithm {
        self.public.algorithm()
    }

    /// Decode [`OpaqueKeypair`] for the specified algorithm.
    pub(super) fn decode_as(reader: &mut impl Reader, algorithm: Algorithm) -> Result<Self> {
        let key = OpaqueKeypairBytes::decode(reader)?;
        let public = OpaquePublicKey {
            algorithm,
            key: key.public,
        };

        Ok(Self {
            public,
            private: key.private,
        })
    }
}

impl Decode for OpaquePrivateKeyBytes {
    type Error = Error;

    fn decode(reader: &mut impl Reader) -> Result<Self> {
        let len = usize::decode(reader)?;
        let mut bytes = vec![0; len];
        reader.read(&mut bytes)?;
        Ok(Self(bytes))
    }
}

impl Decode for OpaqueKeypairBytes {
    type Error = Error;

    fn decode(reader: &mut impl Reader) -> Result<Self> {
        let public = OpaquePublicKeyBytes::decode(reader)?;
        let private = OpaquePrivateKeyBytes::decode(reader)?;

        Ok(Self { public, private })
    }
}

impl Encode for OpaqueKeypair {
    fn encoded_len(&self) -> encoding::Result<usize> {
        [self.public.encoded_len()?, self.private.encoded_len()?].checked_sum()
    }

    fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
        self.public.encode(writer)?;
        self.private.encode(writer)?;

        Ok(())
    }
}

impl ConstantTimeEq for OpaqueKeypair {
    fn ct_eq(&self, other: &Self) -> Choice {
        Choice::from((self.public == other.public) as u8) & self.private.ct_eq(&other.private)
    }
}

impl Encode for OpaquePrivateKeyBytes {
    fn encoded_len(&self) -> encoding::Result<usize> {
        self.0.encoded_len()
    }

    fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
        self.0.encode(writer)
    }
}

impl From<&OpaqueKeypair> for OpaquePublicKey {
    fn from(keypair: &OpaqueKeypair) -> OpaquePublicKey {
        keypair.public.clone()
    }
}

impl fmt::Debug for OpaqueKeypair {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("OpaqueKeypair")
            .field("public", &self.public)
            .finish_non_exhaustive()
    }
}

impl ConstantTimeEq for OpaquePrivateKeyBytes {
    fn ct_eq(&self, other: &Self) -> Choice {
        self.as_ref().ct_eq(other.as_ref())
    }
}

impl AsRef<[u8]> for OpaquePrivateKeyBytes {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}