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