Skip to content

Commit 582eaf1

Browse files
committed
ecdsa: enable and fix workspace-level lints
Completely fixing the missing errors doc is left as a todo
1 parent 055e9a4 commit 582eaf1

7 files changed

Lines changed: 69 additions & 82 deletions

File tree

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ecdsa/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ spki = { version = "0.8", optional = true, default-features = false }
3131

3232
[dev-dependencies]
3333
elliptic-curve = { version = "0.14", default-features = false, features = ["dev"] }
34-
hex-literal = "1"
3534
sha2 = { version = "0.11", default-features = false }
3635

3736
[features]
@@ -48,6 +47,8 @@ pkcs8 = ["der", "digest", "elliptic-curve/pkcs8"]
4847
pem = ["elliptic-curve/pem", "pkcs8"]
4948
serde = ["dep:serdect", "elliptic-curve/serde", "pkcs8"]
5049

50+
[lints]
51+
workspace = true
52+
5153
[package.metadata.docs.rs]
5254
all-features = true
53-
rustdoc-args = ["--cfg", "docsrs"]

ecdsa/src/der.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ impl<'a> DecodeValue<'a> for SignatureRef<'a> {
394394
impl<'a> Sequence<'a> for SignatureRef<'a> {}
395395

396396
/// Locate the range within a slice at which a particular subslice is located
397+
#[allow(clippy::as_conversions)]
397398
fn find_scalar_range(outer: &[u8], inner: &[u8]) -> Result<Range<usize>> {
398399
let outer_start = outer.as_ptr() as usize;
399400
let inner_start = inner.as_ptr() as usize;

ecdsa/src/dev.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ impl EcdsaCurve for MockCurve {
282282
}
283283

284284
/// ECDSA test vector
285+
#[derive(Clone, Copy, Debug)]
285286
pub struct TestVector {
286287
/// Private scalar
287288
pub d: &'static [u8],
@@ -306,6 +307,7 @@ pub struct TestVector {
306307
}
307308

308309
#[cfg(test)]
310+
#[allow(clippy::integer_division_remainder_used, reason = "tests")]
309311
mod tests {
310312
use super::*;
311313

ecdsa/src/hazmat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ where
161161
pub(crate) fn bytes2scalar<C: EcdsaCurve + CurveArithmetic>(mut bytes: &[u8]) -> Scalar<C> {
162162
// Compute number of bytes in `n` (curve order)
163163
let n_bits = C::ORDER.bits();
164-
let n_bytes = n_bits.div_ceil(8) as usize;
164+
let n_bytes = usize::try_from(n_bits.div_ceil(8)).expect("overflow");
165165
if bytes.len() > n_bytes {
166166
bytes = &bytes[..n_bytes];
167167
}

ecdsa/src/lib.rs

Lines changed: 32 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,26 @@
55
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
66
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
77
)]
8-
#![forbid(unsafe_code)]
9-
#![warn(
10-
clippy::cast_lossless,
11-
clippy::cast_possible_truncation,
12-
clippy::cast_possible_wrap,
13-
clippy::cast_precision_loss,
14-
clippy::cast_sign_loss,
15-
clippy::checked_conversions,
16-
clippy::implicit_saturating_sub,
17-
clippy::panic,
18-
clippy::panic_in_result_fn,
19-
clippy::unwrap_used,
20-
missing_docs,
21-
rust_2018_idioms,
22-
unused_lifetimes,
23-
unused_qualifications,
24-
unreachable_pub
25-
)]
8+
#![allow(clippy::missing_errors_doc, reason = "TODO")]
269

