Skip to content

Commit 92be6ad

Browse files
committed
Implement a constant time Scalar::is_canonical check
1 parent e8fdd99 commit 92be6ad

File tree

2 files changed

+12
-8
lines changed

2 files changed

+12
-8
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ harness = false
4545
rand_core = { version = "0.5", default-features = false }
4646
byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] }
4747
digest = { version = "0.9", default-features = false }
48-
subtle = { version = "^2.2.1", default-features = false }
48+
subtle = { version = "^2.4", default-features = false }
4949
serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] }
5050
# The original packed_simd package was orphaned, see
5151
# https://github.com/rust-lang/packed_simd/issues/303#issuecomment-701361161

src/scalar.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,7 @@ use rand_core::{CryptoRng, RngCore};
157157
use digest::generic_array::typenum::U64;
158158
use digest::Digest;
159159

160-
use subtle::Choice;
161-
use subtle::ConditionallySelectable;
162-
use subtle::ConstantTimeEq;
160+
use subtle::{Choice, ConstantTimeGreater, ConditionallySelectable, ConstantTimeEq};
163161

164162
use zeroize::Zeroize;
165163

@@ -237,9 +235,7 @@ impl Scalar {
237235
/// if `bytes` is a canonical byte representation;
238236
/// - `None` if `bytes` is not a canonical byte representation.
239237
pub fn from_canonical_bytes(bytes: [u8; 32]) -> Option<Scalar> {
240-
// Check that the high bit is not set
241-
if (bytes[31] >> 7) != 0u8 { return None; }
242-
let candidate = Scalar::from_bits(bytes);
238+
let candidate = Scalar{bytes};
243239

244240
if candidate.is_canonical() {
245241
Some(candidate)
@@ -1127,7 +1123,15 @@ impl Scalar {
11271123
/// # }
11281124
/// ```
11291125
pub fn is_canonical(&self) -> bool {
1130-
*self == self.reduce()
1126+
let mut over = Choice::from(0);
1127+
let mut under = Choice::from(0);
1128+
for (this, l) in self.unpack().0.iter().zip(&constants::L.0).rev() {
1129+
let gt = this.ct_gt(&l);
1130+
let eq = this.ct_eq(&l);
1131+
under |= (!gt & !eq) &!over;
1132+
over |= gt;
1133+
}
1134+
under.into()
11311135
}
11321136
}
11331137

0 commit comments

Comments
 (0)