Skip to content

Commit 8006f06

Browse files
authored
Impl crypto_common::Generate trait (#1586)
Replaces various bespoke RNG APIs with the new `Generate` trait from `crypto_common`, which was added to `elliptic-curve` in RustCrypto/traits#2173. It's now a required bound for all affine/projective points and scalars, as well as the RNG API used by all generic types defined in the `elliptic-curve` crate itself. This API avoids having to directly import `getrandom::SysRng`, making it possible to call `T::generate()` instead so long as the `getrandom` feature of `elliptic-curve` is enabled.
1 parent 1056cb2 commit 8006f06

File tree

41 files changed

+721
-521
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+721
-521
lines changed

Cargo.lock

Lines changed: 10 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,7 @@ ed448-goldilocks = { path = "ed448-goldilocks" }
2626
hash2curve = { path = "hash2curve" }
2727
primefield = { path = "primefield" }
2828
primeorder = { path = "primeorder" }
29+
30+
crypto-common = { git = "https://github.com/RustCrypto/traits" }
31+
ecdsa = { git = "https://github.com/RustCrypto/signatures" }
32+
elliptic-curve = { git = "https://github.com/RustCrypto/traits" }

bignp256/src/ecdh.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@
1010
//!
1111
#![cfg_attr(feature = "getrandom", doc = "```")]
1212
#![cfg_attr(not(feature = "getrandom"), doc = "```ignore")]
13+
//! # fn main() -> Result<(), Box<dyn core::error::Error>> {
1314
//! // NOTE: requires 'getrandom' feature is enabled
1415
//!
15-
//! use bignp256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret};
16+
//! use bignp256::{
17+
//! EncodedPoint, PublicKey,
18+
//! ecdh::EphemeralSecret,
19+
//! elliptic_curve::Generate
20+
//! };
1621
//!
1722
//! // Alice
1823
//! let alice_secret = EphemeralSecret::generate();
@@ -23,22 +28,20 @@
2328
//! let bob_pk_bytes = EncodedPoint::from(bob_secret.public_key());
2429
//!
2530
//! // Alice decodes Bob's serialized public key and computes a shared secret from it
26-
//! let bob_public =
27-
//! PublicKey::from_encoded_point(bob_pk_bytes).expect("bob's public key is invalid!"); // In real usage, don't panic, handle this!
28-
//!
31+
//! let bob_public = PublicKey::from_encoded_point(bob_pk_bytes)?;
2932
//! let alice_shared = alice_secret.diffie_hellman(&bob_public.into());
3033
//!
3134
//! // Bob decodes Alice's serialized public key and computes the same shared secret
32-
//! let alice_public =
33-
//! PublicKey::from_encoded_point(alice_pk_bytes).expect("alice's public key is invalid!"); // In real usage, don't panic, handle this!
34-
//!
35+
//! let alice_public = PublicKey::from_encoded_point(alice_pk_bytes)?;
3536
//! let bob_shared = bob_secret.diffie_hellman(&alice_public.into());
3637
//!
3738
//! // Both participants arrive on the same shared secret
3839
//! assert_eq!(
3940
//! alice_shared.raw_secret_bytes(),
4041
//! bob_shared.raw_secret_bytes()
4142
//! );
43+
//! # Ok(())
44+
//! # }
4245
//! ```
4346
4447
pub use elliptic_curve::ecdh::diffie_hellman;

bignp256/src/ecdsa.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,25 @@
22
//!
33
//! ## Usage
44
//!
5-
//! NOTE: requires the `dsa` crate feature enabled, and `rand_core` dependency
6-
//! with `getrandom` feature enabled.
7-
#![cfg_attr(feature = "std", doc = "```")]
8-
#![cfg_attr(not(feature = "std"), doc = "```ignore")]
9-
//! # fn example() -> Result<(), Box<dyn std::error::Error>> {
10-
//! use getrandom::{SysRng, rand_core::TryRngCore};
5+
#![cfg_attr(all(feature = "ecdsa", feature = "getrandom"), doc = "```")]
6+
#![cfg_attr(not(all(feature = "ecdsa", feature = "getrandom")), doc = "```ignore")]
7+
//! # fn main() -> Result<(), Box<dyn core::error::Error>> {
8+
//! // NOTE: requires the `ecdsa` and `getrandom` crate features are enabled
119
//! use bignp256::{
12-
//! ecdsa::{Signature, SigningKey, signature::Signer},
13-
//! SecretKey
10+
//! ecdsa::{SigningKey, Signature, signature::Signer},
11+
//! elliptic_curve::{Generate, sec1::ToEncodedPoint},
12+
//! SecretKey,
1413
//! };
1514
//!
1615
//! // Signing
17-
//! let secret_key = SecretKey::try_from_rng(&mut SysRng).unwrap(); // serialize with `::to_bytes()`
18-
//! let signing_key = SigningKey::new(&secret_key)?;
16+
//! let signing_key = SigningKey::generate(); // Serialize with `::to_bytes()`
1917
//! let verifying_key_bytes = signing_key.verifying_key().to_bytes();
18+
//!
2019
//! let message = b"test message";
2120
//! let signature: Signature = signing_key.sign(message);
2221
//!
23-
//! // Verifying
24-
//! use bignp256::ecdsa::{VerifyingKey, signature::Verifier};
22+
//! // Verification
23+
//! use bignp256::{EncodedPoint, ecdsa::{VerifyingKey, signature::Verifier}};
2524
//!
2625
//! let verifying_key = VerifyingKey::from_bytes(&verifying_key_bytes)?;
2726
//! verifying_key.verify(message, &signature)?;

bignp256/src/ecdsa/signing.rs

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ use crate::{BignP256, FieldBytes, NonZeroScalar, ProjectivePoint, PublicKey, Sca
1919
use belt_hash::{BeltHash, Digest};
2020
use core::fmt::{self, Debug};
2121
use elliptic_curve::{
22-
Curve, Field, FieldBytesEncoding, Group, PrimeField,
22+
Curve, Field, FieldBytesEncoding, Generate, Group, PrimeField,
2323
array::{Array, sizes::U32, typenum::Unsigned},
2424
ops::Reduce,
2525
point::AffineCoordinates,
2626
subtle::{Choice, ConstantTimeEq},
2727
};
28+
use rand_core::TryCryptoRng;
2829
use signature::{Error, KeypairRef, MultipartSigner, Result, Signer, hazmat::PrehashSigner};
2930

3031
/// BignP256 secret key used for signing messages and producing signatures.
@@ -46,12 +47,6 @@ pub struct SigningKey {
4647
}
4748

4849
impl SigningKey {
49-
/// Create signing key from a signer's distinguishing identifier and
50-
/// secret key.
51-
pub fn new(secret_key: &SecretKey) -> Result<Self> {
52-
Self::from_nonzero_scalar(secret_key.to_nonzero_scalar())
53-
}
54-
5550
/// Parse signing key from big endian-encoded bytes.
5651
pub fn from_bytes(bytes: &FieldBytes) -> Result<Self> {
5752
Self::from_slice(bytes)
@@ -60,18 +55,19 @@ impl SigningKey {
6055
/// Parse signing key from big endian-encoded byte slice containing a secret
6156
/// scalar value.
6257
pub fn from_slice(slice: &[u8]) -> Result<Self> {
63-
let secret_scalar = NonZeroScalar::try_from(slice).map_err(|_| Error::new())?;
64-
Self::from_nonzero_scalar(secret_scalar)
58+
NonZeroScalar::try_from(slice)
59+
.map(Into::into)
60+
.map_err(|_| Error::new())
6561
}
6662

6763
/// Create a signing key from a non-zero scalar.
68-
pub fn from_nonzero_scalar(secret_scalar: NonZeroScalar) -> Result<Self> {
64+
pub fn from_nonzero_scalar(secret_scalar: NonZeroScalar) -> Self {
6965
let public_key = PublicKey::from_secret_scalar(&secret_scalar);
70-
let verifying_key = VerifyingKey::new(public_key)?;
71-
Ok(Self {
66+
67+
Self {
7268
secret_scalar,
73-
verifying_key,
74-
})
69+
verifying_key: public_key.into(),
70+
}
7571
}
7672

7773
/// Serialize as bytes.
@@ -96,6 +92,14 @@ impl SigningKey {
9692
}
9793
}
9894

95+
impl Generate for SigningKey {
96+
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(
97+
rng: &mut R,
98+
) -> core::result::Result<Self, R::Error> {
99+
NonZeroScalar::try_generate_from_rng(rng).map(Into::into)
100+
}
101+
}
102+
99103
//
100104
// `*Signer` trait impls
101105
//
@@ -194,6 +198,24 @@ impl PartialEq for SigningKey {
194198
}
195199
}
196200

201+
impl From<NonZeroScalar> for SigningKey {
202+
fn from(secret_scalar: NonZeroScalar) -> Self {
203+
Self::from_nonzero_scalar(secret_scalar)
204+
}
205+
}
206+
207+
impl From<SecretKey> for SigningKey {
208+
fn from(secret_key: SecretKey) -> Self {
209+
secret_key.to_nonzero_scalar().into()
210+
}
211+
}
212+
213+
impl From<SigningKey> for SecretKey {
214+
fn from(signing_key: SigningKey) -> Self {
215+
signing_key.secret_scalar.into()
216+
}
217+
}
218+
197219
impl KeypairRef for SigningKey {
198220
type VerifyingKey = VerifyingKey;
199221
}

bignp256/src/ecdsa/verifying.rs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,26 +54,28 @@ use elliptic_curve::sec1::ToEncodedPoint;
5454
///
5555
/// The serialization leverages the encoding used by the [`PublicKey`] type,
5656
/// which is a binary-oriented ASN.1 DER encoding.
57-
#[derive(Clone, Debug)]
57+
#[derive(Clone, Copy, Debug)]
5858
pub struct VerifyingKey {
5959
/// Signer's public key.
6060
public_key: PublicKey,
6161
}
6262

6363
impl VerifyingKey {
64-
/// Initialize [`VerifyingKey`] from a signer's distinguishing identifier
65-
/// and public key.
66-
pub fn new(public_key: PublicKey) -> Result<Self> {
67-
Ok(Self { public_key })
68-
}
69-
7064
/// Initialize [`VerifyingKey`] from an affine point.
7165
///
7266
/// Returns an [`Error`] if the given affine point is the additive identity
7367
/// (a.k.a. point at infinity).
7468
pub fn from_affine(affine: AffinePoint) -> Result<Self> {
75-
let public_key = PublicKey::from_affine(affine).map_err(|_| Error::new())?;
76-
Self::new(public_key)
69+
Ok(Self {
70+
public_key: PublicKey::from_affine(affine).map_err(|_| Error::new())?,
71+
})
72+
}
73+
74+
/// Parse a [`VerifyingKey`] from a byte slice.
75+
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
76+
Ok(Self {
77+
public_key: PublicKey::from_bytes(bytes).map_err(|_| Error::new())?,
78+
})
7779
}
7880

7981
/// Borrow the inner [`AffinePoint`] for this public key.
@@ -90,12 +92,6 @@ impl VerifyingKey {
9092
hasher.finalize_fixed()
9193
}
9294

93-
/// Parse a [`VerifyingKey`] from a byte slice.
94-
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
95-
let public_key = PublicKey::from_bytes(bytes).map_err(|_| Error::new())?;
96-
Self::new(public_key)
97-
}
98-
9995
/// Serialize the [`VerifyingKey`] as a byte array.
10096
#[cfg(feature = "alloc")]
10197
pub fn to_bytes(&self) -> Box<[u8]> {
@@ -185,6 +181,18 @@ impl AsRef<AffinePoint> for VerifyingKey {
185181
}
186182
}
187183

184+
impl From<PublicKey> for VerifyingKey {
185+
fn from(public_key: PublicKey) -> VerifyingKey {
186+
VerifyingKey { public_key }
187+
}
188+
}
189+
190+
impl From<&PublicKey> for VerifyingKey {
191+
fn from(public_key: &PublicKey) -> VerifyingKey {
192+
VerifyingKey::from(*public_key)
193+
}
194+
}
195+
188196
impl From<VerifyingKey> for PublicKey {
189197
fn from(verifying_key: VerifyingKey) -> PublicKey {
190198
verifying_key.public_key
@@ -193,7 +201,7 @@ impl From<VerifyingKey> for PublicKey {
193201

194202
impl From<&VerifyingKey> for PublicKey {
195203
fn from(verifying_key: &VerifyingKey) -> PublicKey {
196-
verifying_key.public_key
204+
PublicKey::from(*verifying_key)
197205
}
198206
}
199207

bignp256/src/secret_key.rs

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use core::str::FromStr;
55
use der::{SecretDocument, asn1::OctetStringRef};
66

77
use crate::{ALGORITHM_OID, PublicKey, ScalarValue};
8-
use elliptic_curve::{Error, array::typenum::Unsigned, zeroize::Zeroizing};
8+
use elliptic_curve::{Error, Generate, array::typenum::Unsigned, zeroize::Zeroizing};
99
use pkcs8::{
1010
AssociatedOid, DecodePrivateKey, EncodePrivateKey, ObjectIdentifier,
1111
spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier},
@@ -24,28 +24,6 @@ pub struct SecretKey {
2424
impl SecretKey {
2525
const MIN_SIZE: usize = 24;
2626

27-
/// Generate a random [`SecretKey`].
28-
///
29-
/// # Panics
30-
///
31-
/// If the system's cryptographically secure RNG has an internal error.
32-
#[cfg(feature = "getrandom")]
33-
pub fn generate() -> Self {
34-
Self {
35-
inner: NonZeroScalar::generate().into(),
36-
}
37-
}
38-
39-
/// Generate a random [`SecretKey`].
40-
#[cfg(feature = "arithmetic")]
41-
pub fn try_from_rng<R: TryCryptoRng + ?Sized>(
42-
rng: &mut R,
43-
) -> core::result::Result<Self, R::Error> {
44-
Ok(Self {
45-
inner: NonZeroScalar::try_from_rng(rng)?.into(),
46-
})
47-
}
48-
4927
/// Borrow the inner secret [`elliptic_curve::ScalarValue`] value.
5028
///
5129
/// # ⚠️ Warning
@@ -117,6 +95,14 @@ impl SecretKey {
11795
}
11896
}
11997

98+
impl AssociatedAlgorithmIdentifier for SecretKey {
99+
type Params = ObjectIdentifier;
100+
const ALGORITHM_IDENTIFIER: AlgorithmIdentifier<Self::Params> = AlgorithmIdentifier {
101+
oid: ALGORITHM_OID,
102+
parameters: Some(BignP256::OID),
103+
};
104+
}
105+
120106
impl From<SecretKey> for NonZeroScalar {
121107
fn from(secret_key: SecretKey) -> NonZeroScalar {
122108
secret_key.to_nonzero_scalar()
@@ -139,12 +125,14 @@ impl From<&NonZeroScalar> for SecretKey {
139125
}
140126
}
141127

142-
impl AssociatedAlgorithmIdentifier for SecretKey {
143-
type Params = ObjectIdentifier;
144-
const ALGORITHM_IDENTIFIER: AlgorithmIdentifier<Self::Params> = AlgorithmIdentifier {
145-
oid: ALGORITHM_OID,
146-
parameters: Some(BignP256::OID),
147-
};
128+
impl Generate for SecretKey {
129+
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(
130+
rng: &mut R,
131+
) -> core::result::Result<Self, R::Error> {
132+
Ok(Self {
133+
inner: ScalarValue::try_generate_from_rng(rng)?,
134+
})
135+
}
148136
}
149137

150138
impl TryFrom<pkcs8::PrivateKeyInfoRef<'_>> for SecretKey {

0 commit comments

Comments
 (0)