Skip to content

Commit

Permalink
k256: use generic signing implementation from ecdsa
Browse files Browse the repository at this point in the history
Uses `ecdsa::hazmat::sign_prehashed` which provides a generic
implementation of ECDSA signing.

The code is largely identical to what was previously used, that code
having originally been copied from `p256` and updated iteratively to
match the generic implementation in the `ecdsa` crate as it evolved.

The only reason why we can't use the default implementation of
`SignPrimitive::try_sign_prehashed` is to handle low-S normalization,
which is unique to the secp256k1 ecosystem but nearly ubiquitous and
very much expected of ECDSA/secp256k1 implementations.

In the next release this can hopefully be upstreamed to the `ecdsa`
crate as well, which would eliminate the need for the `SignPrimitive`
and `VerifyPrimitive` traits (which pretty much exist exclusively so
`k256` can have custom logic to handle low-S normalization).
  • Loading branch information
tarcieri committed Jul 21, 2023
1 parent 6078071 commit 27cda04
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 41 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion k256/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ elliptic-curve = { version = "0.13", default-features = false, features = ["hazm

# optional dependencies
once_cell = { version = "1.18", optional = true, default-features = false }
ecdsa-core = { version = "0.16", package = "ecdsa", optional = true, default-features = false, features = ["der"] }
ecdsa-core = { version = "0.16.8", package = "ecdsa", optional = true, default-features = false, features = ["der"] }
hex-literal = { version = "0.4", optional = true }
serdect = { version = "0.2", optional = true, default-features = false }
sha2 = { version = "0.10", optional = true, default-features = false }
Expand Down
45 changes: 7 additions & 38 deletions k256/src/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,9 @@ use crate::Secp256k1;

#[cfg(feature = "ecdsa")]
use {
crate::{AffinePoint, FieldBytes, ProjectivePoint, Scalar},
crate::{AffinePoint, FieldBytes, Scalar},
ecdsa_core::hazmat::{SignPrimitive, VerifyPrimitive},
elliptic_curve::{
bigint::U256,
ops::{Invert, MulByGenerator, Reduce},
scalar::IsHigh,
subtle::CtOption,
},
elliptic_curve::{ops::Invert, scalar::IsHigh, subtle::CtOption},
};

/// ECDSA/secp256k1 signature (fixed-size)
Expand Down Expand Up @@ -194,37 +189,11 @@ impl SignPrimitive<Secp256k1> for Scalar {
where
K: AsRef<Self> + Invert<Output = CtOption<Self>>,
{
if k.as_ref().is_zero().into() {
return Err(Error::new());
}

let z = <Self as Reduce<U256>>::reduce_bytes(z);

// Compute scalar inversion of 𝑘
let k_inv = Option::<Scalar>::from(k.invert()).ok_or_else(Error::new)?;

// Compute 𝑹 = 𝑘×𝑮
let R = ProjectivePoint::mul_by_generator(k.as_ref()).to_affine();

// Lift x-coordinate of 𝑹 (element of base field) into a serialized big
// integer, then reduce it into an element of the scalar field
let r = <Self as Reduce<U256>>::reduce_bytes(&R.x.to_bytes());

// Compute 𝒔 as a signature over 𝒓 and 𝒛.
let s = k_inv * (z + (r * self));

if s.is_zero().into() {
return Err(Error::new());
}

let signature = Signature::from_scalars(r, s)?;
let is_r_odd = R.y.normalize().is_odd();
let is_s_high = s.is_high();
let is_y_odd = is_r_odd ^ is_s_high;
let signature_low = signature.normalize_s().unwrap_or(signature);
let recovery_id = RecoveryId::new(is_y_odd.into(), false);

Ok((signature_low, Some(recovery_id)))
let (sig, recid) = hazmat::sign_prehashed::<Secp256k1, K>(&self, k, z)?;
let is_y_odd = recid.is_y_odd() ^ bool::from(sig.s().is_high());
let sig_low = sig.normalize_s().unwrap_or(sig);
let recid = RecoveryId::new(is_y_odd, recid.is_x_reduced());
Ok((sig_low, Some(recid)))
}
}

Expand Down

0 comments on commit 27cda04

Please sign in to comment.