diff --git a/ecdsa/CHANGELOG.md b/ecdsa/CHANGELOG.md index 1125fd1..77609d8 100644 --- a/ecdsa/CHANGELOG.md +++ b/ecdsa/CHANGELOG.md @@ -4,14 +4,6 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 0.17.0 (UNRELEASED) - -### Changed -- `DigestPrimitive` was moved off of hazmat ([#945]) -- `DigestPrimitive` has been renamed `DigestAlgorithm` ([#945]) - -[#945]: https://github.com/RustCrypto/signatures/pull/945 - ## 0.16.9 (2023-11-16) ### Changed - Loosen `signature` bound to `2.0, <2.3` ([#756]) diff --git a/ecdsa/Cargo.toml b/ecdsa/Cargo.toml index 4cde7c0..45fcc12 100644 --- a/ecdsa/Cargo.toml +++ b/ecdsa/Cargo.toml @@ -45,7 +45,6 @@ digest = ["dep:digest", "elliptic-curve/digest", "signature/digest"] hazmat = [] pkcs8 = ["digest", "elliptic-curve/pkcs8", "der"] pem = ["elliptic-curve/pem", "pkcs8"] -rfc6979 = ["arithmetic", "digest", "dep:rfc6979"] serde = ["elliptic-curve/serde", "pkcs8", "serdect"] signing = ["arithmetic", "digest", "hazmat", "rfc6979"] verifying = ["arithmetic", "digest", "hazmat"] diff --git a/ecdsa/src/der.rs b/ecdsa/src/der.rs index 3da220f..65a88de 100644 --- a/ecdsa/src/der.rs +++ b/ecdsa/src/der.rs @@ -382,10 +382,10 @@ fn find_scalar_range(outer: &[u8], inner: &[u8]) -> Result> { Ok(Range { start, end }) } -#[cfg(feature = "digest")] +#[cfg(all(feature = "digest", feature = "hazmat"))] impl signature::PrehashSignature for Signature where - C: EcdsaCurve + crate::DigestAlgorithm, + C: EcdsaCurve + crate::hazmat::DigestPrimitive, MaxSize: ArraySize, as Add>::Output: Add + ArraySize, { diff --git a/ecdsa/src/hazmat.rs b/ecdsa/src/hazmat.rs index 2065e19..11c776d 100644 --- a/ecdsa/src/hazmat.rs +++ b/ecdsa/src/hazmat.rs @@ -27,21 +27,46 @@ use { }, }; -#[cfg(feature = "rfc6979")] +#[cfg(feature = "digest")] use { - elliptic_curve::FieldBytesEncoding, - signature::digest::{Digest, FixedOutput, FixedOutputReset, core_api::BlockSizeUser}, + elliptic_curve::FieldBytesSize, + signature::{ + PrehashSignature, + digest::{Digest, FixedOutput, FixedOutputReset, core_api::BlockSizeUser}, + }, }; -#[cfg(any(feature = "arithmetic", feature = "rfc6979"))] +#[cfg(feature = "rfc6979")] +use elliptic_curve::FieldBytesEncoding; + +#[cfg(any(feature = "arithmetic", feature = "digest"))] use crate::{Signature, elliptic_curve::array::ArraySize}; +/// Bind a preferred [`Digest`] algorithm to an elliptic curve type. +/// +/// Generally there is a preferred variety of the SHA-2 family used with ECDSA +/// for a particular elliptic curve. +/// +/// This trait can be used to specify it, and with it receive a blanket impl of +/// [`PrehashSignature`], used by [`signature_derive`][1]) for the [`Signature`] +/// type for a particular elliptic curve. +/// +/// [1]: https://github.com/RustCrypto/traits/tree/master/signature/derive #[cfg(feature = "digest")] -#[deprecated( - since = "0.17.0", - note = "`DigestAlgorithm` is no longer in `hazmat`, please use `ecdsa::DigestAlgorithm` instead" -)] -pub use crate::DigestAlgorithm; +pub trait DigestPrimitive: EcdsaCurve { + /// Preferred digest to use when computing ECDSA signatures for this + /// elliptic curve. This is typically a member of the SHA-2 family. + type Digest: BlockSizeUser + Digest + FixedOutput + FixedOutputReset; +} + +#[cfg(feature = "digest")] +impl PrehashSignature for Signature +where + C: DigestPrimitive, + as core::ops::Add>::Output: ArraySize, +{ + type Digest = C::Digest; +} /// Partial implementation of the `bits2int` function as defined in /// [RFC6979 § 2.3.2] as well as [SEC1] § 2.3.8. diff --git a/ecdsa/src/lib.rs b/ecdsa/src/lib.rs index 02adf41..2c1cc3e 100644 --- a/ecdsa/src/lib.rs +++ b/ecdsa/src/lib.rs @@ -102,13 +102,9 @@ use { }; #[cfg(feature = "digest")] -use { - digest::{ - Digest, FixedOutput, FixedOutputReset, - const_oid::{AssociatedOid, ObjectIdentifier}, - core_api::BlockSizeUser, - }, - signature::PrehashSignature, +use digest::{ + Digest, + const_oid::{AssociatedOid, ObjectIdentifier}, }; #[cfg(feature = "pkcs8")] @@ -468,15 +464,15 @@ where /// /// To support non-default digest algorithms, use the [`SignatureWithOid`] /// type instead. -#[cfg(feature = "digest")] +#[cfg(all(feature = "digest", feature = "hazmat"))] impl AssociatedOid for Signature where - C: DigestAlgorithm, + C: hazmat::DigestPrimitive, C::Digest: AssociatedOid, { const OID: ObjectIdentifier = match ecdsa_oid_for_digest(C::Digest::OID) { Some(oid) => oid, - None => panic!("no RFC5758 ECDSA OID defined for DigestAlgorithm::Digest"), + None => panic!("no RFC5758 ECDSA OID defined for DigestPrimitive::Digest"), }; } @@ -725,14 +721,14 @@ where } /// NOTE: this implementation assumes the default digest for the given elliptic -/// curve as defined by [`DigestAlgorithm`]. +/// curve as defined by [`hazmat::DigestPrimitive`]. /// /// When working with alternative digests, you will need to use e.g. /// [`SignatureWithOid::new_with_digest`]. -#[cfg(feature = "digest")] +#[cfg(all(feature = "digest", feature = "hazmat"))] impl SignatureEncoding for SignatureWithOid where - C: DigestAlgorithm, + C: hazmat::DigestPrimitive, C::Digest: AssociatedOid, SignatureSize: ArraySize, { @@ -740,14 +736,14 @@ where } /// NOTE: this implementation assumes the default digest for the given elliptic -/// curve as defined by [`DigestAlgorithm`]. +/// curve as defined by [`hazmat::DigestPrimitive`]. /// /// When working with alternative digests, you will need to use e.g. /// [`SignatureWithOid::new_with_digest`]. -#[cfg(feature = "digest")] +#[cfg(all(feature = "digest", feature = "hazmat"))] impl TryFrom<&[u8]> for SignatureWithOid where - C: DigestAlgorithm, + C: hazmat::DigestPrimitive, C::Digest: AssociatedOid, SignatureSize: ArraySize, { @@ -782,29 +778,3 @@ const fn ecdsa_oid_for_digest(digest_oid: ObjectIdentifier) -> Option None, } } - -/// Bind a preferred [`Digest`] algorithm to an elliptic curve type. -/// -/// Generally there is a preferred variety of the SHA-2 family used with ECDSA -/// for a particular elliptic curve. -/// -/// This trait can be used to specify it, and with it receive a blanket impl of -/// [`PrehashSignature`], used by [`signature_derive`][1]) for the [`Signature`] -/// type for a particular elliptic curve. -/// -/// [1]: https://github.com/RustCrypto/traits/tree/master/signature/derive -#[cfg(feature = "digest")] -pub trait DigestAlgorithm: EcdsaCurve { - /// Preferred digest to use when computing ECDSA signatures for this - /// elliptic curve. This is typically a member of the SHA-2 family. - type Digest: BlockSizeUser + Digest + FixedOutput + FixedOutputReset; -} - -#[cfg(feature = "digest")] -impl PrehashSignature for Signature -where - C: DigestAlgorithm, - as Add>::Output: ArraySize, -{ - type Digest = C::Digest; -} diff --git a/ecdsa/src/recovery.rs b/ecdsa/src/recovery.rs index 480a7c9..05efa1f 100644 --- a/ecdsa/src/recovery.rs +++ b/ecdsa/src/recovery.rs @@ -7,7 +7,7 @@ use { crate::{SigningKey, hazmat::sign_prehashed_rfc6979}, elliptic_curve::{FieldBytes, subtle::CtOption}, signature::{ - DigestSigner, RandomizedDigestSigner, + DigestSigner, RandomizedDigestSigner, Signer, digest::FixedOutput, hazmat::{PrehashSigner, RandomizedPrehashSigner}, rand_core::TryCryptoRng, @@ -28,7 +28,10 @@ use { #[cfg(any(feature = "signing", feature = "verifying"))] use { - crate::{DigestAlgorithm, EcdsaCurve, Signature, SignatureSize, hazmat::bits2field}, + crate::{ + EcdsaCurve, Signature, SignatureSize, + hazmat::{DigestPrimitive, bits2field}, + }, elliptic_curve::{CurveArithmetic, Scalar, array::ArraySize, ops::Invert}, signature::digest::Digest, }; @@ -97,7 +100,7 @@ impl RecoveryId { signature: &Signature, ) -> Result where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, AffinePoint: DecompressPoint + FromEncodedPoint + ToEncodedPoint, FieldBytesSize: sec1::ModulusSize, SignatureSize: ArraySize, @@ -176,7 +179,7 @@ impl From for u8 { #[cfg(feature = "signing")] impl SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, Scalar: Invert>>, SignatureSize: ArraySize, { @@ -225,7 +228,7 @@ where #[cfg(feature = "signing")] impl DigestSigner, RecoveryId)> for SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, D: Digest, Scalar: Invert>>, SignatureSize: ArraySize, @@ -238,7 +241,7 @@ where #[cfg(feature = "signing")] impl RandomizedPrehashSigner<(Signature, RecoveryId)> for SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, Scalar: Invert>>, SignatureSize: ArraySize, { @@ -254,7 +257,7 @@ where #[cfg(feature = "signing")] impl RandomizedDigestSigner, RecoveryId)> for SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, D: Digest + FixedOutput, Scalar: Invert>>, SignatureSize: ArraySize, @@ -271,7 +274,7 @@ where #[cfg(feature = "signing")] impl PrehashSigner<(Signature, RecoveryId)> for SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, Scalar: Invert>>, SignatureSize: ArraySize, { @@ -280,6 +283,18 @@ where } } +#[cfg(feature = "signing")] +impl Signer<(Signature, RecoveryId)> for SigningKey +where + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, + Scalar: Invert>>, + SignatureSize: ArraySize, +{ + fn try_sign(&self, msg: &[u8]) -> Result<(Signature, RecoveryId)> { + self.sign_recoverable(msg) + } +} + #[cfg(feature = "verifying")] impl VerifyingKey where @@ -291,14 +306,14 @@ where /// Recover a [`VerifyingKey`] from the given message, signature, and /// [`RecoveryId`]. /// - /// The message is first hashed using this curve's [`DigestAlgorithm`]. + /// The message is first hashed using this curve's [`DigestPrimitive`]. pub fn recover_from_msg( msg: &[u8], signature: &Signature, recovery_id: RecoveryId, ) -> Result where - C: DigestAlgorithm, + C: DigestPrimitive, { Self::recover_from_digest(C::Digest::new_with_prefix(msg), signature, recovery_id) } diff --git a/ecdsa/src/signing.rs b/ecdsa/src/signing.rs index f75e605..287e433 100644 --- a/ecdsa/src/signing.rs +++ b/ecdsa/src/signing.rs @@ -1,9 +1,8 @@ //! ECDSA signing: producing signatures using a [`SigningKey`]. use crate::{ - DigestAlgorithm, EcdsaCurve, Error, Result, Signature, SignatureSize, SignatureWithOid, - ecdsa_oid_for_digest, - hazmat::{bits2field, sign_prehashed_rfc6979}, + EcdsaCurve, Error, Result, Signature, SignatureSize, SignatureWithOid, ecdsa_oid_for_digest, + hazmat::{DigestPrimitive, bits2field, sign_prehashed_rfc6979}, }; use core::fmt::{self, Debug}; use digest::{Digest, FixedOutput, const_oid::AssociatedOid}; @@ -16,7 +15,7 @@ use elliptic_curve::{ zeroize::{Zeroize, ZeroizeOnDrop}, }; use signature::{ - DigestSigner, RandomizedDigestSigner, Signer, + DigestSigner, RandomizedDigestSigner, RandomizedSigner, Signer, hazmat::{PrehashSigner, RandomizedPrehashSigner}, rand_core::{CryptoRng, TryCryptoRng}, }; @@ -140,7 +139,7 @@ where /// [RFC6979 § 3.2]: https://tools.ietf.org/html/rfc6979#section-3 impl DigestSigner> for SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, D: Digest + FixedOutput, Scalar: Invert>>, SignatureSize: ArraySize, @@ -156,7 +155,7 @@ where /// [RFC6979 § 3.2]: https://tools.ietf.org/html/rfc6979#section-3 impl PrehashSigner> for SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, Scalar: Invert>>, SignatureSize: ArraySize, { @@ -166,9 +165,24 @@ where } } +/// Sign message using a deterministic ephemeral scalar (`k`) +/// computed using the algorithm described in [RFC6979 § 3.2]. +/// +/// [RFC6979 § 3.2]: https://tools.ietf.org/html/rfc6979#section-3 +impl Signer> for SigningKey +where + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, + Scalar: Invert>>, + SignatureSize: ArraySize, +{ + fn try_sign(&self, msg: &[u8]) -> Result> { + self.try_sign_digest(C::Digest::new_with_prefix(msg)) + } +} + impl RandomizedDigestSigner> for SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, D: Digest + FixedOutput, Scalar: Invert>>, SignatureSize: ArraySize, @@ -184,7 +198,7 @@ where impl RandomizedPrehashSigner> for SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, Scalar: Invert>>, SignatureSize: ArraySize, { @@ -208,9 +222,25 @@ where } } +impl RandomizedSigner> for SigningKey +where + Self: RandomizedDigestSigner>, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, + Scalar: Invert>>, + SignatureSize: ArraySize, +{ + fn try_sign_with_rng( + &self, + rng: &mut R, + msg: &[u8], + ) -> Result> { + self.try_sign_digest_with_rng(rng, C::Digest::new_with_prefix(msg)) + } +} + impl DigestSigner> for SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, D: AssociatedOid + Digest + FixedOutput, Scalar: Invert>>, SignatureSize: ArraySize, @@ -224,7 +254,7 @@ where impl Signer> for SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, C::Digest: AssociatedOid, Scalar: Invert>>, SignatureSize: ArraySize, @@ -237,7 +267,7 @@ where #[cfg(feature = "der")] impl PrehashSigner> for SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, Scalar: Invert>>, SignatureSize: ArraySize, der::MaxSize: ArraySize, @@ -248,10 +278,44 @@ where } } +#[cfg(feature = "der")] +impl Signer> for SigningKey +where + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, + Scalar: Invert>>, + SignatureSize: ArraySize, + der::MaxSize: ArraySize, + as Add>::Output: Add + ArraySize, +{ + fn try_sign(&self, msg: &[u8]) -> Result> { + Signer::>::try_sign(self, msg).map(Into::into) + } +} + +#[cfg(feature = "der")] +impl RandomizedDigestSigner> for SigningKey +where + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, + D: Digest + FixedOutput, + Scalar: Invert>>, + SignatureSize: ArraySize, + der::MaxSize: ArraySize, + as Add>::Output: Add + ArraySize, +{ + fn try_sign_digest_with_rng( + &self, + rng: &mut R, + msg_digest: D, + ) -> Result> { + RandomizedDigestSigner::>::try_sign_digest_with_rng(self, rng, msg_digest) + .map(Into::into) + } +} + #[cfg(feature = "der")] impl RandomizedPrehashSigner> for SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, Scalar: Invert>>, SignatureSize: ArraySize, der::MaxSize: ArraySize, @@ -270,7 +334,7 @@ where #[cfg(feature = "der")] impl DigestSigner> for SigningKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, D: Digest + FixedOutput, Scalar: Invert>>, SignatureSize: ArraySize, @@ -282,26 +346,6 @@ where } } -#[cfg(feature = "der")] -impl RandomizedDigestSigner> for SigningKey -where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, - D: Digest + FixedOutput, - Scalar: Invert>>, - SignatureSize: ArraySize, - der::MaxSize: ArraySize, - as Add>::Output: Add + ArraySize, -{ - fn try_sign_digest_with_rng( - &self, - rng: &mut R, - msg_digest: D, - ) -> Result> { - RandomizedDigestSigner::>::try_sign_digest_with_rng(self, rng, msg_digest) - .map(Into::into) - } -} - // // Other trait impls // diff --git a/ecdsa/src/verifying.rs b/ecdsa/src/verifying.rs index 3f3fc0c..8ea4485 100644 --- a/ecdsa/src/verifying.rs +++ b/ecdsa/src/verifying.rs @@ -2,7 +2,7 @@ use crate::{ EcdsaCurve, Error, Result, Signature, SignatureSize, - hazmat::{self, bits2field}, + hazmat::{self, DigestPrimitive, bits2field}, }; use core::{cmp::Ordering, fmt::Debug}; use elliptic_curve::{ @@ -13,7 +13,7 @@ use elliptic_curve::{ sec1::{self, CompressedPoint, EncodedPoint, FromEncodedPoint, ToEncodedPoint}, }; use signature::{ - DigestVerifier, + DigestVerifier, Verifier, digest::{Digest, FixedOutput}, hazmat::PrehashVerifier, }; @@ -42,11 +42,9 @@ use serdect::serde::{Deserialize, Serialize, de, ser}; #[cfg(feature = "sha2")] use { crate::{ - DigestAlgorithm, ECDSA_SHA224_OID, ECDSA_SHA256_OID, ECDSA_SHA384_OID, ECDSA_SHA512_OID, - SignatureWithOid, + ECDSA_SHA224_OID, ECDSA_SHA256_OID, ECDSA_SHA384_OID, ECDSA_SHA512_OID, SignatureWithOid, }, sha2::{Sha224, Sha256, Sha384, Sha512}, - signature::Verifier, }; #[cfg(all(feature = "alloc", feature = "pkcs8"))] @@ -174,10 +172,20 @@ where } } +impl Verifier> for VerifyingKey +where + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, + SignatureSize: ArraySize, +{ + fn verify(&self, msg: &[u8], signature: &Signature) -> Result<()> { + self.verify_digest(C::Digest::new_with_prefix(msg), signature) + } +} + #[cfg(feature = "sha2")] impl Verifier> for VerifyingKey where - C: EcdsaCurve + CurveArithmetic + DigestAlgorithm, + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, SignatureSize: ArraySize, { fn verify(&self, msg: &[u8], sig: &SignatureWithOid) -> Result<()> { @@ -220,6 +228,20 @@ where } } +#[cfg(feature = "der")] +impl Verifier> for VerifyingKey +where + C: EcdsaCurve + CurveArithmetic + DigestPrimitive, + SignatureSize: ArraySize, + der::MaxSize: ArraySize, + as Add>::Output: Add + ArraySize, +{ + fn verify(&self, msg: &[u8], signature: &der::Signature) -> Result<()> { + let signature = Signature::::try_from(signature.clone())?; + Verifier::>::verify(self, msg, &signature) + } +} + // // Other trait impls //