#![allow(non_snake_case)]
use super::{Signature, VerifyingKey, BELT_OID};
use crate::{BignP256, FieldBytes, NonZeroScalar, ProjectivePoint, PublicKey, Scalar, SecretKey};
use core::fmt::{self, Debug};
use elliptic_curve::{
generic_array::typenum::Unsigned,
ops::{MulByGenerator, Reduce},
point::AffineCoordinates,
subtle::{Choice, ConstantTimeEq},
Curve, Field, FieldBytesEncoding, PrimeField,
};
use signature::{hazmat::PrehashSigner, Error, KeypairRef, Result, Signer};
use belt_hash::{BeltHash, Digest};
use crypto_bigint::{consts::U32, generic_array::GenericArray};
#[derive(Clone)]
pub struct SigningKey {
secret_scalar: NonZeroScalar,
verifying_key: VerifyingKey,
}
impl SigningKey {
pub fn new(secret_key: &SecretKey) -> Result<Self> {
Self::from_nonzero_scalar(secret_key.to_nonzero_scalar())
}
pub fn from_bytes(bytes: &FieldBytes) -> Result<Self> {
Self::from_slice(bytes)
}
pub fn from_slice(slice: &[u8]) -> Result<Self> {
let secret_scalar = NonZeroScalar::try_from(slice).map_err(|_| Error::new())?;
Self::from_nonzero_scalar(secret_scalar)
}
pub fn from_nonzero_scalar(secret_scalar: NonZeroScalar) -> Result<Self> {
let public_key = PublicKey::from_secret_scalar(&secret_scalar);
let verifying_key = VerifyingKey::new(public_key)?;
Ok(Self {
secret_scalar,
verifying_key,
})
}
pub fn to_bytes(&self) -> FieldBytes {
self.secret_scalar.to_bytes()
}
pub fn as_nonzero_scalar(&self) -> &NonZeroScalar {
&self.secret_scalar
}
pub fn verifying_key(&self) -> &VerifyingKey {
&self.verifying_key
}
}
impl PrehashSigner<Signature> for SigningKey {
fn sign_prehash(&self, prehash: &[u8]) -> Result<Signature> {
if prehash.len() != <BignP256 as Curve>::FieldBytesSize::USIZE {
return Err(Error::new());
}
let mut h_word: GenericArray<u8, U32> = GenericArray::clone_from_slice(prehash);
h_word.reverse();
let h = Scalar::reduce_bytes(&h_word);
let k = Scalar::from_repr(rfc6979::generate_k::<BeltHash, _>(
&self.secret_scalar.to_repr(),
&FieldBytesEncoding::<BignP256>::encode_field_bytes(&BignP256::ORDER),
&h.to_bytes(),
&[],
))
.unwrap();
let mut R: GenericArray<u8, _> = ProjectivePoint::mul_by_generator(&k).to_affine().x();
R.reverse();
let mut hasher = BeltHash::new();
hasher.update(BELT_OID);
hasher.update(R);
hasher.update(prehash);
let mut s0 = hasher.finalize();
s0[16..].fill(0x00);
s0.reverse();
let s0_scalar = Scalar::from_slice(&s0).map_err(|_| Error::new())?;
let right = s0_scalar
.add(&Scalar::from_u64(2).pow([128, 0, 0, 0]))
.multiply(self.as_nonzero_scalar());
let s1 = k.sub(&h).sub(&right);
Signature::from_scalars(s0_scalar, s1)
}
}
impl Signer<Signature> for SigningKey {
fn try_sign(&self, msg: &[u8]) -> Result<Signature> {
let hash = self.verifying_key.hash_msg(msg);
self.sign_prehash(&hash)
}
}
impl AsRef<VerifyingKey> for SigningKey {
fn as_ref(&self) -> &VerifyingKey {
&self.verifying_key
}
}
impl ConstantTimeEq for SigningKey {
fn ct_eq(&self, other: &Self) -> Choice {
self.secret_scalar.ct_eq(&other.secret_scalar)
}
}
impl Debug for SigningKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SigningKey")
.field("verifying_key", &self.verifying_key)
.finish_non_exhaustive()
}
}
impl Eq for SigningKey {}
impl PartialEq for SigningKey {
fn eq(&self, other: &SigningKey) -> bool {
self.ct_eq(other).into()
}
}
impl KeypairRef for SigningKey {
type VerifyingKey = VerifyingKey;
}