use alloc::string::String;
use core::ops::{Deref, DerefMut};
use core::str::FromStr;
#[cfg(feature = "std")]
use secp256k1::rand::rngs::OsRng;
use secp256k1::rand::Rng;
use secp256k1::{Secp256k1, Signing};
use serde::{Deserialize, Deserializer};
use super::Error;
use crate::nips::nip19::FromBech32;
#[cfg(all(feature = "std", feature = "nip49"))]
use crate::nips::nip49::{self, EncryptedSecretKey, KeySecurity};
#[cfg(feature = "std")]
use crate::SECP256K1;
#[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(feature = "std")]
pub fn generate() -> Self {
Self::generate_with_rng(&mut OsRng)
}
#[inline]
#[cfg(feature = "std")]
pub fn generate_with_rng<R>(rng: &mut R) -> Self
where
R: Rng + ?Sized,
{
Self::generate_with_ctx(SECP256K1, rng)
}
#[inline]
pub fn generate_with_ctx<C, R>(secp: &Secp256k1<C>, rng: &mut R) -> Self
where
C: Signing,
R: Rng + ?Sized,
{
let (secret_key, _) = secp.generate_keypair(rng);
Self { inner: secret_key }
}
#[inline]
pub fn to_secret_hex(&self) -> String {
hex::encode(self.as_secret_bytes())
}
#[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]
#[cfg(all(feature = "std", 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();
}
}