cardano_serialization_lib/chain_crypto/
key.rs

1use crate::chain_crypto::bech32::{self, Bech32};
2use hex::FromHexError;
3use rand_os::rand_core::{CryptoRng, RngCore};
4use std::fmt;
5use std::hash::Hash;
6use std::str::FromStr;
7
8#[derive(Debug, Copy, Clone, PartialEq, Eq)]
9pub enum SecretKeyError {
10    SizeInvalid,
11    StructureInvalid,
12}
13
14#[derive(Debug, Copy, Clone, PartialEq, Eq)]
15pub enum PublicKeyError {
16    SizeInvalid,
17    StructureInvalid,
18}
19
20#[derive(Debug, Clone, PartialEq)]
21pub enum PublicKeyFromStrError {
22    HexMalformed(FromHexError),
23    KeyInvalid(PublicKeyError),
24}
25
26pub trait AsymmetricPublicKey {
27    type Public: AsRef<[u8]> + Clone + PartialEq + Eq + Hash;
28    const PUBLIC_BECH32_HRP: &'static str;
29    const PUBLIC_KEY_SIZE: usize;
30
31    fn public_from_binary(data: &[u8]) -> Result<Self::Public, PublicKeyError>;
32}
33
34pub trait AsymmetricKey {
35    // The name of the public key Algorithm to represent the public key
36    // where PubAlg::Public is the public key type.
37    type PubAlg: AsymmetricPublicKey;
38
39    // the secret key type
40    type Secret: AsRef<[u8]> + Clone;
41
42    const SECRET_BECH32_HRP: &'static str;
43
44    fn generate<T: RngCore + CryptoRng>(rng: T) -> Self::Secret;
45    fn compute_public(secret: &Self::Secret) -> <Self::PubAlg as AsymmetricPublicKey>::Public;
46    fn secret_from_binary(data: &[u8]) -> Result<Self::Secret, SecretKeyError>;
47}
48
49pub trait SecretKeySizeStatic: AsymmetricKey {
50    const SECRET_KEY_SIZE: usize;
51}
52
53pub struct SecretKey<A: AsymmetricKey>(pub(crate) A::Secret);
54
55pub struct PublicKey<A: AsymmetricPublicKey>(pub(crate) A::Public);
56
57pub struct KeyPair<A: AsymmetricKey>(SecretKey<A>, PublicKey<A::PubAlg>);
58
59impl<A: AsymmetricKey> KeyPair<A> {
60    pub fn private_key(&self) -> &SecretKey<A> {
61        &self.0
62    }
63    pub fn public_key(&self) -> &PublicKey<A::PubAlg> {
64        &self.1
65    }
66    pub fn into_keys(self) -> (SecretKey<A>, PublicKey<A::PubAlg>) {
67        (self.0, self.1)
68    }
69    pub fn generate<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
70        let sk = A::generate(rng);
71        let pk = A::compute_public(&sk);
72        KeyPair(SecretKey(sk), PublicKey(pk))
73    }
74}
75impl<A: AsymmetricKey> std::fmt::Debug for KeyPair<A> {
76    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
77        write!(f, "KeyPair(<secret key>, {:?})", self.public_key())
78    }
79}
80impl<A: AsymmetricKey> std::fmt::Display for KeyPair<A> {
81    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
82        write!(f, "KeyPair(<secret key>, {})", self.public_key())
83    }
84}
85
86impl<A: AsymmetricPublicKey> fmt::Debug for PublicKey<A> {
87    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88        write!(f, "{}", hex::encode(self.0.as_ref()))
89    }
90}
91impl<A: AsymmetricPublicKey> fmt::Display for PublicKey<A> {
92    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93        write!(f, "{}", hex::encode(self.0.as_ref()))
94    }
95}
96
97impl<A: AsymmetricPublicKey> FromStr for PublicKey<A> {
98    type Err = PublicKeyFromStrError;
99
100    fn from_str(hex: &str) -> Result<Self, Self::Err> {
101        let bytes = hex::decode(hex).map_err(PublicKeyFromStrError::HexMalformed)?;
102        Self::from_binary(&bytes).map_err(PublicKeyFromStrError::KeyInvalid)
103    }
104}
105
106impl fmt::Display for SecretKeyError {
107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108        match self {
109            SecretKeyError::SizeInvalid => write!(f, "Invalid Secret Key size"),
110            SecretKeyError::StructureInvalid => write!(f, "Invalid Secret Key structure"),
111        }
112    }
113}
114
115impl fmt::Display for PublicKeyError {
116    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117        match self {
118            PublicKeyError::SizeInvalid => write!(f, "Invalid Public Key size"),
119            PublicKeyError::StructureInvalid => write!(f, "Invalid Public Key structure"),
120        }
121    }
122}
123
124impl fmt::Display for PublicKeyFromStrError {
125    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126        match self {
127            PublicKeyFromStrError::HexMalformed(_) => "hex encoding malformed",
128            PublicKeyFromStrError::KeyInvalid(_) => "invalid public key data",
129        }
130        .fmt(f)
131    }
132}
133
134impl std::error::Error for SecretKeyError {}
135
136impl std::error::Error for PublicKeyError {}
137
138impl std::error::Error for PublicKeyFromStrError {
139    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
140        match self {
141            PublicKeyFromStrError::HexMalformed(e) => Some(e),
142            PublicKeyFromStrError::KeyInvalid(e) => Some(e),
143        }
144    }
145}
146
147impl<A: AsymmetricPublicKey> AsRef<[u8]> for PublicKey<A> {
148    fn as_ref(&self) -> &[u8] {
149        self.0.as_ref()
150    }
151}
152
153impl<A: AsymmetricKey> AsRef<[u8]> for SecretKey<A> {
154    fn as_ref(&self) -> &[u8] {
155        self.0.as_ref()
156    }
157}
158
159impl<A: AsymmetricKey> From<SecretKey<A>> for KeyPair<A> {
160    fn from(secret_key: SecretKey<A>) -> Self {
161        let public_key = secret_key.to_public();
162        KeyPair(secret_key, public_key)
163    }
164}
165
166impl<A: AsymmetricKey> SecretKey<A> {
167    pub fn generate<T: RngCore + CryptoRng>(rng: T) -> Self {
168        SecretKey(A::generate(rng))
169    }
170    pub fn to_public(&self) -> PublicKey<A::PubAlg> {
171        PublicKey(<A as AsymmetricKey>::compute_public(&self.0))
172    }
173    pub fn from_binary(data: &[u8]) -> Result<Self, SecretKeyError> {
174        Ok(SecretKey(<A as AsymmetricKey>::secret_from_binary(data)?))
175    }
176}
177
178impl<A: AsymmetricPublicKey> PublicKey<A> {
179    pub fn from_binary(data: &[u8]) -> Result<Self, PublicKeyError> {
180        Ok(PublicKey(<A as AsymmetricPublicKey>::public_from_binary(
181            data,
182        )?))
183    }
184}
185
186impl<A: AsymmetricKey> Clone for SecretKey<A> {
187    fn clone(&self) -> Self {
188        SecretKey(self.0.clone())
189    }
190}
191impl<A: AsymmetricPublicKey> Clone for PublicKey<A> {
192    fn clone(&self) -> Self {
193        PublicKey(self.0.clone())
194    }
195}
196impl<A: AsymmetricKey> Clone for KeyPair<A> {
197    fn clone(&self) -> Self {
198        KeyPair(self.0.clone(), self.1.clone())
199    }
200}
201
202impl<A: AsymmetricPublicKey> std::cmp::PartialEq<Self> for PublicKey<A> {
203    fn eq(&self, other: &Self) -> bool {
204        self.0.as_ref().eq(other.0.as_ref())
205    }
206}
207
208impl<A: AsymmetricPublicKey> std::cmp::Eq for PublicKey<A> {}
209
210impl<A: AsymmetricPublicKey> std::cmp::PartialOrd<Self> for PublicKey<A> {
211    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
212        self.0.as_ref().partial_cmp(other.0.as_ref())
213    }
214}
215
216impl<A: AsymmetricPublicKey> std::cmp::Ord for PublicKey<A> {
217    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
218        self.0.as_ref().cmp(other.0.as_ref())
219    }
220}
221
222impl<A: AsymmetricPublicKey> Hash for PublicKey<A> {
223    fn hash<H>(&self, state: &mut H)
224    where
225        H: std::hash::Hasher,
226    {
227        self.0.as_ref().hash(state)
228    }
229}
230
231impl<A: AsymmetricPublicKey> Bech32 for PublicKey<A> {
232    const BECH32_HRP: &'static str = A::PUBLIC_BECH32_HRP;
233
234    fn try_from_bech32_str(bech32_str: &str) -> Result<Self, bech32::Error> {
235        let bytes = bech32::try_from_bech32_to_bytes::<Self>(bech32_str)?;
236        Self::from_binary(&bytes).map_err(bech32::Error::data_invalid)
237    }
238
239    fn to_bech32_str(&self) -> String {
240        bech32::to_bech32_from_bytes::<Self>(self.as_ref())
241    }
242}
243
244impl<A: AsymmetricKey> Bech32 for SecretKey<A> {
245    const BECH32_HRP: &'static str = A::SECRET_BECH32_HRP;
246
247    fn try_from_bech32_str(bech32_str: &str) -> Result<Self, bech32::Error> {
248        let bytes = bech32::try_from_bech32_to_bytes::<Self>(bech32_str)?;
249        Self::from_binary(&bytes).map_err(bech32::Error::data_invalid)
250    }
251
252    fn to_bech32_str(&self) -> String {
253        bech32::to_bech32_from_bytes::<Self>(self.0.as_ref())
254    }
255}
256
257#[cfg(test)]
258mod test {
259    use super::*;
260
261    // ONLY ALLOWED WHEN TESTING
262    impl<A> std::fmt::Debug for SecretKey<A>
263    where
264        A: AsymmetricKey,
265    {
266        fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
267            write!(f, "SecretKey ({:?})", self.0.as_ref())
268        }
269    }
270}