Skip to content

Commit 988f281

Browse files
committed
Make Scalar::is_canonical return Choice, and Scalar::from_canonical_bytes return CTOption
1 parent 92be6ad commit 988f281

File tree

2 files changed

+27
-29
lines changed

2 files changed

+27
-29
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ extern crate zeroize;
270270
extern crate fiat_crypto;
271271

272272
// Used for traits related to constant-time code.
273-
extern crate subtle;
273+
pub extern crate subtle;
274274

275275
#[cfg(all(test, feature = "serde"))]
276276
extern crate bincode;

src/scalar.rs

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -35,28 +35,30 @@
3535
//!
3636
//! ```
3737
//! use curve25519_dalek::scalar::Scalar;
38+
//! use curve25519_dalek::subtle::CtOption;
3839
//!
3940
//! let one_as_bytes: [u8; 32] = Scalar::one().to_bytes();
40-
//! let a: Option<Scalar> = Scalar::from_canonical_bytes(one_as_bytes);
41+
//! let a: CtOption<Scalar> = Scalar::from_canonical_bytes(one_as_bytes);
4142
//!
42-
//! assert!(a.is_some());
43+
//! assert!(bool::from(a.is_some()));
4344
//! ```
4445
//!
4546
//! However, if we give it bytes representing a scalar larger than \\( \ell \\)
4647
//! (in this case, \\( \ell + 2 \\)), we'll get `None` back:
4748
//!
4849
//! ```
4950
//! use curve25519_dalek::scalar::Scalar;
51+
//! use curve25519_dalek::subtle::CtOption;
5052
//!
5153
//! let l_plus_two_bytes: [u8; 32] = [
5254
//! 0xef, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
5355
//! 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
5456
//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5557
//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
5658
//! ];
57-
//! let a: Option<Scalar> = Scalar::from_canonical_bytes(l_plus_two_bytes);
59+
//! let a: CtOption<Scalar> = Scalar::from_canonical_bytes(l_plus_two_bytes);
5860
//!
59-
//! assert!(a.is_none());
61+
//! assert!(bool::from(a.is_none()));
6062
//! ```
6163
//!
6264
//! Another way to create a `Scalar` is by reducing a \\(256\\)-bit integer mod
@@ -132,7 +134,7 @@
132134
//! let two: Scalar = Scalar::one() + Scalar::one();
133135
//!
134136
//! assert!(a != two); // the scalar is not reduced (mod l)…
135-
//! assert!(! a.is_canonical()); // …and therefore is not canonical.
137+
//! assert!(! bool::from(a.is_canonical())); // …and therefore is not canonical.
136138
//! assert!(a.reduce() == two); // if we were to reduce it manually, it would be.
137139
//! ```
138140
//!
@@ -157,7 +159,8 @@ use rand_core::{CryptoRng, RngCore};
157159
use digest::generic_array::typenum::U64;
158160
use digest::Digest;
159161

160-
use subtle::{Choice, ConstantTimeGreater, ConditionallySelectable, ConstantTimeEq};
162+
use subtle::{CtOption, Choice};
163+
use subtle::{ConstantTimeGreater, ConditionallySelectable, ConstantTimeEq};
161164

162165
use zeroize::Zeroize;
163166

