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
//! Keypair structures and algorithms
//!
//! Definition of secret key, keypairs and related helpers

use crate::{pubkey::PubKeyError, seckey::SecKeyError, CurvePoint, PubKey, ScalarField, SecKey};
use core::fmt;
use rand::{self, CryptoRng, RngCore};
use thiserror::Error;

/// Keypair error
#[derive(Error, Debug, Clone, PartialEq, Eq)]
pub enum KeypairError {
    /// Invalid secret key
    #[error(transparent)]
    SecretKey(#[from] SecKeyError),
    /// Public key error
    #[error(transparent)]
    PublicKey(#[from] PubKeyError),
    /// point not on curve
    #[error("point not on curve")]
    NonCurvePoint,
}
/// Keypair result
pub type Result<T> = std::result::Result<T, KeypairError>;

/// Keypair structure
#[derive(Clone, PartialEq, Eq)]
pub struct Keypair {
    /// Secret key
    pub(crate) secret: SecKey,
    /// Public key
    pub public: PubKey,
}

impl Keypair {
    /// Create keypair from scalar field `secret` element and curve point `public`
    /// Note: Does not check point `public` is on curve
    pub fn from_parts_unsafe(secret: ScalarField, public: CurvePoint) -> Self {
        Self {
            secret: SecKey::new(secret),
            public: PubKey::from_point_unsafe(public),
        }
    }

    /// Create keypair from secret key
    pub fn from_secret_key(secret_key: SecKey) -> Result<Self> {
        let public = PubKey::from_secret_key(secret_key.clone())?;

        // Safe now because PubKey::from_secret_key() checked point is on the curve
        Ok(Self::from_parts_unsafe(
            secret_key.into_scalar(),
            public.into_point(),
        ))
    }

    /// Generate random keypair
    pub fn rand(rng: &mut (impl RngCore + CryptoRng)) -> Result<Self> {
        let sec_key: SecKey = SecKey::rand(rng);
        Keypair::from_secret_key(sec_key)
    }

    /// Deserialize keypair from secret key bytes
    ///
    /// # Errors
    ///
    /// Will give error if `bytes` do not match certain requirements.
    pub fn from_bytes(secret_bytes: &[u8]) -> Result<Self> {
        let secret = SecKey::from_bytes(secret_bytes)?;
        Keypair::from_secret_key(secret)
    }

    /// Deserialize keypair from secret key hex
    ///
    /// # Errors
    ///
    /// Will give error if `hex` string does not match certain requirements.
    pub fn from_hex(secret_hex: &str) -> Result<Self> {
        let secret = SecKey::from_hex(secret_hex)?;
        Keypair::from_secret_key(secret)
    }

    /// Obtain the Mina address corresponding to the keypair's public key
    pub fn get_address(self) -> String {
        self.public.into_address()
    }

    /// Deserialize keypair into bytes
    pub fn to_bytes(&self) -> Vec<u8> {
        self.secret.to_bytes()
    }

    /// Deserialize keypair into hex
    pub fn to_hex(&self) -> String {
        hex::encode(self.to_bytes())
    }
}

impl fmt::Debug for Keypair {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Omit the secret key for security
        write!(f, "{:?}", self.public)
    }
}

impl fmt::Display for Keypair {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Omit the secret key for security
        write!(f, "{}", self.public)
    }
}