use core::fmt;
use core::ops::Deref;
use core::str::FromStr;
use bitcoin::hashes::sha256::Hash as Sha256Hash;
use bitcoin::hashes::Hash;
use bitcoin::secp256k1;
use bitcoin::secp256k1::rand::rngs::OsRng;
use bitcoin::secp256k1::schnorr::Signature;
use bitcoin::secp256k1::{Keypair, Message, Scalar};
use serde::de::Visitor;
use serde::{Deserialize, Deserializer, Serialize};
use super::{Error, PublicKey};
use crate::SECP256K1;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub struct SecretKey {
#[cfg_attr(feature = "swagger", schema(value_type = String))]
inner: secp256k1::SecretKey,
}
impl Deref for SecretKey {
type Target = secp256k1::SecretKey;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl From<secp256k1::SecretKey> for SecretKey {
fn from(inner: secp256k1::SecretKey) -> Self {
Self { inner }
}
}
impl fmt::Display for SecretKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.to_secret_hex())
}
}
impl SecretKey {
pub fn from_slice(slice: &[u8]) -> Result<Self, Error> {
Ok(Self {
inner: secp256k1::SecretKey::from_slice(slice)?,
})
}
pub fn from_hex<S>(hex: S) -> Result<Self, Error>
where
S: AsRef<str>,
{
Ok(Self {
inner: secp256k1::SecretKey::from_str(hex.as_ref())?,
})
}
pub fn generate() -> Self {
let (secret_key, _) = SECP256K1.generate_keypair(&mut OsRng);
Self { inner: secret_key }
}
pub fn to_secret_hex(&self) -> String {
self.inner.display_secret().to_string()
}
pub fn as_secret_bytes(&self) -> &[u8] {
self.inner.as_ref()
}
pub fn to_secret_bytes(&self) -> [u8; 32] {
self.inner.secret_bytes()
}
pub fn sign(&self, msg: &[u8]) -> Result<Signature, Error> {
let hash: Sha256Hash = Sha256Hash::hash(msg);
let msg = Message::from_digest_slice(hash.as_ref())?;
Ok(SECP256K1.sign_schnorr(&msg, &Keypair::from_secret_key(&SECP256K1, &self.inner)))
}
pub fn public_key(&self) -> PublicKey {
self.inner.public_key(&SECP256K1).into()
}
#[inline]
pub fn to_scalar(self) -> Scalar {
Scalar::from(self.inner)
}
#[inline]
pub fn as_scalar(&self) -> Scalar {
Scalar::from(self.inner)
}
}
impl FromStr for SecretKey {
type Err = Error;
fn from_str(secret_key: &str) -> Result<Self, Self::Err> {
Self::from_hex(secret_key)
}
}
impl Serialize for SecretKey {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match serializer.is_human_readable() {
true => serializer.serialize_str(&self.to_secret_hex()),
false => serializer.serialize_bytes(self.as_secret_bytes()),
}
}
}
impl<'de> Deserialize<'de> for SecretKey {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
match deserializer.is_human_readable() {
true => {
let secret_key: String = String::deserialize(deserializer)?;
SecretKey::from_hex(secret_key).map_err(serde::de::Error::custom)
}
false => {
struct SecretKeyVisitor;
impl Visitor<'_> for SecretKeyVisitor {
type Value = SecretKey;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a byte array")
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
SecretKey::from_slice(value).map_err(serde::de::Error::custom)
}
}
deserializer.deserialize_bytes(SecretKeyVisitor)
}
}
}
}
impl Drop for SecretKey {
fn drop(&mut self) {
self.inner.non_secure_erase();
tracing::trace!("Secret Key dropped.");
}
}