dsa: impl Generate for Components and SigningKey (#1372)

This renames the old `SigningKey::generate` to
`try_generate_from_rng_with_components`, having the new one generate
random `Components` with a 3072-bit modulus size, which is now the
`Default` for `KeySize`.
This commit is contained in:
Tony Arcieri
2026-06-06 11:27:17 -06:00
committed by GitHub
parent 43d9831ccf
commit 1b47ec5298
16 changed files with 69 additions and 40 deletions
Generated
+1
View File
@@ -439,6 +439,7 @@ version = "0.7.0-rc.15"
dependencies = [
"chacha20",
"crypto-bigint",
"crypto-common",
"crypto-primes",
"der",
"digest",
+2
View File
@@ -19,6 +19,7 @@ rust-version = "1.85"
der = { version = "0.8", features = ["alloc"] }
digest = "0.11"
crypto-bigint = { version = "0.7", default-features = false, features = ["alloc", "zeroize"] }
crypto-common = { version = "0.2", default-features = false, features = ["rand_core"] }
crypto-primes = { version = "0.7", default-features = false }
rfc6979 = { version = "0.5" }
sha2 = { version = "0.11", default-features = false }
@@ -41,6 +42,7 @@ sha1 = "0.11"
[features]
default = ["pkcs8"]
getrandom = ["crypto-common/getrandom"]
hazmat = []
[package.metadata.docs.rs]
+2 -1
View File
@@ -9,7 +9,8 @@ fn main() {
let mut rng = rand_core::UnwrapErr(SysRng);
let components =
Components::try_generate_from_rng_with_key_size(&mut rng, KeySize::DSA_2048_256).unwrap();
let signing_key = SigningKey::generate(&mut rng, components);
let signing_key =
SigningKey::try_generate_from_rng_with_components(&mut rng, components).unwrap();
let verifying_key = signing_key.verifying_key();
let signing_key_bytes = signing_key.to_pkcs8_pem(LineEnding::LF).unwrap();
+2 -1
View File
@@ -7,6 +7,7 @@ fn main() {
let mut rng = UnwrapErr(SysRng);
let components =
Components::try_generate_from_rng_with_key_size(&mut rng, KeySize::DSA_2048_256).unwrap();
let signing_key = SigningKey::generate(&mut rng, components);
let signing_key =
SigningKey::try_generate_from_rng_with_components(&mut rng, components).unwrap();
let _verifying_key = signing_key.verifying_key();
}
+2 -1
View File
@@ -12,7 +12,8 @@ fn main() {
.unwrap();
let mut rng = UnwrapErr(SysRng);
let signing_key = SigningKey::generate(&mut rng, components);
let signing_key =
SigningKey::try_generate_from_rng_with_components(&mut rng, components).unwrap();
let verifying_key = signing_key.verifying_key();
let signature = signing_key
+8 -1
View File
@@ -2,8 +2,9 @@
//! Module containing the definition of the common components container
//!
use crate::{generate, size::KeySize, two};
use crate::{generate, key_size::KeySize, two};
use crypto_bigint::{BoxedUint, NonZero, Odd};
use crypto_common::Generate;
use der::{
self, DecodeValue, Encode, EncodeValue, Header, Length, Reader, Sequence, Tag, Writer,
asn1::UintRef,
@@ -115,6 +116,12 @@ impl Components {
}
}
impl Generate for Components {
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
Self::try_generate_from_rng_with_key_size(rng, KeySize::default())
}
}
impl<'a> DecodeValue<'a> for Components {
type Error = der::Error;
+1 -1
View File
@@ -12,7 +12,7 @@ pub(crate) use self::components::common as common_components;
pub(crate) use self::secret_number::{secret_number, secret_number_rfc6979};
#[cfg(feature = "hazmat")]
pub(crate) use self::keypair::keypair;
pub(crate) use self::keypair::signing_keypair;
#[cfg(all(feature = "hazmat", feature = "pkcs8"))]
pub(crate) use self::components::public as public_component;
+1 -1
View File
@@ -4,7 +4,7 @@
use crate::{
generate::{calculate_bounds, generate_prime},
size::KeySize,
key_size::KeySize,
two,
};
use crypto_bigint::{
+17 -14
View File
@@ -5,41 +5,44 @@
use crate::{Components, VerifyingKey, generate::components, signing_key::SigningKey};
use crypto_bigint::{BoxedUint, NonZero, RandomMod};
use signature::rand_core::CryptoRng;
use signature::rand_core::TryCryptoRng;
/// Generate a new keypair
/// Generate a new signing keypair.
#[inline]
pub(crate) fn keypair<R: CryptoRng + ?Sized>(rng: &mut R, components: Components) -> SigningKey {
pub(crate) fn signing_keypair<R: TryCryptoRng + ?Sized>(
rng: &mut R,
components: Components,
) -> Result<SigningKey, R::Error> {
#[inline]
fn find_non_zero_x<R: CryptoRng + ?Sized>(
fn find_non_zero_x<R: TryCryptoRng + ?Sized>(
rng: &mut R,
components: &Components,
) -> NonZero<BoxedUint> {
) -> Result<NonZero<BoxedUint>, R::Error> {
loop {
let x = BoxedUint::random_mod_vartime(rng, components.q());
let x = BoxedUint::try_random_mod_vartime(rng, components.q())?;
if let Some(x) = NonZero::new(x).into() {
return x;
return Ok(x);
}
}
}
#[inline]
fn find_components<R: CryptoRng + ?Sized>(
fn find_components<R: TryCryptoRng + ?Sized>(
rng: &mut R,
components: &Components,
) -> (NonZero<BoxedUint>, NonZero<BoxedUint>) {
) -> Result<(NonZero<BoxedUint>, NonZero<BoxedUint>), R::Error> {
loop {
let x = find_non_zero_x(rng, components);
let x = find_non_zero_x(rng, components)?;
if let Some(y) = components::public(components, &x).into_option() {
return (x, y);
return Ok((x, y));
}
}
}
let (x, y) = find_components(rng, &components);
let (x, y) = find_components(rng, &components)?;
VerifyingKey::from_components(components, y.get())
Ok(VerifyingKey::from_components(components, y.get())
.and_then(|verifying_key| SigningKey::from_components(verifying_key, x.get()))
.expect("[Bug] Newly generated keypair considered invalid")
.expect("[Bug] Newly generated keypair considered invalid"))
}
+6 -2
View File
@@ -34,9 +34,7 @@ impl KeySize {
pub(crate) fn other(l: u32, n: u32) -> Self {
Self { l, n }
}
}
impl KeySize {
pub(crate) fn l_aligned(&self) -> u32 {
self.l.div_ceil(Limb::BITS) * Limb::BITS
}
@@ -50,6 +48,12 @@ impl KeySize {
}
}
impl Default for KeySize {
fn default() -> Self {
Self::DSA_3072_256
}
}
impl PartialEq for KeySize {
fn eq(&self, other: &Self) -> bool {
self.l_aligned() == other.l_aligned() && self.n_aligned() == other.n_aligned()
+8 -9
View File
@@ -12,16 +12,14 @@
//!
//! Generate a DSA keypair
//!
#![cfg_attr(feature = "hazmat", doc = "```")]
#![cfg_attr(not(feature = "hazmat"), doc = "```ignore")]
#![cfg_attr(feature = "getrandom", doc = "```")]
#![cfg_attr(not(feature = "getrandom"), doc = "```ignore")]
//! # fn main() -> Result<(), core::convert::Infallible> {
//! use dsa::{KeySize, Components, SigningKey};
//! // Note: requires `getrandom` feature is enabled.
//!
//! # use getrandom::{SysRng, rand_core::UnwrapErr};
//! # let mut csprng = UnwrapErr(SysRng);
//! use dsa::{KeySize, Components, Generate, SigningKey};
//!
//! let components = Components::try_generate_from_rng_with_key_size(&mut csprng, KeySize::DSA_2048_256)?;
//! let signing_key = SigningKey::generate(&mut csprng, components);
//! let signing_key = SigningKey::generate();
//! let verifying_key = signing_key.verifying_key();
//! # Ok(())
//! # }
@@ -61,9 +59,10 @@ extern crate alloc;
#[cfg(feature = "hazmat")]
pub use crate::signing_key::SigningKey;
pub use crate::{components::Components, size::KeySize, verifying_key::VerifyingKey};
pub use crate::{components::Components, key_size::KeySize, verifying_key::VerifyingKey};
pub use crypto_bigint::BoxedUint;
pub use crypto_common::Generate;
pub use signature;
#[cfg(feature = "pkcs8")]
@@ -73,8 +72,8 @@ use crypto_bigint::NonZero;
mod components;
mod generate;
mod key_size;
mod signing_key;
mod size;
mod verifying_key;
use alloc::{boxed::Box, vec::Vec};
+14 -5
View File
@@ -4,7 +4,7 @@
#![cfg(feature = "hazmat")]
use crate::{Signature, VerifyingKey};
use crate::{Components, Signature, VerifyingKey};
use core::{
cmp::min,
fmt::{self, Debug},
@@ -13,6 +13,7 @@ use crypto_bigint::{
BoxedUint, ConcatenatingMul, NonZero, Resize,
modular::{BoxedMontyForm, BoxedMontyParams},
};
use crypto_common::Generate;
use digest::{Digest, FixedOutputReset, common::BlockSizeUser};
use signature::{
DigestSigner, MultipartSigner, RandomizedDigestSigner, Signer,
@@ -21,8 +22,6 @@ use signature::{
};
use zeroize::{ZeroizeOnDrop, Zeroizing};
#[cfg(feature = "hazmat")]
use {crate::Components, signature::rand_core::CryptoRng};
#[cfg(feature = "pkcs8")]
use {
crate::OID,
@@ -70,8 +69,11 @@ impl SigningKey {
/// Generate a new DSA keypair
#[cfg(feature = "hazmat")]
#[inline]
pub fn generate<R: CryptoRng + ?Sized>(rng: &mut R, components: Components) -> SigningKey {
crate::generate::keypair(rng, components)
pub fn try_generate_from_rng_with_components<R: TryCryptoRng + ?Sized>(
rng: &mut R,
components: Components,
) -> Result<Self, R::Error> {
crate::generate::signing_keypair(rng, components)
}
/// DSA public key
@@ -152,6 +154,13 @@ impl SigningKey {
impl ZeroizeOnDrop for SigningKey {}
impl Generate for SigningKey {
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
let components = Components::try_generate_from_rng(rng)?;
Self::try_generate_from_rng_with_components(rng, components)
}
}
impl Signer<Signature> for SigningKey {
fn try_sign(&self, msg: &[u8]) -> Result<Signature, signature::Error> {
self.try_multipart_sign(&[msg])
+1 -1
View File
@@ -21,7 +21,7 @@ prop_compose! {
let mut rng = ChaCha8Rng::from_seed(seed);
#[allow(deprecated)]
let components = Components::try_generate_from_rng_with_key_size(&mut rng, KeySize::DSA_1024_160).unwrap();
SigningKey::generate(&mut rng, components)
SigningKey::try_generate_from_rng_with_components(&mut rng, components).unwrap()
}
}
+1 -1
View File
@@ -36,7 +36,7 @@ fn generate_random_keypair() -> SigningKey {
let mut rng = UnwrapErr(SysRng);
let components =
Components::try_generate_from_rng_with_key_size(&mut rng, KeySize::DSA_1024_160).unwrap();
SigningKey::generate(&mut rng, components)
SigningKey::try_generate_from_rng_with_components(&mut rng, components).unwrap()
}
#[test]
+1 -1
View File
@@ -20,7 +20,7 @@ fn generate_keypair() -> SigningKey {
let mut rng = UnwrapErr(SysRng);
let components =
Components::try_generate_from_rng_with_key_size(&mut rng, KeySize::DSA_1024_160).unwrap();
SigningKey::generate(&mut rng, components)
SigningKey::try_generate_from_rng_with_components(&mut rng, components).unwrap()
}
#[test]
+2 -1
View File
@@ -23,7 +23,8 @@ fn generate_verifying_key() -> VerifyingKey {
let mut rng = rand_core::UnwrapErr(SysRng);
let components =
Components::try_generate_from_rng_with_key_size(&mut rng, KeySize::DSA_1024_160).unwrap();
let signing_key = SigningKey::generate(&mut rng, components);
let signing_key =
SigningKey::try_generate_from_rng_with_components(&mut rng, components).unwrap();
signing_key.verifying_key().clone()
}