1extern crate alloc;
4
5use crate::ScalarField;
6use alloc::{string::String, vec, vec::Vec};
7use ark_ff::UniformRand;
8use o1_utils::FieldHelpers;
9use rand::{self, CryptoRng, RngCore};
10use sha2::{Digest, Sha256};
11use thiserror::Error;
12
13#[derive(Error, Debug, Clone, PartialEq, Eq)]
15pub enum SecKeyError {
16 #[error("invalid secret key hex")]
18 SecretKeyHex,
19 #[error("Invalid secret key bytes")]
21 SecretKeyBytes,
22 #[error("Invalid secret key length")]
24 SecretKeyLength,
25 #[error("Invalid secret key base58")]
27 SecretKeyBase58,
28 #[error("Invalid secret key checksum")]
30 SecretKeyChecksum,
31 #[error("Invalid secret key version")]
33 SecretKeyVersion,
34}
35pub type Result<T> = core::result::Result<T, SecKeyError>;
37
38pub const MINA_SEC_KEY_LEN: usize = 52;
40
41#[derive(Clone, Debug, PartialEq, Eq)] pub struct SecKey(ScalarField);
44
45impl SecKey {
46 pub fn rand(rng: &mut (impl RngCore + CryptoRng)) -> Self {
48 let secret: ScalarField = ScalarField::rand(rng);
49
50 Self(secret)
51 }
52
53 pub fn new(scalar: ScalarField) -> Self {
55 Self(scalar)
56 }
57
58 pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
64 if bytes.len() != ScalarField::size_in_bytes() {
65 return Err(SecKeyError::SecretKeyBytes);
66 }
67 let mut sec_bytes = vec![0u8; ScalarField::size_in_bytes()];
68 sec_bytes.clone_from_slice(bytes);
69 sec_bytes.reverse(); let secret =
71 ScalarField::from_bytes(&sec_bytes).map_err(|_| SecKeyError::SecretKeyBytes)?;
72 Ok(SecKey(secret))
73 }
74
75 pub fn from_hex(secret_hex: &str) -> Result<Self> {
81 let bytes: Vec<u8> = hex::decode(secret_hex).map_err(|_| SecKeyError::SecretKeyHex)?;
82 SecKey::from_bytes(&bytes)
83 }
84
85 pub fn from_base58(base58: &str) -> Result<Self> {
91 if base58.len() != MINA_SEC_KEY_LEN {
92 return Err(SecKeyError::SecretKeyLength);
93 }
94
95 let bytes = bs58::decode(base58)
96 .into_vec()
97 .map_err(|_| SecKeyError::SecretKeyBase58)?;
98
99 let (raw, checksum) = (&bytes[..bytes.len() - 4], &bytes[bytes.len() - 4..]);
100
101 let hash = Sha256::digest(&Sha256::digest(raw)[..]);
102
103 if checksum != &hash[..4] {
104 return Err(SecKeyError::SecretKeyChecksum);
105 }
106
107 let (version, scalar_bytes) = (&raw[..2], &raw[2..raw.len()]);
108
109 if version != [0x5a, 0x01] {
110 return Err(SecKeyError::SecretKeyVersion);
111 }
112
113 let mut scalar_bytes = scalar_bytes.to_vec();
114
115 scalar_bytes.reverse();
116
117 Self::from_bytes(&scalar_bytes)
118 }
119
120 pub fn scalar(&self) -> &ScalarField {
122 &self.0
123 }
124
125 pub fn into_scalar(self) -> ScalarField {
127 self.0
128 }
129
130 pub fn to_bytes(&self) -> Vec<u8> {
132 let mut bytes = self.0.to_bytes();
133 bytes.reverse(); bytes
135 }
136
137 pub fn to_hex(&self) -> String {
139 hex::encode(self.to_bytes())
140 }
141
142 pub fn to_base58(&self) -> String {
144 let mut raw: Vec<u8> = vec![0x5a, 0x01];
145
146 let mut scalar_bytes = self.to_bytes();
147 scalar_bytes.reverse();
148
149 raw.extend(scalar_bytes);
150
151 let checksum = Sha256::digest(&Sha256::digest(&raw[..])[..]);
152 raw.extend(&checksum[..4]);
153
154 bs58::encode(raw).into_string()
155 }
156}