@@ -234,14 +237,9 @@ impl Scalar {
234237
/// - `Some(s)`, where `s` is the `Scalar` corresponding to `bytes`,
235238
/// if `bytes` is a canonical byte representation;
236239
/// - `None` if `bytes` is not a canonical byte representation.
237-
pub fn from_canonical_bytes(bytes: [u8; 32]) -> Option<Scalar> {
240+
pub fn from_canonical_bytes(bytes: [u8; 32]) -> CtOption<Scalar> {
238241
let candidate = Scalar{bytes};
239-
240-
if candidate.is_canonical() {
241-
Some(candidate)
242-
} else {
243-
None
244-
}
242+
CtOption::new(candidate, candidate.is_canonical())
245243
}
246244

247245
/// Construct a `Scalar` from the low 255 bits of a 256-bit integer.
@@ -1106,7 +1104,7 @@ impl Scalar {
11061104

11071105
/// Check whether this `Scalar` is the canonical representative mod \\(\ell\\).
11081106
///
1109-
/// This is intended for uses like input validation, where variable-time code is acceptable.
1107+
/// This is intended for uses like input validation.
11101108
///
11111109
/// ```
11121110
/// # extern crate curve25519_dalek;
@@ -1116,13 +1114,13 @@ impl Scalar {
11161114
/// # fn main() {
11171115
/// // 2^255 - 1, since `from_bits` clears the high bit
11181116
/// let _2_255_minus_1 = Scalar::from_bits([0xff;32]);
1119-
/// assert!(!_2_255_minus_1.is_canonical());
1117+
/// assert!(!bool::from(_2_255_minus_1.is_canonical()));
11201118
///
11211119
/// let reduced = _2_255_minus_1.reduce();
1122-
/// assert!(reduced.is_canonical());
1120+
/// assert!(bool::from(reduced.is_canonical()));
11231121
/// # }
11241122
/// ```
1125-
pub fn is_canonical(&self) -> bool {
1123+
pub fn is_canonical(&self) -> Choice {
11261124
let mut over = Choice::from(0);
11271125
let mut under = Choice::from(0);
11281126
for (this, l) in self.unpack().0.iter().zip(&constants::L.0).rev() {
@@ -1131,7 +1129,7 @@ impl Scalar {
11311129
under |= (!gt & !eq) &!over;
11321130
over |= gt;
11331131
}
1134-
under.into()
1132+
under
11351133
}
11361134
}
11371135

@@ -1670,16 +1668,16 @@ mod test {
16701668
let non_canonical_full = [0xFF; 32];
16711669
let non_canonical_255_minus_1 = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0b0111_1111];
16721670

1673-
assert!( Scalar::from_canonical_bytes(canonical_bytes).is_some() );
1674-
assert!( Scalar::from_canonical_bytes(canonical_l_minus_one).is_some() );
1675-
assert!( Scalar::from_canonical_bytes(canonical_zero).is_some() );
1676-
assert!( Scalar::from_canonical_bytes(canonical_255_minus_1).is_some() );
1677-
assert!( Scalar::from_canonical_bytes(non_canonical_bytes_because_unreduced).is_none() );
1678-
assert!( Scalar::from_canonical_bytes(non_canonical_bytes_because_highbit).is_none() );
1679-
assert!( Scalar::from_canonical_bytes(non_canonical_l).is_none() );
1680-
assert!( Scalar::from_canonical_bytes(non_canonical_l_plus_one).is_none() );
1681-
assert!( Scalar::from_canonical_bytes(non_canonical_full).is_none() );
1682-
assert!( Scalar::from_canonical_bytes(non_canonical_255_minus_1).is_none() );
1671+
assert!( bool::from(Scalar::from_canonical_bytes(canonical_bytes).is_some()) );
1672+
assert!( bool::from(Scalar::from_canonical_bytes(canonical_l_minus_one).is_some()) );
1673+
assert!( bool::from(Scalar::from_canonical_bytes(canonical_zero).is_some()) );
1674+
assert!( bool::from(Scalar::from_canonical_bytes(canonical_255_minus_1).is_some()) );
1675+
assert!( bool::from(Scalar::from_canonical_bytes(non_canonical_bytes_because_unreduced).is_none()) );
1676+
assert!( bool::from(Scalar::from_canonical_bytes(non_canonical_bytes_because_highbit).is_none()) );
1677+
assert!( bool::from(Scalar::from_canonical_bytes(non_canonical_l).is_none()) );
1678+
assert!( bool::from(Scalar::from_canonical_bytes(non_canonical_l_plus_one).is_none()) );
1679+
assert!( bool::from(Scalar::from_canonical_bytes(non_canonical_full).is_none()) );
1680+
assert!( bool::from(Scalar::from_canonical_bytes(non_canonical_255_minus_1).is_none()) );
16831681
}
16841682

16851683
#[test]

0 commit comments

Comments
 (0)