Skip to content

Commit 6cbef4f

Browse files
authored
dsa: handle NonZero/Odd conversions on BoxedUint internally (#998)
Makes `BoxedUint` the one unsigned integer type in the public API, converting to `NonZero<BoxedUint>` and `Odd<BoxedUint>` as needed. This makes the API simpler to use for end-users, with fewer types for them to manage. Closes #987
1 parent 3dfd263 commit 6cbef4f

File tree

9 files changed

+58
-95
lines changed

9 files changed

+58
-95
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ members = [
1515
opt-level = 2
1616

1717
[patch.crates-io]
18+
elliptic-curve = { git = "https://github.com/RustCrypto/traits.git" }
19+
1820
# A global patch crates-io block is used to avoid duplicate dependencies
1921
# when pulling a member crate through git
2022
dsa = { path = "./dsa" }

dsa/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ rust-version = "1.85"
1717

1818
[dependencies]
1919
digest = "0.11.0-rc.0"
20-
crypto-bigint = { version = "=0.7.0-pre.4", default-features = false, features = ["alloc", "zeroize"] }
20+
crypto-bigint = { version = "=0.7.0-pre.5", default-features = false, features = ["alloc", "zeroize"] }
2121
crypto-primes = { version = "=0.7.0-pre.1", default-features = false }
2222
pkcs8 = { version = "0.11.0-rc.1", default-features = false, features = ["alloc"] }
2323
rfc6979 = { version = "0.5.0-rc.0" }

dsa/src/components.rs

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,17 @@ pub struct Components {
3030

3131
impl Components {
3232
/// Construct the common components container from its inner values (p, q and g)
33-
pub fn from_components(
34-
p: Odd<BoxedUint>,
35-
q: NonZero<BoxedUint>,
36-
g: NonZero<BoxedUint>,
37-
) -> signature::Result<Self> {
33+
pub fn from_components(p: BoxedUint, q: BoxedUint, g: BoxedUint) -> signature::Result<Self> {
34+
let p = Odd::new(p)
35+
.into_option()
36+
.ok_or_else(signature::Error::new)?;
37+
let q = NonZero::new(q)
38+
.into_option()
39+
.ok_or_else(signature::Error::new)?;
40+
let g = NonZero::new(g)
41+
.into_option()
42+
.ok_or_else(signature::Error::new)?;
43+
3844
if *p < two() || *q < two() || *g > *p {
3945
return Err(signature::Error::new());
4046
}
@@ -54,7 +60,8 @@ impl Components {
5460
/// Generate a new pair of common components
5561
pub fn generate<R: CryptoRng + ?Sized>(rng: &mut R, key_size: KeySize) -> Self {
5662
let (p, q, g) = crate::generate::common_components(rng, key_size);
57-
Self::from_components(p, q, g).expect("[Bug] Newly generated components considered invalid")
63+
Self::from_components(p.get(), q.get(), g.get())
64+
.expect("[Bug] Newly generated components considered invalid")
5865
}
5966

6067
/// DSA prime p
@@ -84,22 +91,9 @@ impl<'a> DecodeValue<'a> for Components {
8491
let q = reader.decode::<UintRef<'_>>()?;
8592
let g = reader.decode::<UintRef<'_>>()?;
8693

87-
let p = BoxedUint::from_be_slice(p.as_bytes(), (p.as_bytes().len() * 8) as u32)
88-
.expect("invariant violation");
89-
let q = BoxedUint::from_be_slice(q.as_bytes(), (q.as_bytes().len() * 8) as u32)
90-
.expect("invariant violation");
91-
let g = BoxedUint::from_be_slice(g.as_bytes(), (g.as_bytes().len() * 8) as u32)
92-
.expect("invariant violation");
93-
94-
let p = Odd::new(p)
95-
.into_option()
96-
.ok_or(Tag::Integer.value_error())?;
97-
let q = NonZero::new(q)
98-
.into_option()
99-
.ok_or(Tag::Integer.value_error())?;
100-
let g = NonZero::new(g)
101-
.into_option()
102-
.ok_or(Tag::Integer.value_error())?;
94+
let p = BoxedUint::from_be_slice_vartime(p.as_bytes());
95+
let q = BoxedUint::from_be_slice_vartime(q.as_bytes());
96+
let g = BoxedUint::from_be_slice_vartime(g.as_bytes());
10397

10498
Self::from_components(p, q, g).map_err(|_| Tag::Integer.value_error())
10599
}

dsa/src/generate/keypair.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub fn keypair<R: CryptoRng + ?Sized>(rng: &mut R, components: Components) -> Si
3939

4040
let (x, y) = find_components(rng, &components);
4141

42-
VerifyingKey::from_components(components, y)
43-
.and_then(|verifying_key| SigningKey::from_components(verifying_key, x))
42+
VerifyingKey::from_components(components, y.get())
43+
.and_then(|verifying_key| SigningKey::from_components(verifying_key, x.get()))
4444
.expect("[Bug] Newly generated keypair considered invalid")
4545
}

dsa/src/lib.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@
2929
//! # use crypto_bigint::{BoxedUint, NonZero, Odd};
3030
//! # let read_common_parameters = ||
3131
//! # (
32-
//! # Odd::new(BoxedUint::one()).unwrap(),
33-
//! # NonZero::new(BoxedUint::one()).unwrap(),
34-
//! # NonZero::new(BoxedUint::one()).unwrap(),
32+
//! # BoxedUint::one(),
33+
//! # BoxedUint::one(),
34+
//! # BoxedUint::one(),
3535
//! # );
36-
//! # let read_public_component = || NonZero::new(BoxedUint::one()).unwrap();
37-
//! # let read_private_component = || NonZero::new(BoxedUint::one()).unwrap();
36+
//! # let read_public_component = || BoxedUint::one();
37+
//! # let read_private_component = || BoxedUint::one();
3838
//! # || -> signature::Result<()> {
3939
//! let (p, q, g) = read_common_parameters();
4040
//! let components = Components::from_components(p, q, g)?;
@@ -57,10 +57,11 @@ pub use crate::signing_key::SigningKey;
5757

5858
pub use crate::{components::Components, size::KeySize, verifying_key::VerifyingKey};
5959

60-
pub use crypto_bigint::{BoxedUint, NonZero, Odd};
60+
pub use crypto_bigint::BoxedUint;
6161
pub use pkcs8;
6262
pub use signature;
6363

64+
use crypto_bigint::NonZero;
6465
use pkcs8::spki::ObjectIdentifier;
6566

6667
mod components;
@@ -94,8 +95,10 @@ pub struct Signature {
9495

9596
impl Signature {
9697
/// Create a new Signature container from its components
97-
pub fn from_components(r: NonZero<BoxedUint>, s: NonZero<BoxedUint>) -> Self {
98-
Self { r, s }
98+
pub fn from_components(r: BoxedUint, s: BoxedUint) -> Option<Self> {
99+
let r = NonZero::new(r).into_option()?;
100+
let s = NonZero::new(s).into_option()?;
101+
Some(Self { r, s })
99102
}
100103

101104
/// Signature part r
@@ -124,14 +127,7 @@ impl<'a> DecodeValue<'a> for Signature {
124127
let s = BoxedUint::from_be_slice(s.as_bytes(), s.as_bytes().len() as u32 * 8)
125128
.map_err(|_| UintRef::TAG.value_error())?;
126129

127-
let r = NonZero::new(r)
128-
.into_option()
129-
.ok_or(UintRef::TAG.value_error())?;
130-
let s = NonZero::new(s)
131-
.into_option()
132-
.ok_or(UintRef::TAG.value_error())?;
133-
134-
Ok(Self::from_components(r, s))
130+
Self::from_components(r, s).ok_or_else(|| UintRef::TAG.value_error())
135131
})
136132
}
137133
}

dsa/src/signing_key.rs

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,11 @@ pub struct SigningKey {
4444

4545
impl SigningKey {
4646
/// Construct a new private key from the public key and private component
47-
pub fn from_components(
48-
verifying_key: VerifyingKey,
49-
x: NonZero<BoxedUint>,
50-
) -> signature::Result<Self> {
47+
pub fn from_components(verifying_key: VerifyingKey, x: BoxedUint) -> signature::Result<Self> {
48+
let x = NonZero::new(x)
49+
.into_option()
50+
.ok_or_else(signature::Error::new)?;
51+
5152
if x > *verifying_key.components().q() {
5253
return Err(signature::Error::new());
5354
}
@@ -116,26 +117,19 @@ impl SigningKey {
116117
debug_assert_eq!(key_size.l_aligned(), r.bits_precision());
117118

118119
let r_short = r.clone().resize(key_size.n_aligned());
119-
let r_short = NonZero::new(r_short)
120-
.expect("[bug] invalid value of k used here, the secret number computed was invalid");
121-
let r = NonZero::new(r)
122-
.expect("[bug] invalid value of k used here, the secret number computed was invalid");
123-
124120
let n = q.bits() / 8;
125121
let block_size = hash.len(); // Hash function output size
126122

127123
let z_len = min(n as usize, block_size);
128124
let z = BoxedUint::from_be_slice(&hash[..z_len], z_len as u32 * 8)
129125
.expect("invariant violation");
130126

131-
let s = inv_k.mul_mod(&(z + &**x * &*r), &q.resize(key_size.l_aligned()));
127+
let s = inv_k.mul_mod(&(z + &**x * &r), &q.resize(key_size.l_aligned()));
132128
let s = s.resize(key_size.n_aligned());
133-
let s = NonZero::new(s)
134-
.expect("[bug] invalid value of k used here, the secret number computed was invalid");
135129

136130
debug_assert_eq!(key_size.n_aligned(), r_short.bits_precision());
137131
debug_assert_eq!(key_size.n_aligned(), s.bits_precision());
138-
let signature = Signature::from_components(r_short, s);
132+
let signature = Signature::from_components(r_short, s).ok_or_else(signature::Error::new)?;
139133

140134
if signature.r() < q && signature.s() < q {
141135
Ok(signature)
@@ -260,21 +254,19 @@ impl<'a> TryFrom<PrivateKeyInfoRef<'a>> for SigningKey {
260254

261255
let y = if let Some(y_bytes) = value.public_key.as_ref().and_then(|bs| bs.as_bytes()) {
262256
let y = UintRef::from_der(y_bytes)?;
263-
let y = BoxedUint::from_be_slice(y.as_bytes(), precision)
264-
.map_err(|_| pkcs8::Error::KeyMalformed)?;
265-
NonZero::new(y)
266-
.into_option()
267-
.ok_or(pkcs8::Error::KeyMalformed)?
257+
BoxedUint::from_be_slice(y.as_bytes(), precision)
258+
.map_err(|_| pkcs8::Error::KeyMalformed)?
268259
} else {
269260
crate::generate::public_component(&components, &x)
270261
.into_option()
271262
.ok_or(pkcs8::Error::KeyMalformed)?
263+
.get()
272264
};
273265

274266
let verifying_key =
275267
VerifyingKey::from_components(components, y).map_err(|_| pkcs8::Error::KeyMalformed)?;
276268

277-
SigningKey::from_components(verifying_key, x).map_err(|_| pkcs8::Error::KeyMalformed)
269+
SigningKey::from_components(verifying_key, x.get()).map_err(|_| pkcs8::Error::KeyMalformed)
278270
}
279271
}
280272

dsa/src/verifying_key.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ pub struct VerifyingKey {
3232

3333
impl VerifyingKey {
3434
/// Construct a new public key from the common components and the public component
35-
pub fn from_components(
36-
components: Components,
37-
y: NonZero<BoxedUint>,
38-
) -> signature::Result<Self> {
35+
pub fn from_components(components: Components, y: BoxedUint) -> signature::Result<Self> {
36+
let y = NonZero::new(y)
37+
.into_option()
38+
.ok_or_else(signature::Error::new)?;
39+
3940
let params = BoxedMontyParams::new_vartime(components.p().clone());
4041
let form = BoxedMontyForm::new((*y).clone(), params);
4142

@@ -192,13 +193,7 @@ impl<'a> TryFrom<SubjectPublicKeyInfoRef<'a>> for VerifyingKey {
192193
.as_bytes()
193194
.ok_or(spki::Error::KeyMalformed)?,
194195
)?;
195-
196-
let y = NonZero::new(
197-
BoxedUint::from_be_slice(y.as_bytes(), y.as_bytes().len() as u32 * 8)
198-
.expect("invariant violation"),
199-
)
200-
.into_option()
201-
.ok_or(spki::Error::KeyMalformed)?;
196+
let y = BoxedUint::from_be_slice_vartime(y.as_bytes());
202197

203198
Self::from_components(components, y).map_err(|_| spki::Error::KeyMalformed)
204199
}

dsa/tests/deterministic.rs

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![cfg(feature = "hazmat")]
2-
use crypto_bigint::{BoxedUint, NonZero, Odd};
2+
use crypto_bigint::BoxedUint;
33
use digest::{Digest, FixedOutputReset, block_api::BlockSizeUser};
44
use dsa::{Components, Signature, SigningKey, VerifyingKey};
55
use sha1::Sha1;
@@ -39,14 +39,6 @@ fn dsa_1024_signing_key() -> SigningKey {
3939
82F65CBDC4FAE93C2EA212390E54905A86E2223170B44EAA7DA5DD9FFCFB7F3B";
4040
let y = decode_hex_number(y_str, 1024);
4141

42-
let (p, q, g, y, x) = (
43-
Odd::new(p).unwrap(),
44-
NonZero::new(q).unwrap(),
45-
NonZero::new(g).unwrap(),
46-
NonZero::new(y).unwrap(),
47-
NonZero::new(x).unwrap(),
48-
);
49-
5042
let components = Components::from_components(p, q, g).expect("Invalid components");
5143
let verifying_key =
5244
VerifyingKey::from_components(components, y).expect("Invalid verifying key");
@@ -98,14 +90,6 @@ fn dsa_2048_signing_key() -> SigningKey {
9890
2048,
9991
);
10092

101-
let (p, q, g, y, x) = (
102-
Odd::new(p).unwrap(),
103-
NonZero::new(q).unwrap(),
104-
NonZero::new(g).unwrap(),
105-
NonZero::new(y).unwrap(),
106-
NonZero::new(x).unwrap(),
107-
);
108-
10993
let components = Components::from_components(p, q, g).expect("Invalid components");
11094
let verifying_key =
11195
VerifyingKey::from_components(components, y).expect("Invalid verifying key");
@@ -144,9 +128,10 @@ fn from_str_signature(r: &str, s: &str) -> Signature {
144128
let precision = (r.len() * 8) as u32;
145129

146130
Signature::from_components(
147-
NonZero::new(decode_hex_number(r, precision)).unwrap(),
148-
NonZero::new(decode_hex_number(s, precision)).unwrap(),
131+
decode_hex_number(r, precision),
132+
decode_hex_number(s, precision),
149133
)
134+
.unwrap()
150135
}
151136

152137
/// Return the RFC 6979 test cases

0 commit comments

Comments
 (0)