Skip to content

Commit dcae306

Browse files
authored
elliptic-curve: SecretKey::from_slice allows >=24-bytes (#1412)
To address the concerns in #1330, sets a global minimum elliptic curve key size of 24-bytes (192-bits), which provides the equivalent of 96-bit symmetric security.
1 parent 20ae48b commit dcae306

File tree

2 files changed

+19
-26
lines changed

2 files changed

+19
-26
lines changed

elliptic-curve/src/secret_key.rs

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{Curve, Error, FieldBytes, Result, ScalarPrimitive};
1212
use core::fmt::{self, Debug};
1313
use generic_array::typenum::Unsigned;
1414
use subtle::{Choice, ConstantTimeEq};
15-
use zeroize::{Zeroize, ZeroizeOnDrop};
15+
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
1616

1717
#[cfg(feature = "arithmetic")]
1818
use crate::{rand_core::CryptoRngCore, CurveArithmetic, NonZeroScalar, PublicKey};
@@ -40,7 +40,6 @@ use {
4040
},
4141
alloc::vec::Vec,
4242
sec1::der::Encode,
43-
zeroize::Zeroizing,
4443
};
4544

4645
#[cfg(all(feature = "arithmetic", any(feature = "jwk", feature = "pem")))]
@@ -85,6 +84,11 @@ impl<C> SecretKey<C>
8584
where
8685
C: Curve,
8786
{
87+
/// Minimum allowed size of an elliptic curve secret key in bytes.
88+
///
89+
/// This provides the equivalent of 96-bits of symmetric security.
90+
const MIN_SIZE: usize = 24;
91+
8892
/// Generate a random [`SecretKey`].
8993
#[cfg(feature = "arithmetic")]
9094
pub fn random(rng: &mut impl CryptoRngCore) -> Self
@@ -148,31 +152,20 @@ where
148152
Ok(Self { inner })
149153
}
150154

151-
/// Deserialize secret key from an encoded secret scalar passed as a
152-
/// byte slice.
155+
/// Deserialize secret key from an encoded secret scalar passed as a byte slice.
156+
///
157+
/// The slice is expected to be a minimum of 24-bytes (192-byts) and at most `C::FieldBytesSize`
158+
/// bytes in length.
153159
///
154-
/// The slice is expected to be at most `C::FieldBytesSize` bytes in
155-
/// length but may be up to 4-bytes shorter than that, which is handled by
156-
/// zero-padding the value.
160+
/// Byte slices shorter than the field size are handled by zero padding the input.
157161
pub fn from_slice(slice: &[u8]) -> Result<Self> {
158-
if slice.len() > C::FieldBytesSize::USIZE {
159-
return Err(Error);
160-
}
161-
162-
/// Maximum number of "missing" bytes to interpret as zeroes.
163-
const MAX_LEADING_ZEROES: usize = 4;
164-
165-
let offset = C::FieldBytesSize::USIZE.saturating_sub(slice.len());
166-
167-
if offset == 0 {
162+
if slice.len() == C::FieldBytesSize::USIZE {
168163
Self::from_bytes(FieldBytes::<C>::from_slice(slice))
169-
} else if offset <= MAX_LEADING_ZEROES {
170-
let mut bytes = FieldBytes::<C>::default();
164+
} else if (Self::MIN_SIZE..C::FieldBytesSize::USIZE).contains(&slice.len()) {
165+
let mut bytes = Zeroizing::new(FieldBytes::<C>::default());
166+
let offset = C::FieldBytesSize::USIZE.saturating_sub(slice.len());
171167
bytes[offset..].copy_from_slice(slice);
172-
173-
let ret = Self::from_bytes(&bytes);
174-
bytes.zeroize();
175-
ret
168+
Self::from_bytes(&bytes)
176169
} else {
177170
Err(Error)
178171
}

elliptic-curve/tests/secret_key.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use elliptic_curve::dev::SecretKey;
66

77
#[test]
8-
fn from_slice_undersize() {
8+
fn from_empty_slice() {
99
assert!(SecretKey::from_slice(&[]).is_err());
1010
}
1111

@@ -17,12 +17,12 @@ fn from_slice_expected_size() {
1717

1818
#[test]
1919
fn from_slice_allowed_short() {
20-
let bytes = [1u8; 28];
20+
let bytes = [1u8; 24];
2121
assert!(SecretKey::from_slice(&bytes).is_ok());
2222
}
2323

2424
#[test]
2525
fn from_slice_too_short() {
26-
let bytes = [1u8; 27];
26+
let bytes = [1u8; 23]; // min 24-bytes
2727
assert!(SecretKey::from_slice(&bytes).is_err());
2828
}

0 commit comments

Comments
 (0)