#![allow(non_snake_case)]
use super::{BELT_OID, Signature, VerifyingKey};
use crate::{BignP256, FieldBytes, NonZeroScalar, ProjectivePoint, PublicKey, Scalar, SecretKey};
use belt_hash::{BeltHash, Digest};
use core::fmt::{self, Debug};
use elliptic_curve::{
Curve, Field, FieldBytesEncoding, Generate, Group, PrimeField,
array::{Array, sizes::U32, typenum::Unsigned},
ops::Reduce,
point::AffineCoordinates,
subtle::{Choice, ConstantTimeEq},
};
use rand_core::TryCryptoRng;
use signature::{Error, KeypairRef, MultipartSigner, Result, Signer, hazmat::PrehashSigner};
#[derive(Clone)]
pub struct SigningKey {
secret_scalar: NonZeroScalar,
verifying_key: VerifyingKey,
}
impl SigningKey {
pub fn from_bytes(bytes: &FieldBytes) -> Result<Self> {
Self::from_slice(bytes)
}
pub fn from_slice(slice: &[u8]) -> Result<Self> {
NonZeroScalar::try_from(slice)
.map(Into::into)
.map_err(|_| Error::new())
}
pub fn from_nonzero_scalar(secret_scalar: NonZeroScalar) -> Self {
let public_key = PublicKey::from_secret_scalar(&secret_scalar);
Self {
secret_scalar,
verifying_key: public_key.into(),
}
}
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 Generate for SigningKey {
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(
rng: &mut R,
) -> core::result::Result<Self, R::Error> {
NonZeroScalar::try_generate_from_rng(rng).map(Into::into)
}
}
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 h_word: Array<u8, U32> = Array::try_from(prehash).map_err(|_| Error::new())?;
let h = Scalar::reduce(&h_word);
let k = Scalar::from_repr(bign_genk::generate_k::<BeltHash, belt_block::BeltBlock, _>(
&self.secret_scalar.to_bytes(),
&FieldBytesEncoding::<BignP256>::encode_field_bytes(BignP256::ORDER.as_ref()),
&h.to_bytes(),
&[],
))
.unwrap();
let R = ProjectivePoint::mul_by_generator(&k).to_affine();
let Rx = R.x();
let mut hasher = BeltHash::new();
hasher.update(BELT_OID);
hasher.update(Rx);
hasher.update(prehash);
let mut s0 = hasher.finalize();
s0[16..].fill(0x00);
let s0_scalar = Scalar::from_slice(&s0).ok_or_else(Error::new)?;
let right = s0_scalar
.add(&Scalar::from_u64(2).pow([128, 0, 0, 0]))
.multiply(&self.secret_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> {
self.try_multipart_sign(&[msg])
}
}
impl MultipartSigner<Signature> for SigningKey {
fn try_multipart_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 From<NonZeroScalar> for SigningKey {
fn from(secret_scalar: NonZeroScalar) -> Self {
Self::from_nonzero_scalar(secret_scalar)
}
}
impl From<SecretKey> for SigningKey {
fn from(secret_key: SecretKey) -> Self {
secret_key.to_nonzero_scalar().into()
}
}
impl From<SigningKey> for SecretKey {
fn from(signing_key: SigningKey) -> Self {
signing_key.secret_scalar.into()
}
}
impl KeypairRef for SigningKey {
type VerifyingKey = VerifyingKey;
}