2710
//! ## `serde` support
2811
//!
29-
//! When the `serde` feature of this crate is enabled, `Serialize` and
30-
//! `Deserialize` impls are provided for the [`Signature`] and [`VerifyingKey`]
31-
//! types.
12+
//! When the `serde` feature of this crate is enabled, `Serialize` and `Deserialize` impls are
13+
//! provided for the [`Signature`] and [`VerifyingKey`] types.
3214
//!
3315
//! Please see type-specific documentation for more information.
3416
//!
3517
//! ## Interop
3618
//!
37-
//! Any crates which provide an implementation of ECDSA for a particular
38-
//! elliptic curve can leverage the types from this crate, along with the
39-
//! [`k256`], [`p256`], and/or [`p384`] crates to expose ECDSA functionality in
40-
//! a generic, interoperable way by leveraging the [`Signature`] type with in
41-
//! conjunction with the [`signature::Signer`] and [`signature::Verifier`]
42-
//! traits.
19+
//! Any crates which provide an implementation of ECDSA for a particular elliptic curve can leverage
20+
//! the types from this crate, along with the [`k256`], [`p256`], and/or [`p384`] crates to expose
21+
//! ECDSA functionality in a generic, interoperable way by leveraging the [`Signature`] type with in
22+
//! conjunction with the [`signature::Signer`] and [`signature::Verifier`] traits.
4323
//!
44-
//! For example, the [`ring-compat`] crate implements the [`signature::Signer`]
45-
//! and [`signature::Verifier`] traits in conjunction with the
46-
//! [`p256::ecdsa::Signature`] and [`p384::ecdsa::Signature`] types to
47-
//! wrap the ECDSA implementations from [*ring*] in a generic, interoperable
48-
//! API.
24+
//! For example, the [`ring-compat`] crate implements the [`signature::Signer`] and
25+
//! [`signature::Verifier`] traits in conjunction with the [`p256::ecdsa::Signature`] and
26+
//! [`p384::ecdsa::Signature`] types to wrap the ECDSA implementations from [*ring*] in a generic,
27+
//! interoperable API.
4928
//!
5029
//! [`k256`]: https://docs.rs/k256
5130
//! [`p256`]: https://docs.rs/p256
@@ -188,21 +167,19 @@ pub type SignatureBytes<C> = Array<u8, SignatureSize<C>>;
188167
///
189168
/// Both `r` and `s` MUST be non-zero.
190169
///
191-
/// For example, in a curve with a 256-bit modulus like NIST P-256 or
192-
/// secp256k1, `r` and `s` will both be 32-bytes and serialized as big endian,
193-
/// resulting in a signature with a total of 64-bytes.
170+
/// For example, in a curve with a 256-bit modulus like NIST P-256 or secp256k1, `r` and `s` are
171+
/// both 32-bytes and serialized as big endian, resulting in a signature with a total of 64-bytes.
194172
///
195-
/// ASN.1 DER-encoded signatures also supported via the
196-
/// [`Signature::from_der`] and [`Signature::to_der`] methods.
173+
/// ASN.1 DER-encoded signatures also supported via the [`Signature::from_der`] and
174+
/// [`Signature::to_der`] methods.
197175
///
198176
/// # `serde` support
199177
///
200-
/// When the `serde` feature of this crate is enabled, it provides support for
201-
/// serializing and deserializing ECDSA signatures using the `Serialize` and
202-
/// `Deserialize` traits.
178+
/// When the `serde` feature of this crate is enabled, it provides support for serializing and
179+
/// deserializing ECDSA signatures using the `Serialize` and `Deserialize` traits.
203180
///
204-
/// The serialization uses a hexadecimal encoding when used with
205-
/// "human readable" text formats, and a binary encoding otherwise.
181+
/// The serialization uses a hexadecimal encoding when used with "human readable" text formats, and
182+
/// a binary encoding otherwise.
206183
///
207184
/// [IEEE P1363]: https://en.wikipedia.org/wiki/IEEE_P1363
208185
#[derive(Clone, Copy, Eq, PartialEq)]
@@ -218,11 +195,9 @@ where
218195
/// Parse a signature from fixed-width bytes, i.e. 2 * the size of
219196
/// [`FieldBytes`] for a particular curve.
220197
///
221-
/// # Returns
222-
/// - `Ok(signature)` if the `r` and `s` components are both in the valid
223-
/// range `1..n` when serialized as concatenated big endian integers.
224-
/// - `Err(err)` if the `r` and/or `s` component of the signature is
225-
/// out-of-range when interpreted as a big endian integer.
198+
/// # Errors
199+
/// If the `r` and/or `s` component of the signature is out-of-range when interpreted as a big
200+
/// endian integer.
226201
pub fn from_bytes(bytes: &SignatureBytes<C>) -> Result<Self> {
227202
let chunks = FieldBytes::<C>::slice_as_chunks(bytes).0;
228203
let r = chunks[0];
@@ -250,11 +225,8 @@ where
250225
/// Create a [`Signature`] from the serialized `r` and `s` scalar values
251226
/// which comprise the signature.
252227
///
253-
/// # Returns
254-
/// - `Ok(signature)` if the `r` and `s` components are both in the valid
255-
/// range `1..n` when serialized as concatenated big endian integers.
256-
/// - `Err(err)` if the `r` and/or `s` component of the signature is
257-
/// out-of-range when interpreted as a big endian integer.
228+
/// # Errors
229+
/// If the `r` and/or `s` component of the signature is out-of-range when interpreted as a big endian integer.
258230
pub fn from_scalars(r: impl Into<FieldBytes<C>>, s: impl Into<FieldBytes<C>>) -> Result<Self> {
259231
let r = ScalarValue::from_slice(&r.into()).map_err(|_| Error::new())?;
260232
let s = ScalarValue::from_slice(&s.into()).map_err(|_| Error::new())?;
@@ -282,6 +254,7 @@ where
282254

283255
/// Serialize this signature as ASN.1 DER.
284256
#[cfg(feature = "der")]
257+
#[allow(clippy::missing_panics_doc, reason = "should not panic in practice")]
285258
pub fn to_der(&self) -> der::Signature<C>
286259
where
287260
der::MaxSize<C>: ArraySize,
@@ -321,6 +294,7 @@ where
321294
/// Normalize signature into "low S" form described in [BIP 0062: Dealing with Malleability][1].
322295
///
323296
/// [1]: https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki
297+
#[must_use]
324298
pub fn normalize_s(&self) -> Self {
325299
let mut result = *self;
326300
let s_inv = ScalarValue::from(-self.s());
@@ -439,11 +413,10 @@ where
439413
}
440414
}
441415

442-
/// ECDSA [`ObjectIdentifier`] which identifies the digest used by default
443-
/// with the `Signer` and `Verifier` traits.
416+
/// ECDSA [`ObjectIdentifier`] which identifies the digest used by default with the `Signer` and
417+
/// `Verifier` traits.
444418
///
445-
/// To support non-default digest algorithms, use the [`SignatureWithOid`]
446-
/// type instead.
419+
/// To support non-default digest algorithms, use the [`SignatureWithOid`] type instead.
447420
#[cfg(feature = "digest")]
448421
impl<C> AssociatedOid for Signature<C>
449422
where
@@ -507,9 +480,8 @@ impl<C: EcdsaCurve> Zeroize for Signature<C> {
507480
}
508481
}
509482

