use crate::SchnorrError;
use mohan::{dalek::scalar::Scalar, ser};
use rand::{CryptoRng, RngCore};
use std::fmt::Debug;
use subtle::{Choice, ConstantTimeEq};
use zeroize::Zeroize;
pub const SECRET_KEY_LENGTH: usize = 32;
#[derive(Default, Clone)]
pub struct SecretKey(pub(crate) Scalar);
impl Debug for SecretKey {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "SecretKey: {:?}", &self.0)
}
}
impl Eq for SecretKey {}
impl PartialEq for SecretKey {
fn eq(&self, other: &Self) -> bool {
self.ct_eq(other).unwrap_u8() == 1u8
}
}
impl ConstantTimeEq for SecretKey {
fn ct_eq(&self, other: &Self) -> Choice {
self.0.ct_eq(&other.0)
}
}
impl Zeroize for SecretKey {
fn zeroize(&mut self) {
mohan::zeroize_hack(&mut self.0);
}
}
impl Drop for SecretKey {
fn drop(&mut self) {
self.zeroize();
}
}
impl SecretKey {
#[inline]
pub fn to_bytes(&self) -> [u8; SECRET_KEY_LENGTH] {
self.0.to_bytes()
}
#[inline]
pub fn as_bytes<'a>(&'a self) -> &'a [u8; SECRET_KEY_LENGTH] {
&self.0.as_bytes()
}
#[inline]
pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, SchnorrError> {
if bytes.len() != SECRET_KEY_LENGTH {
return Err(SchnorrError::SerError);
}
let mut bits: [u8; 32] = [0u8; 32];
bits.copy_from_slice(&bytes[..32]);
Ok(SecretKey(Scalar::from_bits(bits)))
}
pub fn generate<T>(csprng: &mut T) -> SecretKey
where
T: CryptoRng + RngCore,
{
SecretKey(Scalar::random(csprng))
}
pub fn to_scalar(&self) -> Scalar {
self.0
}
#[inline]
pub fn as_scalar<'a>(&'a self) -> &'a Scalar {
&self.0
}
pub fn from_scalar(s: Scalar) -> SecretKey {
SecretKey(s)
}
}
impl ser::Writeable for SecretKey {
fn write<W: ser::Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
self.0.write(writer)?;
Ok(())
}
}
impl ser::Readable for SecretKey {
fn read(reader: &mut dyn ser::Reader) -> Result<SecretKey, ser::Error> {
Ok(SecretKey(Scalar::read(reader)?))
}
}
impl std::borrow::Borrow<Scalar> for SecretKey {
#[inline]
fn borrow(&self) -> &Scalar {
self.as_scalar()
}
}