#[cfg(feature = "alloc")]
use alloc::boxed::Box;
use super::{BELT_OID, Signature};
use crate::{
AffinePoint, BignP256, FieldBytes, Hash, ProjectivePoint, PublicKey, Scalar, Sec1Point,
};
use belt_hash::{
BeltHash,
digest::{Digest, FixedOutput},
};
use elliptic_curve::{
Curve, Field, Group,
array::{Array, sizes::U32, typenum::Unsigned},
ops::{LinearCombination, Reduce},
point::AffineCoordinates,
sec1::ToSec1Point,
};
use signature::{Error, MultipartVerifier, Result, Verifier, hazmat::PrehashVerifier};
#[derive(Clone, Copy, Debug)]
pub struct VerifyingKey {
public_key: PublicKey,
}
impl VerifyingKey {
pub fn from_affine(affine: AffinePoint) -> Result<Self> {
Ok(Self {
public_key: PublicKey::from_affine(affine).map_err(|_| Error::new())?,
})
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
Ok(Self {
public_key: PublicKey::from_bytes(bytes).map_err(|_| Error::new())?,
})
}
pub fn as_affine(&self) -> &AffinePoint {
self.public_key.as_affine()
}
pub(crate) fn hash_msg(&self, msg: &[&[u8]]) -> Hash {
let mut hasher = BeltHash::new();
msg.iter().for_each(|slice| hasher.update(slice));
hasher.finalize_fixed()
}
#[cfg(feature = "alloc")]
pub fn to_bytes(&self) -> Box<[u8]> {
self.public_key.to_bytes()
}
}
impl PrehashVerifier<Signature> for VerifyingKey {
#[allow(deprecated)] fn verify_prehash(&self, prehash: &[u8], signature: &Signature) -> Result<()> {
if prehash.len() != <BignP256 as Curve>::FieldBytesSize::USIZE {
return Err(Error::new());
}
let s0 = signature.s0();
let s1 = signature.s1();
let hash: Array<u8, U32> = Array::clone_from_slice(prehash);
let hw = Scalar::reduce(FieldBytes::from_slice(&hash));
let left = s1.add(&hw);
let right = s0.add(&Scalar::from_u64(2).pow([128, 0, 0, 0]));
let r = ProjectivePoint::lincomb(&[
(ProjectivePoint::generator(), left),
(self.public_key.to_projective(), right),
]);
if r.is_identity().into() {
return Err(Error::new());
}
let r = r.to_affine();
let rx = r.x();
let mut hasher = BeltHash::new();
hasher.update(BELT_OID);
hasher.update(rx);
hasher.update(prehash);
let t = hasher.finalize();
let s0 = &mut s0.to_bytes()[..16];
if s0 == &t.as_slice()[..16] {
Ok(())
} else {
Err(Error::new())
}
}
}
impl Verifier<Signature> for VerifyingKey {
fn verify(&self, msg: &[u8], signature: &Signature) -> Result<()> {
self.multipart_verify(&[msg], signature)
}
}
impl MultipartVerifier<Signature> for VerifyingKey {
fn multipart_verify(&self, msg: &[&[u8]], signature: &Signature) -> Result<()> {
let hash = self.hash_msg(msg);
self.verify_prehash(&hash, signature)
}
}
impl AsRef<AffinePoint> for VerifyingKey {
fn as_ref(&self) -> &AffinePoint {
self.as_affine()
}
}
impl From<PublicKey> for VerifyingKey {
fn from(public_key: PublicKey) -> VerifyingKey {
VerifyingKey { public_key }
}
}
impl From<&PublicKey> for VerifyingKey {
fn from(public_key: &PublicKey) -> VerifyingKey {
VerifyingKey::from(*public_key)
}
}
impl From<VerifyingKey> for PublicKey {
fn from(verifying_key: VerifyingKey) -> PublicKey {
verifying_key.public_key
}
}
impl From<&VerifyingKey> for PublicKey {
fn from(verifying_key: &VerifyingKey) -> PublicKey {
PublicKey::from(*verifying_key)
}
}
impl ToSec1Point<BignP256> for VerifyingKey {
fn to_sec1_point(&self, compress: bool) -> Sec1Point {
self.as_affine().to_sec1_point(compress)
}
}