use alloc::string::String;
use core::ops::{Deref, DerefMut};
use core::str::FromStr;
#[cfg(feature = "rand")]
use rand::RngCore;
#[cfg(all(feature = "std", feature = "os-rng"))]
use rand::TryRngCore;
#[cfg(all(feature = "std", feature = "os-rng"))]
use rand::rngs::OsRng;
use serde::{Deserialize, Deserializer};
use super::Error;
use crate::nips::nip19::FromBech32;
#[cfg(all(feature = "std", feature = "os-rng", feature = "nip49"))]
use crate::nips::nip49::{self, EncryptedSecretKey, KeySecurity};
#[cfg(feature = "rand")]
use crate::util;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SecretKey {
inner: secp256k1::SecretKey,
}
impl Deref for SecretKey {
type Target = secp256k1::SecretKey;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for SecretKey {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl From<secp256k1::SecretKey> for SecretKey {
fn from(inner: secp256k1::SecretKey) -> Self {
Self { inner }
}
}
impl SecretKey {
pub const LEN: usize = 32;
pub fn parse(secret_key: &str) -> Result<Self, Error> {
if let Ok(secret_key) = Self::from_hex(secret_key) {
return Ok(secret_key);
}
if let Ok(secret_key) = Self::from_bech32(secret_key) {
return Ok(secret_key);
}
Err(Error::InvalidSecretKey)
}
#[inline]
pub fn from_slice(slice: &[u8]) -> Result<Self, Error> {
Ok(Self {
inner: secp256k1::SecretKey::from_slice(slice)?,
})
}
#[inline]
pub fn from_hex(hex: &str) -> Result<Self, Error> {
Ok(Self {
inner: secp256k1::SecretKey::from_str(hex)?,
})
}
#[inline]
#[cfg(all(feature = "std", feature = "os-rng"))]
pub fn generate() -> Self {
Self::generate_with_rng(&mut OsRng.unwrap_err())
}
#[inline]
#[cfg(feature = "rand")]
pub fn generate_with_rng<R>(rng: &mut R) -> Self
where
R: RngCore,
{
let mut data: [u8; Self::LEN] = util::random_32_bytes(rng);
loop {
match secp256k1::SecretKey::from_slice(&data) {
Ok(secret_key) => return Self { inner: secret_key },
Err(_) => data = util::random_32_bytes(rng),
}
}
}
#[inline]
pub fn as_secret_bytes(&self) -> &[u8] {
self.inner.as_ref()
}
#[inline]
pub fn to_secret_bytes(&self) -> [u8; Self::LEN] {
self.inner.secret_bytes()
}
#[inline]
pub fn to_secret_hex(&self) -> String {
unsafe { String::from_utf8_unchecked(self.to_secret_hex_byte_array().to_vec()) }
}
#[inline]
pub fn to_secret_hex_byte_array(&self) -> [u8; Self::LEN * 2] {
let mut buf = [0u8; Self::LEN * 2];
faster_hex::hex_encode(self.as_secret_bytes(), &mut buf).expect("Buffer size is correct");
buf
}
#[inline]
#[cfg(all(feature = "std", feature = "os-rng", feature = "nip49"))]
pub fn encrypt(&self, password: &str) -> Result<EncryptedSecretKey, nip49::Error> {
EncryptedSecretKey::new(self, password, 16, KeySecurity::Unknown)
}
}
impl FromStr for SecretKey {
type Err = Error;
#[inline]
fn from_str(secret_key: &str) -> Result<Self, Self::Err> {
Self::parse(secret_key)
}
}
impl<'de> Deserialize<'de> for SecretKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let secret_key: String = String::deserialize(deserializer)?;
Self::parse(&secret_key).map_err(serde::de::Error::custom)
}
}
impl Drop for SecretKey {
fn drop(&mut self) {
self.inner.non_secure_erase();
}
}