mina_signer/
keypair.rs

1//! Keypair structures and algorithms
2//!
3//! Definition of secret key, keypairs and related helpers
4
5extern crate alloc;
6use crate::{pubkey::PubKeyError, seckey::SecKeyError, CurvePoint, PubKey, ScalarField, SecKey};
7use alloc::{string::String, vec::Vec};
8use core::fmt;
9use rand::{self, CryptoRng, RngCore};
10use thiserror::Error;
11
12/// Keypair error
13#[derive(Error, Debug, Clone, PartialEq, Eq)]
14pub enum KeypairError {
15    /// Invalid secret key
16    #[error(transparent)]
17    SecretKey(#[from] SecKeyError),
18    /// Public key error
19    #[error(transparent)]
20    PublicKey(#[from] PubKeyError),
21    /// point not on curve
22    #[error("point not on curve")]
23    NonCurvePoint,
24}
25/// Keypair result
26pub type Result<T> = core::result::Result<T, KeypairError>;
27
28/// Keypair structure
29#[derive(Clone, PartialEq, Eq)]
30pub struct Keypair {
31    /// Secret key
32    pub secret: SecKey,
33    /// Public key
34    pub public: PubKey,
35}
36
37impl Keypair {
38    /// Create keypair from scalar field `secret` element and curve point `public`
39    /// Note: Does not check point `public` is on curve
40    pub fn from_parts_unsafe(secret: ScalarField, public: CurvePoint) -> Self {
41        Self {
42            secret: SecKey::new(secret),
43            public: PubKey::from_point_unsafe(public),
44        }
45    }
46
47    /// Create keypair from secret key
48    pub fn from_secret_key(secret_key: SecKey) -> Result<Self> {
49        let public = PubKey::from_secret_key(secret_key.clone())?;
50
51        // Safe now because PubKey::from_secret_key() checked point is on the curve
52        Ok(Self::from_parts_unsafe(
53            secret_key.into_scalar(),
54            public.into_point(),
55        ))
56    }
57
58    /// Generate random keypair
59    pub fn rand(rng: &mut (impl RngCore + CryptoRng)) -> Result<Self> {
60        let sec_key: SecKey = SecKey::rand(rng);
61        Keypair::from_secret_key(sec_key)
62    }
63
64    /// Deserialize keypair from secret key bytes
65    ///
66    /// # Errors
67    ///
68    /// Will give error if `bytes` do not match certain requirements.
69    pub fn from_bytes(secret_bytes: &[u8]) -> Result<Self> {
70        let secret = SecKey::from_bytes(secret_bytes)?;
71        Keypair::from_secret_key(secret)
72    }
73
74    /// Deserialize keypair from secret key hex
75    ///
76    /// # Errors
77    ///
78    /// Will give error if `hex` string does not match certain requirements.
79    pub fn from_hex(secret_hex: &str) -> Result<Self> {
80        let secret = SecKey::from_hex(secret_hex)?;
81        Keypair::from_secret_key(secret)
82    }
83
84    /// Obtain the Mina address corresponding to the keypair's public key
85    pub fn get_address(self) -> String {
86        self.public.into_address()
87    }
88
89    /// Deserialize keypair into bytes
90    pub fn to_bytes(&self) -> Vec<u8> {
91        self.secret.to_bytes()
92    }
93
94    /// Deserialize keypair into hex
95    pub fn to_hex(&self) -> String {
96        hex::encode(self.to_bytes())
97    }
98}
99
100impl fmt::Debug for Keypair {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        // Omit the secret key for security
103        write!(f, "{:?}", self.public)
104    }
105}
106
107impl fmt::Display for Keypair {
108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109        // Omit the secret key for security
110        write!(f, "{}", self.public)
111    }
112}