Skip to content

Commit

Permalink
ecdsa: add try_sign_digest_rfc6979 and verify_digest primitives (#…
Browse files Browse the repository at this point in the history
…475)

Adds primitive methods that operate on a generic `D` digest algorithm
implementation.

This simplifies invoking the primitive methods.
  • Loading branch information
tarcieri authored May 10, 2022
1 parent a830713 commit b33804b
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 16 deletions.
43 changes: 42 additions & 1 deletion ecdsa/src/hazmat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,17 @@ use crate::{
Signature,
};

#[cfg(all(feature = "arithmetic", feature = "digest"))]
use signature::digest::FixedOutput;

#[cfg(all(feature = "rfc6979"))]
use {
elliptic_curve::ScalarCore,
signature::digest::{
block_buffer::Eager,
core_api::{BlockSizeUser, BufferKindUser, CoreProxy, FixedOutputCore},
generic_array::typenum::{IsLess, Le, NonZero, U256},
FixedOutput, HashMarker, OutputSizeUser,
HashMarker, OutputSizeUser,
},
};

Expand Down Expand Up @@ -139,6 +142,34 @@ where
let k = Self::from(ScalarCore::<C>::new(*k).unwrap());
self.try_sign_prehashed(k, z)
}

/// Try to sign the given digest instance using the method described in
/// [RFC6979].
///
/// [RFC6979]: https://datatracker.ietf.org/doc/html/rfc6979
#[cfg(all(feature = "rfc6979"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rfc6979")))]
fn try_sign_digest_rfc6979<D>(
&self,
msg_digest: D,
ad: &[u8],
) -> Result<(Signature<C>, Option<RecoveryId>)>
where
Self: From<ScalarCore<C>>,
C::UInt: for<'a> From<&'a Self>,
D: CoreProxy + FixedOutput<OutputSize = FieldSize<C>>,
D::Core: BlockSizeUser
+ BufferKindUser<BufferKind = Eager>
+ Clone
+ Default
+ FixedOutputCore
+ HashMarker
+ OutputSizeUser<OutputSize = D::OutputSize>,
<D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
self.try_sign_prehashed_rfc6979::<D>(msg_digest.finalize_fixed(), ad)
}
}

/// Verify the given prehashed message using ECDSA.
Expand Down Expand Up @@ -182,6 +213,16 @@ where
Err(Error::new())
}
}

/// Verify message digest against the provided signature.
#[cfg(feature = "digest")]
#[cfg_attr(docsrs, doc(cfg(feature = "digest")))]
fn verify_digest<D>(&self, msg_digest: D, sig: &Signature<C>) -> Result<()>
where
D: FixedOutput<OutputSize = FieldSize<C>>,
{
self.verify_prehashed(msg_digest.finalize_fixed(), sig)
}
}

/// Bind a preferred [`Digest`] algorithm to an elliptic curve type.
Expand Down
16 changes: 6 additions & 10 deletions ecdsa/src/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@ where
SignatureSize<C>: ArrayLength<u8>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// TODO(tarcieri): use `finish_non_exhaustive` when stable
f.debug_tuple("SigningKey").field(&"...").finish()
f.debug_struct("SigningKey").finish_non_exhaustive()
}
}

Expand Down Expand Up @@ -192,8 +191,7 @@ where
///
/// [RFC6979 § 3.2]: https://tools.ietf.org/html/rfc6979#section-3
fn try_sign_digest(&self, msg_digest: D) -> Result<Signature<C>> {
let digest = msg_digest.finalize_fixed();
Ok(self.inner.try_sign_prehashed_rfc6979::<D>(digest, &[])?.0)
Ok(self.inner.try_sign_digest_rfc6979::<D>(msg_digest, &[])?.0)
}
}

Expand All @@ -205,7 +203,7 @@ where
SignatureSize<C>: ArrayLength<u8>,
{
fn try_sign(&self, msg: &[u8]) -> Result<Signature<C>> {
self.try_sign_digest(C::Digest::new().chain_update(msg))
self.try_sign_digest(C::Digest::new_with_prefix(msg))
}
}

Expand All @@ -232,13 +230,11 @@ where
fn try_sign_digest_with_rng(
&self,
mut rng: impl CryptoRng + RngCore,
msg: D,
msg_digest: D,
) -> Result<Signature<C>> {
let mut ad = FieldBytes::<C>::default();
rng.fill_bytes(&mut ad);

let digest = msg.finalize_fixed();
Ok(self.inner.try_sign_prehashed_rfc6979::<D>(digest, &ad)?.0)
Ok(self.inner.try_sign_digest_rfc6979::<D>(msg_digest, &ad)?.0)
}
}

Expand All @@ -250,7 +246,7 @@ where
SignatureSize<C>: ArrayLength<u8>,
{
fn try_sign_with_rng(&self, rng: impl CryptoRng + RngCore, msg: &[u8]) -> Result<Signature<C>> {
self.try_sign_digest_with_rng(rng, C::Digest::new().chain_update(msg))
self.try_sign_digest_with_rng(rng, C::Digest::new_with_prefix(msg))
}
}

Expand Down
10 changes: 5 additions & 5 deletions ecdsa/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ where
/// Returns an [`Error`] if the given affine point is the additive identity
/// (a.k.a. point at infinity).
pub fn from_affine(affine: AffinePoint<C>) -> Result<Self> {
let inner = PublicKey::from_affine(affine).map_err(|_| Error::new())?;
Ok(Self { inner })
Ok(Self {
inner: PublicKey::from_affine(affine).map_err(|_| Error::new())?,
})
}

/// Initialize [`VerifyingKey`] from an [`EncodedPoint`].
Expand Down Expand Up @@ -93,8 +94,7 @@ where
SignatureSize<C>: ArrayLength<u8>,
{
fn verify_digest(&self, msg_digest: D, signature: &Signature<C>) -> Result<()> {
let digest = msg_digest.finalize_fixed();
self.inner.as_affine().verify_prehashed(digest, signature)
self.inner.as_affine().verify_digest(msg_digest, signature)
}
}

Expand All @@ -107,7 +107,7 @@ where
SignatureSize<C>: ArrayLength<u8>,
{
fn verify(&self, msg: &[u8], signature: &Signature<C>) -> Result<()> {
self.verify_digest(C::Digest::new().chain_update(msg), signature)
self.verify_digest(C::Digest::new_with_prefix(msg), signature)
}
}

Expand Down

0 comments on commit b33804b

Please sign in to comment.