use secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, SignOnly, VerifyOnly};
use zeroize::Zeroizing;
use crate::curve::{
CurveError, CurvePrivateKey, CurvePublicKey, TweakableKey, secp256k1::Secp256k1Backend,
};
pub struct Secp256k1FfiBackend;
struct ScalarGuard(Scalar);
impl ScalarGuard {
fn from_bytes(bytes: &[u8; 32]) -> Result<Self, CurveError> {
let bytes = Zeroizing::new(*bytes);
Scalar::from_be_bytes(*bytes).map(Self).map_err(CurveError::new)
}
}
impl AsRef<Scalar> for ScalarGuard {
fn as_ref(&self) -> &Scalar {
&self.0
}
}
impl Drop for ScalarGuard {
fn drop(&mut self) {
self.0.non_secure_erase();
}
}
#[inline]
fn with_signing_context<R>(f: impl FnOnce(&Secp256k1<SignOnly>) -> R) -> R {
#[cfg(not(feature = "std"))]
{
let secp = Secp256k1::signing_only();
f(&secp)
}
#[cfg(feature = "std")]
{
fn signing_context() -> &'static Secp256k1<SignOnly> {
use std::sync::OnceLock;
static CONTEXT: OnceLock<Secp256k1<SignOnly>> = OnceLock::new();
CONTEXT.get_or_init(Secp256k1::signing_only)
}
f(signing_context())
}
}
#[inline]
fn with_verification_context<R>(f: impl FnOnce(&Secp256k1<VerifyOnly>) -> R) -> R {
#[cfg(not(feature = "std"))]
{
let secp = Secp256k1::verification_only();
f(&secp)
}
#[cfg(feature = "std")]
{
fn verification_context() -> &'static Secp256k1<VerifyOnly> {
use std::sync::OnceLock;
static CONTEXT: OnceLock<Secp256k1<VerifyOnly>> = OnceLock::new();
CONTEXT.get_or_init(Secp256k1::verification_only)
}
f(verification_context())
}
}
impl CurvePublicKey for PublicKey {
type Error = CurveError;
type Bytes = [u8; 33];
fn from_bytes(bytes: &Self::Bytes) -> Result<Self, Self::Error> {
PublicKey::from_byte_array_compressed(*bytes).map_err(CurveError::new)
}
fn to_bytes(&self) -> Self::Bytes {
self.serialize()
}
}
impl TweakableKey for PublicKey {
type Error = CurveError;
fn add_tweak(&self, tweak: &[u8; 32]) -> Result<Self, Self::Error> {
let scalar = ScalarGuard::from_bytes(tweak)?;
with_verification_context(|secp| {
(*self).add_exp_tweak(secp, scalar.as_ref()).map_err(CurveError::new)
})
}
}
impl CurvePrivateKey for SecretKey {
type Error = CurveError;
type PublicKey = PublicKey;
type Bytes = [u8; 32];
fn from_bytes(bytes: &Self::Bytes) -> Result<Self, Self::Error> {
SecretKey::from_byte_array(*bytes).map_err(CurveError::new)
}
fn to_bytes(&self) -> Self::Bytes {
self.secret_bytes()
}
fn to_public(&self) -> Self::PublicKey {
with_signing_context(|secp| PublicKey::from_secret_key(secp, self))
}
fn zeroize(&mut self) {
self.non_secure_erase();
}
}
impl TweakableKey for SecretKey {
type Error = CurveError;
fn add_tweak(&self, tweak: &[u8; 32]) -> Result<Self, Self::Error> {
let scalar = ScalarGuard::from_bytes(tweak)?;
(*self).add_tweak(scalar.as_ref()).map_err(CurveError::new)
}
}
impl Secp256k1Backend for Secp256k1FfiBackend {
type PublicKey = PublicKey;
type PrivateKey = SecretKey;
}