fuel_crypto/secp256/
secret.rs1use fuel_types::Bytes32;
2
3use core::{
4 fmt,
5 ops::Deref,
6 str,
7};
8
9use zeroize::Zeroize;
10
11use crate::{
12 secp256::PublicKey,
13 Error,
14};
15
16#[cfg(feature = "std")]
17use coins_bip32::path::DerivationPath;
18
19#[cfg(feature = "std")]
20use coins_bip39::{
21 English,
22 Mnemonic,
23};
24
25#[cfg(feature = "random")]
26use rand::{
27 CryptoRng,
28 RngCore,
29};
30
31#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Zeroize)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34#[repr(transparent)]
35pub struct SecretKey(Bytes32);
36
37impl SecretKey {
38 pub const LEN: usize = Bytes32::LEN;
40}
41
42impl Deref for SecretKey {
43 type Target = [u8; SecretKey::LEN];
44
45 fn deref(&self) -> &[u8; SecretKey::LEN] {
46 self.0.deref()
47 }
48}
49
50impl AsRef<[u8]> for SecretKey {
51 fn as_ref(&self) -> &[u8] {
52 self.0.as_ref()
53 }
54}
55
56impl From<SecretKey> for [u8; SecretKey::LEN] {
57 fn from(salt: SecretKey) -> [u8; SecretKey::LEN] {
58 salt.0.into()
59 }
60}
61
62impl fmt::LowerHex for SecretKey {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 self.0.fmt(f)
65 }
66}
67
68impl fmt::UpperHex for SecretKey {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 self.0.fmt(f)
71 }
72}
73
74impl fmt::Debug for SecretKey {
75 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76 self.0.fmt(f)
77 }
78}
79
80impl fmt::Display for SecretKey {
81 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
82 self.0.fmt(f)
83 }
84}
85
86impl From<::k256::SecretKey> for SecretKey {
87 fn from(s: ::k256::SecretKey) -> Self {
88 let mut raw_bytes = [0u8; Self::LEN];
89 raw_bytes.copy_from_slice(&s.to_bytes());
90 Self(Bytes32::from(raw_bytes))
91 }
92}
93
94#[cfg(feature = "std")]
95impl From<::secp256k1::SecretKey> for SecretKey {
96 fn from(s: ::secp256k1::SecretKey) -> Self {
97 let mut raw_bytes = [0u8; Self::LEN];
98 raw_bytes.copy_from_slice(s.as_ref());
99 Self(Bytes32::from(raw_bytes))
100 }
101}
102
103impl From<&SecretKey> for ::k256::SecretKey {
104 fn from(sk: &SecretKey) -> Self {
105 ::k256::SecretKey::from_bytes(&(*sk.0).into())
106 .expect("SecretKey is guaranteed to be valid")
107 }
108}
109
110#[cfg(feature = "std")]
111impl From<&SecretKey> for ::secp256k1::SecretKey {
112 fn from(sk: &SecretKey) -> Self {
113 ::secp256k1::SecretKey::from_slice(sk.as_ref())
114 .expect("SecretKey is guaranteed to be valid")
115 }
116}
117
118#[cfg(all(feature = "random", feature = "test-helpers"))]
119impl Default for SecretKey {
120 fn default() -> Self {
122 let mut rng = rand::thread_rng();
123 SecretKey::random(&mut rng)
124 }
125}
126
127#[cfg(feature = "std")]
128pub type W = English;
129
130impl SecretKey {
131 #[cfg(feature = "random")]
133 pub fn random(rng: &mut (impl CryptoRng + RngCore)) -> Self {
134 super::backend::k1::random_secret(rng)
135 }
136
137 #[cfg(feature = "std")]
142 pub fn new_from_mnemonic_phrase_with_path(
143 phrase: &str,
144 path: &str,
145 ) -> Result<Self, Error> {
146 use core::str::FromStr;
147
148 let mnemonic = Mnemonic::<W>::new_from_phrase(phrase)?;
149 let path = DerivationPath::from_str(path)?;
150 Self::new_from_mnemonic(path, mnemonic)
151 }
152
153 #[cfg(feature = "std")]
157 pub fn new_from_mnemonic(d: DerivationPath, m: Mnemonic<W>) -> Result<Self, Error> {
158 let derived_priv_key = m.derive_key(d, None)?;
159 let key: &coins_bip32::prelude::SigningKey = derived_priv_key.as_ref();
160 let bytes: [u8; Self::LEN] = key.to_bytes().into();
161 Ok(SecretKey(Bytes32::from(bytes)))
162 }
163
164 pub fn public_key(&self) -> PublicKey {
166 crate::secp256::backend::k1::public_key(self)
167 }
168}
169
170impl TryFrom<Bytes32> for SecretKey {
171 type Error = Error;
172
173 fn try_from(b: Bytes32) -> Result<Self, Self::Error> {
174 match k256::SecretKey::from_bytes((&*b).into()) {
175 Ok(_) => Ok(Self(b)),
176 Err(_) => Err(Error::InvalidSecretKey),
177 }
178 }
179}
180
181impl TryFrom<&[u8]> for SecretKey {
182 type Error = Error;
183
184 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
185 Bytes32::try_from(slice)
186 .map_err(|_| Error::InvalidSecretKey)
187 .and_then(SecretKey::try_from)
188 }
189}
190
191impl str::FromStr for SecretKey {
192 type Err = Error;
193
194 fn from_str(s: &str) -> Result<Self, Self::Err> {
195 Bytes32::from_str(s)
196 .map_err(|_| Error::InvalidSecretKey)
197 .and_then(SecretKey::try_from)
198 }
199}
200
201#[cfg(test)]
202#[allow(non_snake_case)]
203mod tests {
204 #[cfg(feature = "random")]
205 #[test]
206 fn default__yields_valid_secret() {
207 use super::SecretKey;
208 let _ = SecretKey::default();
209 }
210}