Skip to content

Commit bcfebe2

Browse files
committed
ecdsa: move Array* bounds to EcdsaCurve
Eliminates repetitive `SignatureSize<C>: ArraySize` bounds and `Copy`-related bounds by moving them all to `EcdsaCurve` and bounding on `Curve::FieldBytesSize`. This even enables custom derive to work in places it didn't before.
1 parent c844e26 commit bcfebe2

5 files changed

Lines changed: 25 additions & 124 deletions

File tree

ecdsa/src/hazmat.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@
1212
//! FULL PRIVATE KEY RECOVERY!
1313
//! </div>
1414
15-
use crate::{EcdsaCurve, Error, RecoveryId, Result, Signature, SignatureSize};
15+
use crate::{EcdsaCurve, Error, RecoveryId, Result, Signature};
1616
use elliptic_curve::{
1717
CurveArithmetic, FieldBytes, NonZeroScalar, ProjectivePoint, Scalar,
18-
array::ArraySize,
1918
bigint::{BitOps, Encoding},
2019
ff::PrimeField,
2120
group::{Curve as _, Group},
@@ -58,7 +57,6 @@ pub fn sign_prehashed<C>(
5857
) -> Result<(Signature<C>, RecoveryId)>
5958
where
6059
C: EcdsaCurve + CurveArithmetic,
61-
SignatureSize<C>: ArraySize,
6260
{
6361
let z = bytes2scalar::<C>(z);
6462

@@ -109,7 +107,6 @@ pub fn sign_prehashed_rfc6979<C, D>(
109107
where
110108
C: EcdsaCurve + CurveArithmetic,
111109
D: Digest + BlockSizeUser,
112-
SignatureSize<C>: ArraySize,
113110
{
114111
let order = C::ORDER;
115112
let mut kgen = rfc6979::KGenerator::<D, C::Uint>::new(&d.to_repr(), z, ad, &order);
@@ -137,7 +134,6 @@ where
137134
pub fn verify_prehashed<C>(q: &ProjectivePoint<C>, z: &[u8], sig: &Signature<C>) -> Result<()>
138135
where
139136
C: EcdsaCurve + CurveArithmetic,
140-
SignatureSize<C>: ArraySize,
141137
{
142138
if C::NORMALIZE_S && sig.s().is_high().into() {
143139
return Err(Error::new());

ecdsa/src/lib.rs

Lines changed: 10 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ pub use crate::verifying::VerifyingKey;
8787

8888
use core::{fmt, ops::Add};
8989
use elliptic_curve::{
90-
FieldBytes, FieldBytesSize, ScalarValue,
90+
Curve, FieldBytes, FieldBytesSize, ScalarValue,
9191
array::{Array, ArraySize, typenum::Unsigned},
9292
};
9393

@@ -164,7 +164,9 @@ const SHA384_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.16.840.1.10
164164
const SHA512_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.3");
165165

166166
/// Marker trait for elliptic curves intended for use with ECDSA.
167-
pub trait EcdsaCurve: PrimeCurve {
167+
pub trait EcdsaCurve:
168+
Curve<FieldBytesSize: Add<Output: ArraySize<ArrayType<u8>: Copy>>> + PrimeCurve
169+
{
168170
/// Does this curve use low-S normalized signatures?
169171
///
170172
/// This is typically `false`. See [`Signature::normalize_s`] for more information.
@@ -203,7 +205,7 @@ pub type SignatureBytes<C> = Array<u8, SignatureSize<C>>;
203205
/// "human readable" text formats, and a binary encoding otherwise.
204206
///
205207
/// [IEEE P1363]: https://en.wikipedia.org/wiki/IEEE_P1363
206-
#[derive(Clone, Eq, PartialEq)]
208+
#[derive(Clone, Copy, Eq, PartialEq)]
207209
pub struct Signature<C: EcdsaCurve> {
208210
r: ScalarValue<C>,
209211
s: ScalarValue<C>,
@@ -212,7 +214,6 @@ pub struct Signature<C: EcdsaCurve> {
212214
impl<C> Signature<C>
213215
where
214216
C: EcdsaCurve,
215-
SignatureSize<C>: ArraySize,
216217
{
217218
/// Parse a signature from fixed-width bytes, i.e. 2 * the size of
218219
/// [`FieldBytes`] for a particular curve.
@@ -301,7 +302,6 @@ where
301302
impl<C> Signature<C>
302303
where
303304
C: EcdsaCurve + CurveArithmetic,
304-
SignatureSize<C>: ArraySize,
305305
{
306306
/// Get the `r` component of this signature
307307
pub fn r(&self) -> NonZeroScalar<C> {
@@ -318,30 +318,20 @@ where
318318
(self.r(), self.s())
319319
}
320320

321-
/// Normalize signature into "low S" form as described in
322-
/// [BIP 0062: Dealing with Malleability][1].
321+
/// Normalize signature into "low S" form described in [BIP 0062: Dealing with Malleability][1].
323322
///
324323
/// [1]: https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki
325324
pub fn normalize_s(&self) -> Self {
326-
let mut result = self.clone();
325+
let mut result = *self;
327326
let s_inv = ScalarValue::from(-self.s());
328327
result.s.conditional_assign(&s_inv, self.s.is_high());
329328
result
330329
}
331330
}
332331

333-
impl<C> Copy for Signature<C>
334-
where
335-
C: EcdsaCurve,
336-
SignatureSize<C>: ArraySize,
337-
<SignatureSize<C> as ArraySize>::ArrayType<u8>: Copy,
338-
{
339-
}
340-
341332
impl<C> From<Signature<C>> for SignatureBytes<C>
342333
where
343334
C: EcdsaCurve,
344-
SignatureSize<C>: ArraySize,
345335
{
346336
fn from(signature: Signature<C>) -> SignatureBytes<C> {
347337
signature.to_bytes()
@@ -351,15 +341,13 @@ where
351341
impl<C> SignatureEncoding for Signature<C>
352342
where
353343
C: EcdsaCurve,
354-
SignatureSize<C>: ArraySize,
355344
{
356345
type Repr = SignatureBytes<C>;
357346
}
358347

359348
impl<C> TryFrom<&[u8]> for Signature<C>
360349
where
361350
C: EcdsaCurve,
362-
SignatureSize<C>: ArraySize,
363351
{
364352
type Error = Error;
365353

@@ -371,7 +359,6 @@ where
371359
impl<C> fmt::Debug for Signature<C>
372360
where
373361
C: EcdsaCurve,
374-
SignatureSize<C>: ArraySize,
375362
{
376363
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
377364
write!(f, "ecdsa::Signature<{:?}>(", C::default())?;
@@ -387,7 +374,6 @@ where
387374
impl<C> fmt::Display for Signature<C>
388375
where
389376
C: EcdsaCurve,
390-
SignatureSize<C>: ArraySize,
391377
{
392378
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
393379
write!(f, "{self:X}")
@@ -397,7 +383,6 @@ where
397383
impl<C> core::hash::Hash for Signature<C>
398384
where
399385
C: EcdsaCurve,
400-
SignatureSize<C>: ArraySize,
401386
{
402387
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
403388
self.to_bytes().hash(state);
@@ -407,7 +392,6 @@ where
407392
impl<C> fmt::LowerHex for Signature<C>
408393
where
409394
C: EcdsaCurve,
410-
SignatureSize<C>: ArraySize,
411395
{
412396
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
413397
for byte in self.to_bytes() {
@@ -420,7 +404,6 @@ where
420404
impl<C> fmt::UpperHex for Signature<C>
421405
where
422406
C: EcdsaCurve,
423-
SignatureSize<C>: ArraySize,
424407
{
425408
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
426409
for byte in self.to_bytes() {
@@ -434,7 +417,6 @@ where
434417
impl<C> str::FromStr for Signature<C>
435418
where
436419
C: EcdsaCurve + CurveArithmetic,
437-
SignatureSize<C>: ArraySize,
438420
{
439421
type Err = Error;
440422

@@ -494,7 +476,6 @@ where
494476
impl<C> Serialize for Signature<C>
495477
where
496478
C: EcdsaCurve,
497-
SignatureSize<C>: ArraySize,
498479
{
499480
fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
500481
where
@@ -508,7 +489,6 @@ where
508489
impl<'de, C> Deserialize<'de> for Signature<C>
509490
where
510491
C: EcdsaCurve,
511-
SignatureSize<C>: ArraySize,
512492
{
513493
fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
514494
where
@@ -540,7 +520,7 @@ impl<C: EcdsaCurve> Zeroize for Signature<C> {
540520
///
541521
/// [RFC5758 § 3.2]: https://www.rfc-editor.org/rfc/rfc5758#section-3.2
542522
#[cfg(feature = "digest")]
543-
#[derive(Clone, Eq, PartialEq)]
523+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
544524
pub struct SignatureWithOid<C: EcdsaCurve> {
545525
/// Inner signature type.
546526
signature: Signature<C>,
@@ -596,7 +576,6 @@ where
596576
pub fn from_bytes_with_digest<D>(bytes: &SignatureBytes<C>) -> Result<Self>
597577
where
598578
D: AssociatedOid + Digest,
599-
SignatureSize<C>: ArraySize,
600579
{
601580
Self::new_with_digest::<D>(Signature::<C>::from_bytes(bytes)?)
602581
}
@@ -605,7 +584,6 @@ where
605584
pub fn from_slice_with_digest<D>(slice: &[u8]) -> Result<Self>
606585
where
607586
D: AssociatedOid + Digest,
608-
SignatureSize<C>: ArraySize,
609587
{
610588
Self::new_with_digest::<D>(Signature::<C>::from_slice(slice)?)
611589
}
@@ -643,9 +621,7 @@ where
643621

644622
/// Serialize this signature as fixed-width bytes.
645623
pub fn to_bytes(&self) -> SignatureBytes<C>
646-
where
647-
SignatureSize<C>: ArraySize,
648-
{
624+
where {
649625
self.signature.to_bytes()
650626
}
651627

@@ -660,7 +636,7 @@ where
660636
der::MaxSize<C>: ArraySize,
661637
<FieldBytesSize<C> as Add>::Output: Add<der::MaxOverhead> + ArraySize,
662638
{
663-
self.signature.clone().into()
639+
self.signature.into()
664640
}
665641
}
666642

@@ -675,20 +651,10 @@ pub trait DigestAlgorithm: EcdsaCurve {
675651
type Digest: BlockSizeUser + Digest + FixedOutput;
676652
}
677653

678-
#[cfg(feature = "digest")]
679-
impl<C> Copy for SignatureWithOid<C>
680-
where
681-
C: EcdsaCurve,
682-
SignatureSize<C>: ArraySize,
683-
<SignatureSize<C> as ArraySize>::ArrayType<u8>: Copy,
684-
{
685-
}
686-
687654
#[cfg(feature = "digest")]
688655
impl<C> core::hash::Hash for SignatureWithOid<C>
689656
where
690657
C: EcdsaCurve,
691-
SignatureSize<C>: ArraySize,
692658
{
693659
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
694660
self.signature.hash(state);
@@ -710,7 +676,6 @@ where
710676
impl<C> From<SignatureWithOid<C>> for SignatureBytes<C>
711677
where
712678
C: EcdsaCurve,
713-
SignatureSize<C>: ArraySize,
714679
{
715680
fn from(signature: SignatureWithOid<C>) -> SignatureBytes<C> {
716681
signature.to_bytes()
@@ -751,7 +716,6 @@ impl<C> SignatureEncoding for SignatureWithOid<C>
751716
where
752717
C: DigestAlgorithm,
753718
C::Digest: AssociatedOid,
754-
SignatureSize<C>: ArraySize,
755719
{
756720
type Repr = SignatureBytes<C>;
757721
}
@@ -766,7 +730,6 @@ impl<C> TryFrom<&[u8]> for SignatureWithOid<C>
766730
where
767731
C: DigestAlgorithm,
768732
C::Digest: AssociatedOid,
769-
SignatureSize<C>: ArraySize,
770733
{
771734
type Error = Error;
772735

ecdsa/src/recovery.rs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@ use crate::{Error, Result};
55
#[cfg(feature = "algorithm")]
66
use {
77
crate::{
8-
DigestAlgorithm, EcdsaCurve, Signature, SignatureSize, SigningKey, VerifyingKey,
8+
DigestAlgorithm, EcdsaCurve, Signature, SigningKey, VerifyingKey,
99
hazmat::{bytes2scalar, sign_prehashed_rfc6979, verify_prehashed},
1010
},
1111
digest::{Digest, Update},
1212
elliptic_curve::{
1313
AffinePoint, CurveArithmetic, FieldBytes, FieldBytesSize, Group, PrimeField,
1414
ProjectivePoint, Scalar,
15-
array::ArraySize,
1615
bigint::CheckedAdd,
1716
field,
1817
ops::Invert,
@@ -95,7 +94,6 @@ impl RecoveryId {
9594
C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
9695
AffinePoint<C>: DecompressPoint<C> + FromSec1Point<C> + ToSec1Point<C>,
9796
FieldBytesSize<C>: sec1::ModulusSize,
98-
SignatureSize<C>: ArraySize,
9997
{
10098
Self::trial_recovery_from_digest(verifying_key, C::Digest::new_with_prefix(msg), signature)
10199
}
@@ -113,7 +111,6 @@ impl RecoveryId {
113111
D: Digest,
114112
AffinePoint<C>: DecompressPoint<C> + FromSec1Point<C> + ToSec1Point<C>,
115113
FieldBytesSize<C>: sec1::ModulusSize,
116-
SignatureSize<C>: ArraySize,
117114
{
118115
Self::trial_recovery_from_prehash(verifying_key, &digest.finalize(), signature)
119116
}
@@ -130,7 +127,6 @@ impl RecoveryId {
130127
C: EcdsaCurve + CurveArithmetic,
131128
AffinePoint<C>: DecompressPoint<C> + FromSec1Point<C> + ToSec1Point<C>,
132129
FieldBytesSize<C>: sec1::ModulusSize,
133-
SignatureSize<C>: ArraySize,
134130
{
135131
// Ensure signature verifies with the provided key
136132
verify_prehashed::<C>(
@@ -172,7 +168,6 @@ impl<C> SigningKey<C>
172168
where
173169
C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
174170
Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
175-
SignatureSize<C>: ArraySize,
176171
{
177172
/// Sign the given message prehash, using the given rng for the RFC6979 Section 3.6 "additional
178173
/// data", returning a signature and recovery ID.
@@ -220,7 +215,6 @@ where
220215
C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
221216
D: Digest + Update,
222217
Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
223-
SignatureSize<C>: ArraySize,
224218
{
225219
fn try_sign_digest<F: Fn(&mut D) -> Result<()>>(
226220
&self,
@@ -237,7 +231,6 @@ impl<C> RandomizedPrehashSigner<(Signature<C>, RecoveryId)> for SigningKey<C>
237231
where
238232
C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
239233
Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
240-
SignatureSize<C>: ArraySize,
241234
{
242235
fn sign_prehash_with_rng<R: TryCryptoRng + ?Sized>(
243236
&self,
@@ -254,7 +247,6 @@ where
254247
C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
255248
D: Digest + Update,
256249
Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
257-
SignatureSize<C>: ArraySize,
258250
{
259251
fn try_sign_digest_with_rng<R: TryCryptoRng + ?Sized, F: Fn(&mut D) -> Result<()>>(
260252
&self,
@@ -272,7 +264,6 @@ impl<C> PrehashSigner<(Signature<C>, RecoveryId)> for SigningKey<C>
272264
where
273265
C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
274266
Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
275-
SignatureSize<C>: ArraySize,
276267
{
277268
fn sign_prehash(&self, prehash: &[u8]) -> Result<(Signature<C>, RecoveryId)> {
278269
self.sign_prehash_recoverable(prehash)
@@ -284,7 +275,6 @@ impl<C> Signer<(Signature<C>, RecoveryId)> for SigningKey<C>
284275
where
285276
C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
286277
Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
287-
SignatureSize<C>: ArraySize,
288278
{
289279
fn try_sign(&self, msg: &[u8]) -> Result<(Signature<C>, RecoveryId)> {
290280
self.try_multipart_sign(&[msg])
@@ -296,7 +286,6 @@ impl<C> MultipartSigner<(Signature<C>, RecoveryId)> for SigningKey<C>
296286
where
297287
C: EcdsaCurve + CurveArithmetic + DigestAlgorithm,
298288
Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
299-
SignatureSize<C>: ArraySize,
300289
{
301290
fn try_multipart_sign(&self, msg: &[&[u8]]) -> Result<(Signature<C>, RecoveryId)> {
302291
let mut digest = C::Digest::new();
@@ -312,7 +301,6 @@ where
312301
C: EcdsaCurve + CurveArithmetic,
313302
AffinePoint<C>: DecompressPoint<C> + FromSec1Point<C> + ToSec1Point<C>,
314303
FieldBytesSize<C>: sec1::ModulusSize,
315-
SignatureSize<C>: ArraySize,
316304
{
317305
/// Recover a [`VerifyingKey`] from the given message, signature, and [`RecoveryId`].
318306
///

0 commit comments

Comments
 (0)