use {
crate::{
ecc::{Curve, PrivateKey, PublicKey},
pubkey::ecc::{Coordinates, Num},
util,
Hash,
InvalidSignature,
SignatureScheme,
},
docext::docext,
std::marker::PhantomData,
};
#[docext]
#[derive(Debug)]
pub struct Ecdsa<C, H> {
_curve: C,
hash: H,
}
impl<C, H> Ecdsa<C, H> {
pub fn new(curve: C, hash: H) -> Self {
Self {
_curve: curve,
hash,
}
}
}
impl<C, H, const DIGEST_SIZE: usize> SignatureScheme for Ecdsa<C, H>
where
H: Hash<Digest = [u8; DIGEST_SIZE]>,
C: Curve,
{
type PublicKey = PublicKey<C>;
type PrivateKey = PrivateKey<C>;
type Signature = EcdsaSignature<C, H>;
fn sign(&mut self, key: Self::PrivateKey, msg: &[u8]) -> Self::Signature {
assert!(DIGEST_SIZE >= C::SIZE);
let e = self.hash.hash(msg);
let e = Num::from_le_bytes(util::resize(e));
let mut preimage: Vec<u8> = Default::default();
preimage.extend(msg);
preimage.extend(key.0.to_le_bytes());
let mut k = Num::from_le_bytes(util::resize(self.hash.hash(&preimage)));
let mut r;
let mut s;
'retry: loop {
k = Num::from_le_bytes(util::resize(self.hash.hash(&k.to_le_bytes())));
r = match (k * C::g()).coordinates() {
Coordinates::Infinity => continue 'retry,
Coordinates::Finite(x, _) => x,
};
s = e.add(r.mul(key.0, C::N), C::N);
s = k.inv(C::N).unwrap().mul(s, C::N);
if s == Num::ZERO {
continue 'retry;
}
return EcdsaSignature {
r,
s,
_curve: Default::default(),
_hash: Default::default(),
};
}
}
fn verify(
&mut self,
key: Self::PublicKey,
msg: &[u8],
sig: &Self::Signature,
) -> Result<(), InvalidSignature> {
assert!(DIGEST_SIZE >= C::SIZE);
let e = Num::from_le_bytes(util::resize(self.hash.hash(msg)));
let i = sig.s.inv(C::N).unwrap();
let u = e.mul(i, C::N);
let v = sig.r.mul(i, C::N);
match (u * C::g() + v * key.point()).coordinates() {
Coordinates::Finite(x, _) => {
if x.eq(sig.r, C::N) {
Ok(())
} else {
Err(InvalidSignature)
}
}
Coordinates::Infinity => Err(InvalidSignature),
}
}
}
#[derive(Debug)]
pub struct EcdsaSignature<C, H> {
r: Num,
s: Num,
_curve: PhantomData<C>,
_hash: PhantomData<H>,
}
impl<C, H> Clone for EcdsaSignature<C, H> {
fn clone(&self) -> Self {
*self
}
}
impl<C, H> Copy for EcdsaSignature<C, H> {}
impl<C: Curve, H> EcdsaSignature<C, H> {
pub fn new(r: Num, s: Num) -> Result<Self, InvalidSignature> {
if r < C::N && s < C::N {
Ok(Self {
r,
s,
_curve: Default::default(),
_hash: Default::default(),
})
} else {
Err(InvalidSignature)
}
}
pub fn r(&self) -> Num {
self.r
}
pub fn s(&self) -> Num {
self.s
}
}