namada_core/key/
common.rs

1//! Cryptographic keys
2use std::fmt::{self, Display};
3use std::str::FromStr;
4
5use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
6use data_encoding::{HEXLOWER, HEXUPPER};
7use namada_macros::BorshDeserializer;
8#[cfg(feature = "migrations")]
9use namada_migrations::*;
10#[cfg(any(test, feature = "rand"))]
11use rand::{CryptoRng, RngCore};
12use serde::de::{self, Visitor};
13use serde::{Deserialize, Deserializer, Serialize, Serializer};
14use thiserror::Error;
15
16use super::{
17    ParsePublicKeyError, ParseSecretKeyError, ParseSignatureError, RefTo,
18    SchemeType, SigScheme as SigSchemeTrait, VerifySigError, ed25519,
19    secp256k1,
20};
21use crate::borsh::BorshSerializeExt;
22use crate::ethereum_events::EthAddress;
23use crate::key::{SignableBytes, StorageHasher};
24use crate::{impl_display_and_from_str_via_format, string_encoding};
25
26/// Public key
27#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
28#[derive(
29    Clone,
30    Debug,
31    Eq,
32    PartialEq,
33    Ord,
34    PartialOrd,
35    Hash,
36    BorshSerialize,
37    BorshDeserialize,
38    BorshDeserializer,
39    BorshSchema,
40)]
41pub enum CommonPublicKey {
42    /// Encapsulate Ed25519 public keys
43    Ed25519(ed25519::PublicKey),
44    /// Encapsulate Secp256k1 public keys
45    Secp256k1(secp256k1::PublicKey),
46}
47
48/// Public key
49pub type PublicKey = CommonPublicKey;
50
51const ED25519_PK_PREFIX: &str = "ED25519_PK_PREFIX";
52const SECP256K1_PK_PREFIX: &str = "SECP256K1_PK_PREFIX";
53
54impl Serialize for PublicKey {
55    fn serialize<S>(
56        &self,
57        serializer: S,
58    ) -> std::result::Result<S::Ok, S::Error>
59    where
60        S: serde::Serializer,
61    {
62        // String encoded, because toml doesn't support enums
63        let prefix = match self {
64            PublicKey::Ed25519(_) => ED25519_PK_PREFIX,
65            PublicKey::Secp256k1(_) => SECP256K1_PK_PREFIX,
66        };
67        let keypair_string = format!("{}{}", prefix, self);
68        Serialize::serialize(&keypair_string, serializer)
69    }
70}
71
72impl<'de> Deserialize<'de> for PublicKey {
73    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
74    where
75        D: serde::Deserializer<'de>,
76    {
77        use serde::de::Error;
78
79        let keypair_string: String =
80            serde::Deserialize::deserialize(deserializer)
81                .map_err(D::Error::custom)?;
82        if let Some(raw) = keypair_string.strip_prefix(ED25519_PK_PREFIX) {
83            PublicKey::from_str(raw).map_err(D::Error::custom)
84        } else if let Some(raw) =
85            keypair_string.strip_prefix(SECP256K1_PK_PREFIX)
86        {
87            PublicKey::from_str(raw).map_err(D::Error::custom)
88        } else {
89            Err(D::Error::custom(
90                "Could not deserialize SecretKey do to invalid prefix",
91            ))
92        }
93    }
94}
95
96impl super::PublicKey for PublicKey {
97    const TYPE: SchemeType = SigScheme::TYPE;
98
99    fn try_from_pk<PK: super::PublicKey>(
100        pk: &PK,
101    ) -> Result<Self, ParsePublicKeyError> {
102        if PK::TYPE == Self::TYPE {
103            Self::try_from_slice(pk.serialize_to_vec().as_slice())
104                .map_err(ParsePublicKeyError::InvalidEncoding)
105        } else if PK::TYPE == ed25519::PublicKey::TYPE {
106            Ok(Self::Ed25519(
107                ed25519::PublicKey::try_from_slice(
108                    pk.serialize_to_vec().as_slice(),
109                )
110                .map_err(ParsePublicKeyError::InvalidEncoding)?,
111            ))
112        } else if PK::TYPE == secp256k1::PublicKey::TYPE {
113            Ok(Self::Secp256k1(
114                secp256k1::PublicKey::try_from_slice(
115                    pk.serialize_to_vec().as_slice(),
116                )
117                .map_err(ParsePublicKeyError::InvalidEncoding)?,
118            ))
119        } else {
120            Err(ParsePublicKeyError::MismatchedScheme)
121        }
122    }
123}
124
125/// String decoding error
126pub type DecodeError = string_encoding::DecodeError;
127
128impl string_encoding::Format for PublicKey {
129    type EncodedBytes<'a> = Vec<u8>;
130
131    const HRP: string_encoding::Hrp =
132        string_encoding::Hrp::parse_unchecked(string_encoding::COMMON_PK_HRP);
133
134    fn to_bytes(&self) -> Vec<u8> {
135        self.serialize_to_vec()
136    }
137
138    fn decode_bytes(
139        bytes: &[u8],
140    ) -> Result<Self, string_encoding::DecodeError> {
141        BorshDeserialize::try_from_slice(bytes)
142            .map_err(DecodeError::InvalidBytes)
143    }
144}
145
146impl_display_and_from_str_via_format!(PublicKey);
147
148impl From<PublicKey> for crate::tendermint::PublicKey {
149    fn from(value: PublicKey) -> Self {
150        use crate::tendermint::PublicKey as TmPK;
151        match value {
152            PublicKey::Ed25519(ed25519::PublicKey(pk)) => {
153                TmPK::from_raw_ed25519(pk.as_bytes()).unwrap()
154            }
155            PublicKey::Secp256k1(secp256k1::PublicKey(pk)) => {
156                TmPK::from_raw_secp256k1(&pk.to_sec1_bytes()).unwrap()
157            }
158        }
159    }
160}
161
162#[allow(missing_docs)]
163#[derive(Error, Debug)]
164pub enum EthAddressConvError {
165    #[error("Eth key cannot be ed25519, only secp256k1")]
166    CannotBeEd25519,
167}
168
169impl TryFrom<&PublicKey> for EthAddress {
170    type Error = EthAddressConvError;
171
172    fn try_from(value: &PublicKey) -> Result<Self, Self::Error> {
173        match value {
174            PublicKey::Ed25519(_) => Err(EthAddressConvError::CannotBeEd25519),
175            PublicKey::Secp256k1(pk) => Ok(EthAddress::from(pk)),
176        }
177    }
178}
179
180/// Secret key
181#[derive(
182    Debug,
183    Clone,
184    BorshSerialize,
185    BorshDeserialize,
186    BorshDeserializer,
187    BorshSchema,
188)]
189#[allow(clippy::large_enum_variant)]
190pub enum SecretKey {
191    /// Encapsulate Ed25519 secret keys
192    Ed25519(ed25519::SecretKey),
193    /// Encapsulate Secp256k1 secret keys
194    Secp256k1(secp256k1::SecretKey),
195}
196
197impl Serialize for SecretKey {
198    fn serialize<S>(
199        &self,
200        serializer: S,
201    ) -> std::result::Result<S::Ok, S::Error>
202    where
203        S: serde::Serializer,
204    {
205        // String encoded, because toml doesn't support enums
206        let prefix = match self {
207            SecretKey::Ed25519(_) => "ED25519_SK_PREFIX",
208            SecretKey::Secp256k1(_) => "SECP256K1_SK_PREFIX",
209        };
210        let keypair_string = format!("{}{}", prefix, self);
211        Serialize::serialize(&keypair_string, serializer)
212    }
213}
214
215impl<'de> Deserialize<'de> for SecretKey {
216    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
217    where
218        D: serde::Deserializer<'de>,
219    {
220        use serde::de::Error;
221
222        let keypair_string: String =
223            serde::Deserialize::deserialize(deserializer)
224                .map_err(D::Error::custom)?;
225        if let Some(raw) = keypair_string.strip_prefix("ED25519_SK_PREFIX") {
226            SecretKey::from_str(raw).map_err(D::Error::custom)
227        } else if let Some(raw) =
228            keypair_string.strip_prefix("SECP256K1_SK_PREFIX")
229        {
230            SecretKey::from_str(raw).map_err(D::Error::custom)
231        } else {
232            Err(D::Error::custom(
233                "Could not deserialize SecretKey do to invalid prefix",
234            ))
235        }
236    }
237}
238
239impl SecretKey {
240    /// Derive public key from this secret key
241    pub fn to_public(&self) -> PublicKey {
242        self.ref_to()
243    }
244}
245
246impl super::SecretKey for SecretKey {
247    type PublicKey = PublicKey;
248
249    const TYPE: SchemeType = SigScheme::TYPE;
250
251    fn try_from_sk<SK: super::SecretKey>(
252        sk: &SK,
253    ) -> Result<Self, ParseSecretKeyError> {
254        if SK::TYPE == Self::TYPE {
255            Self::try_from_slice(sk.serialize_to_vec().as_ref())
256                .map_err(ParseSecretKeyError::InvalidEncoding)
257        } else if SK::TYPE == ed25519::SecretKey::TYPE {
258            Ok(Self::Ed25519(
259                ed25519::SecretKey::try_from_slice(
260                    sk.serialize_to_vec().as_ref(),
261                )
262                .map_err(ParseSecretKeyError::InvalidEncoding)?,
263            ))
264        } else if SK::TYPE == secp256k1::SecretKey::TYPE {
265            Ok(Self::Secp256k1(
266                secp256k1::SecretKey::try_from_slice(
267                    sk.serialize_to_vec().as_ref(),
268                )
269                .map_err(ParseSecretKeyError::InvalidEncoding)?,
270            ))
271        } else {
272            Err(ParseSecretKeyError::MismatchedScheme)
273        }
274    }
275}
276
277impl RefTo<PublicKey> for SecretKey {
278    fn ref_to(&self) -> PublicKey {
279        match self {
280            SecretKey::Ed25519(sk) => PublicKey::Ed25519(sk.ref_to()),
281            SecretKey::Secp256k1(sk) => PublicKey::Secp256k1(sk.ref_to()),
282        }
283    }
284}
285
286impl Display for SecretKey {
287    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
288        write!(f, "{}", HEXLOWER.encode(&self.serialize_to_vec()))
289    }
290}
291
292impl FromStr for SecretKey {
293    type Err = ParseSecretKeyError;
294
295    fn from_str(str: &str) -> Result<Self, Self::Err> {
296        let vec = HEXLOWER
297            .decode(str.as_ref())
298            .map_err(ParseSecretKeyError::InvalidHex)?;
299        Self::try_from_slice(vec.as_slice())
300            .map_err(ParseSecretKeyError::InvalidEncoding)
301    }
302}
303
304/// Signature
305#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
306#[derive(
307    Clone,
308    Debug,
309    Eq,
310    PartialEq,
311    PartialOrd,
312    Ord,
313    Hash,
314    BorshSerialize,
315    BorshDeserialize,
316    BorshDeserializer,
317    BorshSchema,
318)]
319pub enum CommonSignature {
320    /// Encapsulate Ed25519 signatures
321    Ed25519(ed25519::Signature),
322    /// Encapsulate Secp256k1 signatures
323    Secp256k1(secp256k1::Signature),
324}
325
326/// Signature
327pub type Signature = CommonSignature;
328
329impl string_encoding::Format for Signature {
330    type EncodedBytes<'a> = Vec<u8>;
331
332    const HRP: string_encoding::Hrp =
333        string_encoding::Hrp::parse_unchecked(string_encoding::COMMON_SIG_HRP);
334
335    fn to_bytes(&self) -> Vec<u8> {
336        self.serialize_to_vec()
337    }
338
339    fn decode_bytes(
340        bytes: &[u8],
341    ) -> Result<Self, string_encoding::DecodeError> {
342        BorshDeserialize::try_from_slice(bytes)
343            .map_err(DecodeError::InvalidBytes)
344    }
345}
346
347impl Serialize for CommonSignature {
348    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
349    where
350        S: Serializer,
351    {
352        let hex_str = HEXUPPER.encode(&self.serialize_to_vec());
353        serializer.serialize_str(&hex_str)
354    }
355}
356
357// Implement custom deserialization
358impl<'de> Deserialize<'de> for CommonSignature {
359    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
360    where
361        D: Deserializer<'de>,
362    {
363        struct SignatureVisitor;
364
365        impl Visitor<'_> for SignatureVisitor {
366            type Value = CommonSignature;
367
368            fn expecting(
369                &self,
370                formatter: &mut fmt::Formatter<'_>,
371            ) -> fmt::Result {
372                formatter.write_str(
373                    "a hex string representing either an Ed25519 or Secp256k1 \
374                     signature",
375                )
376            }
377
378            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
379            where
380                E: de::Error,
381            {
382                let bytes =
383                    HEXUPPER.decode(value.as_bytes()).map_err(E::custom)?;
384                CommonSignature::try_from_slice(&bytes)
385                    .map_err(|e| E::custom(e.to_string()))
386            }
387        }
388
389        deserializer.deserialize_str(SignatureVisitor)
390    }
391}
392
393impl_display_and_from_str_via_format!(Signature);
394
395impl From<ed25519::Signature> for Signature {
396    fn from(sig: ed25519::Signature) -> Self {
397        Signature::Ed25519(sig)
398    }
399}
400
401impl From<secp256k1::Signature> for Signature {
402    fn from(sig: secp256k1::Signature) -> Self {
403        Signature::Secp256k1(sig)
404    }
405}
406
407impl super::Signature for Signature {
408    const TYPE: SchemeType = SigScheme::TYPE;
409
410    fn try_from_sig<SIG: super::Signature>(
411        sig: &SIG,
412    ) -> Result<Self, ParseSignatureError> {
413        if SIG::TYPE == Self::TYPE {
414            Self::try_from_slice(sig.serialize_to_vec().as_slice())
415                .map_err(ParseSignatureError::InvalidEncoding)
416        } else if SIG::TYPE == ed25519::Signature::TYPE {
417            Ok(Self::Ed25519(
418                ed25519::Signature::try_from_slice(
419                    sig.serialize_to_vec().as_slice(),
420                )
421                .map_err(ParseSignatureError::InvalidEncoding)?,
422            ))
423        } else if SIG::TYPE == secp256k1::Signature::TYPE {
424            Ok(Self::Secp256k1(
425                secp256k1::Signature::try_from_slice(
426                    sig.serialize_to_vec().as_slice(),
427                )
428                .map_err(ParseSignatureError::InvalidEncoding)?,
429            ))
430        } else {
431            Err(ParseSignatureError::MismatchedScheme)
432        }
433    }
434}
435
436/// An implementation of the common signature scheme
437#[derive(
438    Debug,
439    Clone,
440    BorshSerialize,
441    BorshDeserialize,
442    BorshDeserializer,
443    BorshSchema,
444    PartialEq,
445    Eq,
446    PartialOrd,
447    Ord,
448    Hash,
449    Serialize,
450    Deserialize,
451    Default,
452)]
453pub struct SigScheme;
454
455impl super::SigScheme for SigScheme {
456    type PublicKey = PublicKey;
457    type SecretKey = SecretKey;
458    type Signature = Signature;
459
460    const TYPE: SchemeType = SchemeType::Common;
461
462    #[cfg(any(test, feature = "rand"))]
463    fn generate<R>(_csprng: &mut R) -> SecretKey
464    where
465        R: CryptoRng + RngCore,
466    {
467        panic!(
468            "Cannot generate common signing scheme. Must convert from \
469             alternative scheme."
470        );
471    }
472
473    fn from_bytes(_seed: [u8; 32]) -> Self::SecretKey {
474        unimplemented!(
475            "Cannot generate common signing scheme. Must convert from \
476             alternative scheme."
477        );
478    }
479
480    fn sign_with_hasher<H>(
481        keypair: &SecretKey,
482        data: impl super::SignableBytes,
483    ) -> Self::Signature
484    where
485        H: 'static + StorageHasher,
486    {
487        match keypair {
488            SecretKey::Ed25519(kp) => Signature::Ed25519(
489                ed25519::SigScheme::sign_with_hasher::<H>(kp, data),
490            ),
491            SecretKey::Secp256k1(kp) => Signature::Secp256k1(
492                secp256k1::SigScheme::sign_with_hasher::<H>(kp, data),
493            ),
494        }
495    }
496
497    fn verify_signature_with_hasher<H>(
498        pk: &Self::PublicKey,
499        data: &impl SignableBytes,
500        sig: &Self::Signature,
501    ) -> Result<(), VerifySigError>
502    where
503        H: 'static + StorageHasher,
504    {
505        match (pk, sig) {
506            (PublicKey::Ed25519(pk), Signature::Ed25519(sig)) => {
507                ed25519::SigScheme::verify_signature_with_hasher::<H>(
508                    pk, data, sig,
509                )
510            }
511            (PublicKey::Secp256k1(pk), Signature::Secp256k1(sig)) => {
512                secp256k1::SigScheme::verify_signature_with_hasher::<H>(
513                    pk, data, sig,
514                )
515            }
516            _ => Err(VerifySigError::MismatchedScheme),
517        }
518    }
519
520    fn mock(keypair: &SecretKey) -> Self::Signature {
521        match keypair {
522            SecretKey::Ed25519(kp) => {
523                Signature::Ed25519(ed25519::SigScheme::mock(kp))
524            }
525            SecretKey::Secp256k1(kp) => {
526                Signature::Secp256k1(secp256k1::SigScheme::mock(kp))
527            }
528        }
529    }
530}
531
532#[cfg(test)]
533mod tests {
534    use super::*;
535
536    /// Run `cargo test gen_ed25519_keypair -- --nocapture` to generate a
537    /// new ed25519 keypair wrapped in `common` key types.
538    #[test]
539    fn gen_ed25519_keypair() {
540        let secret_key =
541            SecretKey::Ed25519(crate::key::testing::gen_keypair::<
542                ed25519::SigScheme,
543            >());
544        let public_key = secret_key.to_public();
545        println!("Public key: {}", public_key);
546        println!("Secret key: {}", secret_key);
547    }
548}