pub use ecdsa_core::signature_flow::{self, Error};
use super::NistP256;
#[cfg(feature = "ecdsa")]
use {
crate::{AffinePoint, ProjectivePoint, Scalar},
core::borrow::Borrow,
ecdsa_core::hazmat::{SignPrimitive, VerifyPrimitive},
elliptic_curve_flow::{group::ff::Field, ops::Invert},
};
pub type Signature = ecdsa_core::Signature<NistP256>;
pub type DerSignature = ecdsa_core::der::Signature<NistP256>;
#[cfg(feature = "ecdsa")]
#[cfg_attr(docsrs, doc(cfg(feature = "ecdsa")))]
pub type SigningKey = ecdsa_core::SigningKey<NistP256>;
#[cfg(feature = "ecdsa")]
#[cfg_attr(docsrs, doc(cfg(feature = "ecdsa")))]
pub type VerifyingKey = ecdsa_core::VerifyingKey<NistP256>;
use sha3::Sha3_256;
#[cfg(feature = "sha256")]
#[cfg_attr(docsrs, doc(cfg(feature = "sha256")))]
impl ecdsa_core::hazmat::DigestPrimitive for NistP256 {
type Digest = Sha3_256;
}
#[cfg(feature = "ecdsa")]
impl SignPrimitive<NistP256> for Scalar {
#[allow(clippy::many_single_char_names)]
fn try_sign_prehashed<K>(&self, ephemeral_scalar: &K, z: &Scalar) -> Result<Signature, Error>
where
K: Borrow<Scalar> + Invert<Output = Scalar>,
{
let k_inverse = ephemeral_scalar.invert();
let k = ephemeral_scalar.borrow();
if k_inverse.is_none().into() || k.is_zero().into() {
return Err(Error::new());
}
let k_inverse = k_inverse.unwrap();
let x = (ProjectivePoint::generator() * k).to_affine().x;
let r = Scalar::from_bytes_reduced(&x.to_bytes());
let s = k_inverse * (z + &(r * self));
if s.is_zero().into() {
return Err(Error::new());
}
Signature::from_scalars(r, s)
}
}
#[cfg(feature = "ecdsa")]
impl VerifyPrimitive<NistP256> for AffinePoint {
fn verify_prehashed(&self, z: &Scalar, signature: &Signature) -> Result<(), Error> {
let r = signature.r();
let s = signature.s();
let s_inv = s.invert().unwrap();
let u1 = z * &s_inv;
let u2 = *r * s_inv;
let x = ((ProjectivePoint::generator() * u1) + (ProjectivePoint::from(*self) * u2))
.to_affine()
.x;
if Scalar::from_bytes_reduced(&x.to_bytes()) == *r {
Ok(())
} else {
Err(Error::new())
}
}
}
#[cfg(all(test, feature = "ecdsa"))]
mod tests {
use crate::{
ecdsa::{signature_flow::Signer, SigningKey},
test_vectors::ecdsa::ECDSA_TEST_VECTORS,
BlindedScalar, Scalar,
};
use ecdsa_core::hazmat::SignPrimitive;
use elliptic_curve_flow::{generic_array::GenericArray, group::ff::PrimeField, rand_core::OsRng};
use hex_literal::hex;
#[test]
fn rfc6979() {
let x = &hex!("c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721");
let signer = SigningKey::from_bytes(x).unwrap();
let signature = signer.sign(b"sample");
assert_eq!(
signature.as_ref(),
&hex!(
"efd48b2aacb6a8fd1140dd9cd45e81d69d2c877b56aaf991c34d0ea84eaf3716
f7cb1c942d657c41d436c7a1b6e29f65f3e900dbb9aff4064dc4ab2f843acda8"
)[..]
);
}
#[test]
fn scalar_blinding() {
let vector = &ECDSA_TEST_VECTORS[0];
let d = Scalar::from_repr(GenericArray::clone_from_slice(vector.d)).unwrap();
let k = Scalar::from_repr(GenericArray::clone_from_slice(vector.k)).unwrap();
let k_blinded = BlindedScalar::new(k, &mut OsRng);
let z = Scalar::from_repr(GenericArray::clone_from_slice(vector.m)).unwrap();
let sig = d.try_sign_prehashed(&k_blinded, &z).unwrap();
assert_eq!(vector.r, sig.r().to_bytes().as_slice());
assert_eq!(vector.s, sig.s().to_bytes().as_slice());
}
mod sign {
use crate::{test_vectors::ecdsa::ECDSA_TEST_VECTORS, NistP256};
ecdsa_core::new_signing_test!(NistP256, ECDSA_TEST_VECTORS);
}
mod verify {
use crate::{test_vectors::ecdsa::ECDSA_TEST_VECTORS, NistP256};
ecdsa_core::new_verification_test!(NistP256, ECDSA_TEST_VECTORS);
}
mod wycheproof {
use crate::NistP256;
ecdsa_core::new_wycheproof_test!(wycheproof, "wycheproof", NistP256);
}
}