cml_crypto/chain_crypto/
key.rs

1use crate::chain_crypto::bech32::{self, Bech32};
2use cbor_event::{de::Deserializer, se::Serializer};
3use hex::FromHexError;
4use rand::{CryptoRng, RngCore};
5use schemars::JsonSchema;
6use std::fmt;
7use std::hash::Hash;
8use std::str::FromStr;
9
10#[derive(Debug, Copy, Clone, PartialEq, Eq)]
11pub enum SecretKeyError {
12    SizeInvalid,
13    StructureInvalid,
14}
15
16#[derive(Debug, Copy, Clone, PartialEq, Eq)]
17pub enum PublicKeyError {
18    SizeInvalid,
19    StructureInvalid,
20}
21
22#[derive(Debug, Clone, PartialEq)]
23pub enum PublicKeyFromStrError {
24    HexMalformed(FromHexError),
25    KeyInvalid(PublicKeyError),
26}
27
28#[derive(Debug, Clone, PartialEq)]
29pub enum SecretKeyFromStrError {
30    HexMalformed(FromHexError),
31    KeyInvalid(SecretKeyError),
32}
33
34pub trait AsymmetricPublicKey {
35    type Public: AsRef<[u8]> + Clone + PartialEq + Eq + Hash;
36    const PUBLIC_BECH32_HRP: &'static str;
37    const PUBLIC_KEY_SIZE: usize;
38
39    fn public_from_binary(data: &[u8]) -> Result<Self::Public, PublicKeyError>;
40}
41
42pub trait AsymmetricKey {
43    // The name of the public key Algorithm to represent the public key
44    // where PubAlg::Public is the public key type.
45    type PubAlg: AsymmetricPublicKey;
46
47    // the secret key type
48    type Secret: AsRef<[u8]> + Clone;
49
50    const SECRET_BECH32_HRP: &'static str;
51
52    fn generate<T: RngCore + CryptoRng>(rng: T) -> Self::Secret;
53    fn compute_public(secret: &Self::Secret) -> <Self::PubAlg as AsymmetricPublicKey>::Public;
54    fn secret_from_binary(data: &[u8]) -> Result<Self::Secret, SecretKeyError>;
55}
56
57pub trait SecretKeySizeStatic: AsymmetricKey {
58    const SECRET_KEY_SIZE: usize;
59}
60
61pub struct SecretKey<A: AsymmetricKey>(pub(crate) A::Secret);
62
63pub struct PublicKey<A: AsymmetricPublicKey>(pub(crate) A::Public);
64
65pub struct KeyPair<A: AsymmetricKey>(SecretKey<A>, PublicKey<A::PubAlg>);
66
67impl<A: AsymmetricKey> KeyPair<A> {
68    pub fn private_key(&self) -> &SecretKey<A> {
69        &self.0
70    }
71    pub fn public_key(&self) -> &PublicKey<A::PubAlg> {
72        &self.1
73    }
74    pub fn into_keys(self) -> (SecretKey<A>, PublicKey<A::PubAlg>) {
75        (self.0, self.1)
76    }
77    pub fn generate<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
78        let sk = A::generate(rng);
79        let pk = A::compute_public(&sk);
80        KeyPair(SecretKey(sk), PublicKey(pk))
81    }
82}
83impl<A: AsymmetricKey> std::fmt::Debug for KeyPair<A> {
84    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
85        write!(f, "KeyPair(<secret key>, {:?})", self.public_key())
86    }
87}
88impl<A: AsymmetricKey> std::fmt::Display for KeyPair<A> {
89    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
90        write!(f, "KeyPair(<secret key>, {})", self.public_key())
91    }
92}
93
94impl<A: AsymmetricPublicKey> fmt::Debug for PublicKey<A> {
95    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96        write!(f, "{}", hex::encode(self.0.as_ref()))
97    }
98}
99impl<A: AsymmetricPublicKey> fmt::Display for PublicKey<A> {
100    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101        write!(f, "{}", hex::encode(self.0.as_ref()))
102    }
103}
104
105impl<A: AsymmetricPublicKey> FromStr for PublicKey<A> {
106    type Err = PublicKeyFromStrError;
107
108    fn from_str(hex: &str) -> Result<Self, Self::Err> {
109        let bytes = hex::decode(hex).map_err(PublicKeyFromStrError::HexMalformed)?;
110        Self::from_binary(&bytes).map_err(PublicKeyFromStrError::KeyInvalid)
111    }
112}
113
114impl<A: AsymmetricPublicKey> serde::Serialize for PublicKey<A> {
115    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
116    where
117        S: serde::Serializer,
118    {
119        serializer.serialize_str(&self.to_bech32_str())
120    }
121}
122
123impl<'de, A: AsymmetricPublicKey> serde::de::Deserialize<'de> for PublicKey<A> {
124    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
125    where
126        D: serde::de::Deserializer<'de>,
127    {
128        let s = <String as serde::de::Deserialize>::deserialize(deserializer)?;
129        PublicKey::try_from_bech32_str(&s).map_err(|_e| {
130            serde::de::Error::invalid_value(
131                serde::de::Unexpected::Str(&s),
132                &"bech32 public key string",
133            )
134        })
135    }
136}
137
138impl JsonSchema for PublicKey<crate::chain_crypto::Ed25519> {
139    fn schema_name() -> String {
140        String::from("Ed25519PublicKey")
141    }
142    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
143        String::json_schema(gen)
144    }
145    fn is_referenceable() -> bool {
146        String::is_referenceable()
147    }
148}
149impl JsonSchema for PublicKey<crate::chain_crypto::Ed25519Bip32> {
150    fn schema_name() -> String {
151        String::from("Ed25519Bip32PublicKey")
152    }
153    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
154        String::json_schema(gen)
155    }
156    fn is_referenceable() -> bool {
157        String::is_referenceable()
158    }
159}
160
161impl<A: AsymmetricKey> FromStr for SecretKey<A> {
162    type Err = SecretKeyFromStrError;
163
164    fn from_str(hex: &str) -> Result<Self, Self::Err> {
165        let bytes = hex::decode(hex).map_err(SecretKeyFromStrError::HexMalformed)?;
166        Self::from_binary(&bytes).map_err(SecretKeyFromStrError::KeyInvalid)
167    }
168}
169
170impl fmt::Display for SecretKeyError {
171    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
172        match self {
173            SecretKeyError::SizeInvalid => write!(f, "Invalid Secret Key size"),
174            SecretKeyError::StructureInvalid => write!(f, "Invalid Secret Key structure"),
175        }
176    }
177}
178
179impl fmt::Display for PublicKeyError {
180    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
181        match self {
182            PublicKeyError::SizeInvalid => write!(f, "Invalid Public Key size"),
183            PublicKeyError::StructureInvalid => write!(f, "Invalid Public Key structure"),
184        }
185    }
186}
187
188impl fmt::Display for PublicKeyFromStrError {
189    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
190        match self {
191            PublicKeyFromStrError::HexMalformed(_) => "hex encoding malformed",
192            PublicKeyFromStrError::KeyInvalid(_) => "invalid public key data",
193        }
194        .fmt(f)
195    }
196}
197
198impl std::error::Error for SecretKeyError {}
199
200impl std::error::Error for PublicKeyError {}
201
202impl std::error::Error for PublicKeyFromStrError {
203    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
204        match self {
205            PublicKeyFromStrError::HexMalformed(e) => Some(e),
206            PublicKeyFromStrError::KeyInvalid(e) => Some(e),
207        }
208    }
209}
210
211impl<A: AsymmetricPublicKey> AsRef<[u8]> for PublicKey<A> {
212    fn as_ref(&self) -> &[u8] {
213        self.0.as_ref()
214    }
215}
216
217impl<A: AsymmetricKey> AsRef<[u8]> for SecretKey<A> {
218    fn as_ref(&self) -> &[u8] {
219        self.0.as_ref()
220    }
221}
222
223impl<A: AsymmetricKey> From<SecretKey<A>> for KeyPair<A> {
224    fn from(secret_key: SecretKey<A>) -> Self {
225        let public_key = secret_key.to_public();
226        KeyPair(secret_key, public_key)
227    }
228}
229
230impl<A: AsymmetricKey> SecretKey<A> {
231    pub fn generate<T: RngCore + CryptoRng>(rng: T) -> Self {
232        SecretKey(A::generate(rng))
233    }
234    pub fn to_public(&self) -> PublicKey<A::PubAlg> {
235        PublicKey(<A as AsymmetricKey>::compute_public(&self.0))
236    }
237    pub fn from_binary(data: &[u8]) -> Result<Self, SecretKeyError> {
238        Ok(SecretKey(<A as AsymmetricKey>::secret_from_binary(data)?))
239    }
240}
241
242impl<A: AsymmetricPublicKey> PublicKey<A> {
243    pub fn from_binary(data: &[u8]) -> Result<Self, PublicKeyError> {
244        Ok(PublicKey(<A as AsymmetricPublicKey>::public_from_binary(
245            data,
246        )?))
247    }
248}
249
250impl<A: AsymmetricKey> Clone for SecretKey<A> {
251    fn clone(&self) -> Self {
252        SecretKey(self.0.clone())
253    }
254}
255impl<A: AsymmetricPublicKey> Clone for PublicKey<A> {
256    fn clone(&self) -> Self {
257        PublicKey(self.0.clone())
258    }
259}
260impl<A: AsymmetricKey> Clone for KeyPair<A> {
261    fn clone(&self) -> Self {
262        KeyPair(self.0.clone(), self.1.clone())
263    }
264}
265
266impl<A: AsymmetricPublicKey> std::cmp::PartialEq<Self> for PublicKey<A> {
267    fn eq(&self, other: &Self) -> bool {
268        self.0.as_ref().eq(other.0.as_ref())
269    }
270}
271
272impl<A: AsymmetricPublicKey> std::cmp::Eq for PublicKey<A> {}
273
274impl<A: AsymmetricPublicKey> std::cmp::PartialOrd<Self> for PublicKey<A> {
275    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
276        Some(self.cmp(other))
277    }
278}
279
280impl<A: AsymmetricPublicKey> std::cmp::Ord for PublicKey<A> {
281    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
282        self.0.as_ref().cmp(other.0.as_ref())
283    }
284}
285
286impl<A: AsymmetricPublicKey> Hash for PublicKey<A> {
287    fn hash<H>(&self, state: &mut H)
288    where
289        H: std::hash::Hasher,
290    {
291        self.0.as_ref().hash(state)
292    }
293}
294
295impl<A: AsymmetricPublicKey> Bech32 for PublicKey<A> {
296    const BECH32_HRP: &'static str = A::PUBLIC_BECH32_HRP;
297
298    fn try_from_bech32_str(bech32_str: &str) -> Result<Self, bech32::Error> {
299        let bytes = bech32::try_from_bech32_to_bytes::<Self>(bech32_str)?;
300        Self::from_binary(&bytes).map_err(bech32::Error::data_invalid)
301    }
302
303    fn to_bech32_str(&self) -> String {
304        bech32::to_bech32_from_bytes::<Self>(self.as_ref())
305    }
306}
307
308impl<A: AsymmetricKey> Bech32 for SecretKey<A> {
309    const BECH32_HRP: &'static str = A::SECRET_BECH32_HRP;
310
311    fn try_from_bech32_str(bech32_str: &str) -> Result<Self, bech32::Error> {
312        let bytes = bech32::try_from_bech32_to_bytes::<Self>(bech32_str)?;
313        Self::from_binary(&bytes).map_err(bech32::Error::data_invalid)
314    }
315
316    fn to_bech32_str(&self) -> String {
317        bech32::to_bech32_from_bytes::<Self>(self.0.as_ref())
318    }
319}
320
321impl<A: AsymmetricPublicKey> cbor_event::se::Serialize for PublicKey<A> {
322    fn serialize<'se, W: std::io::Write>(
323        &self,
324        serializer: &'se mut Serializer<W>,
325    ) -> cbor_event::Result<&'se mut Serializer<W>> {
326        serializer.write_bytes(self.as_ref())
327    }
328}
329
330impl<A: AsymmetricPublicKey> cbor_event::de::Deserialize for PublicKey<A> {
331    fn deserialize<R: std::io::BufRead>(raw: &mut Deserializer<R>) -> cbor_event::Result<Self> {
332        let result = PublicKey::<A>::from_binary(raw.bytes()?.as_ref())
333            .map_err(|err| cbor_event::Error::CustomError(format!("{err}")))?;
334        Ok(result)
335    }
336}
337
338#[cfg(test)]
339mod test {
340    use super::*;
341
342    // ONLY ALLOWED WHEN TESTING
343    impl<A> std::fmt::Debug for SecretKey<A>
344    where
345        A: AsymmetricKey,
346    {
347        fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
348            write!(f, "SecretKey ({:?})", self.0.as_ref())
349        }
350    }
351}