510-
/// An extended [`Signature`] type which is parameterized by an
511-
/// `ObjectIdentifier` which identifies the ECDSA variant used by a
512-
/// particular signature.
483+
/// An extended [`Signature`] type which is parameterized by an `ObjectIdentifier` which identifies
484+
/// the ECDSA variant used by a particular signature.
513485
///
514486
/// Valid `ObjectIdentifiers` are defined in [RFC5758 § 3.2]:
515487
///
@@ -540,8 +512,7 @@ where
540512
{
541513
/// Create a new signature with an explicitly provided OID.
542514
///
543-
/// OID must begin with `1.2.840.10045.4`, the [RFC5758] OID prefix for
544-
/// ECDSA variants.
515+
/// OID must begin with `1.2.840.10045.4`, the [RFC5758] OID prefix for ECDSA variants.
545516
///
546517
/// [RFC5758]: https://www.rfc-editor.org/rfc/rfc5758#section-3.2
547518
pub fn new(signature: Signature<C>, oid: ObjectIdentifier) -> Result<Self> {

ecdsa/src/recovery.rs

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,15 @@ use {
2929

3030
/// Recovery IDs, a.k.a. "recid".
3131
///
32-
/// This is an integer value `0`, `1`, `2`, or `3` included along with a
33-
/// signature which is used during the recovery process to select the correct
34-
/// public key from the signature.
32+
/// This is an integer value `0`, `1`, `2`, or `3` included along with a signature which is used
33+
/// during the recovery process to select the correct public key from the signature.
3534
///
3635
/// It consists of two bits of information:
3736
///
38-
/// - low bit (0/1): was the y-coordinate of the affine point resulting from
39-
/// the fixed-base multiplication 𝑘×𝑮 odd? This part of the algorithm
40-
/// functions similar to point decompression.
41-
/// - hi bit (2/3): did the affine x-coordinate of 𝑘×𝑮 overflow the order of
42-
/// the scalar field, requiring a reduction when computing `r`?
37+
/// 1. low bit (0/1): was the y-coordinate of the affine point resulting from the fixed-base
38+
/// multiplication 𝑘×𝑮 odd? This part of the algorithm functions similar to point decompression.
39+
/// 2. hi bit (2/3): did the affine x-coordinate of 𝑘×𝑮 overflow the order of the scalar field `n`,
40+
/// requiring a reduction when computing `r`?
4341
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
4442
pub struct RecoveryId(pub(crate) u8);
4543

@@ -51,21 +49,26 @@ impl RecoveryId {
5149
///
5250
/// - `is_y_odd`: is the affine y-coordinate of 𝑘×𝑮 odd?
5351
/// - `is_x_reduced`: did the affine x-coordinate of 𝑘×𝑮 overflow the curve order?
52+
#[must_use]
53+
#[allow(clippy::as_conversions, reason = "const fn")]
5454
pub const fn new(is_y_odd: bool, is_x_reduced: bool) -> Self {
5555
Self(((is_x_reduced as u8) << 1) | (is_y_odd as u8))
5656
}
5757

5858
/// Did the affine x-coordinate of 𝑘×𝑮 overflow the curve order?
59+
#[must_use]
5960
pub const fn is_x_reduced(self) -> bool {
6061
(self.0 & 0b10) != 0
6162
}
6263

6364
/// Is the affine y-coordinate of 𝑘×𝑮 odd?
65+
#[must_use]
6466
pub const fn is_y_odd(self) -> bool {
6567
(self.0 & 1) != 0
6668
}
6769

6870
/// Convert a `u8` into a [`RecoveryId`].
71+
#[must_use]
6972
pub const fn from_byte(byte: u8) -> Option<Self> {
7073
if byte <= Self::MAX {
7174
Some(Self(byte))
@@ -75,16 +78,20 @@ impl RecoveryId {
7578
}
7679

7780
/// Convert this [`RecoveryId`] into a `u8`.
81+
#[must_use]
7882
pub const fn to_byte(self) -> u8 {
7983
self.0
8084
}
8185
}
8286

8387
#[cfg(feature = "algorithm")]
8488
impl RecoveryId {
85-
/// Given a public key, message, and signature, use trial recovery
86-
/// to determine if a suitable recovery ID exists, or return an error
87-
/// otherwise.
89+
/// Given a public key, message, and signature, use trial recovery to determine if a suitable
90+
/// recovery ID exists.
91+
///
92+
/// # Errors
93+
/// Returns an error if a suitable solution could not be found and/or the signature does not
94+
/// verify.
8895
pub fn trial_recovery_from_msg<C>(
8996
verifying_key: &VerifyingKey<C>,
9097
msg: &[u8],
@@ -98,9 +105,12 @@ impl RecoveryId {
98105
Self::trial_recovery_from_digest(verifying_key, C::Digest::new_with_prefix(msg), signature)
99106
}
100107

101-
/// Given a public key, message digest, and signature, use trial recovery
102-
/// to determine if a suitable recovery ID exists, or return an error
103-
/// otherwise.
108+
/// Given a public key, message digest, and signature, use trial recovery to determine if a
109+
/// suitable recovery ID exists.
110+
///
111+
/// # Errors
112+
/// Returns an error if a suitable solution could not be found and/or the signature does not
113+
/// verify.
104114
pub fn trial_recovery_from_digest<C, D>(
105115
verifying_key: &VerifyingKey<C>,
106116
digest: D,
@@ -115,9 +125,12 @@ impl RecoveryId {
115125
Self::trial_recovery_from_prehash(verifying_key, &digest.finalize(), signature)
116126
}
117127

118-
/// Given a public key, message digest, and signature, use trial recovery
119-
/// to determine if a suitable recovery ID exists, or return an error
120-
/// otherwise.
128+
/// Given a public key, message digest, and signature, use trial recovery to determine if a
129+
/// suitable recovery ID exists.
130+
///
131+
/// # Errors
132+
/// Returns an error if a suitable solution could not be found and/or the signature does not
133+
/// verify.
121134
pub fn trial_recovery_from_prehash<C>(
122135
verifying_key: &VerifyingKey<C>,
123136
prehash: &[u8],

0 commit comments

Comments
 (0)