Skip to content

Commit 07db2db

Browse files
committed
ed25519: switch to cofactored verification
1 parent a3cc0e4 commit 07db2db

File tree

4 files changed

+50
-25
lines changed

4 files changed

+50
-25
lines changed

src/ed25519.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -228,22 +228,20 @@ impl VerifyingState {
228228

229229
/// Verifies the signature and return it.
230230
pub fn verify(&self) -> Result<(), Error> {
231+
let mut expected_r_bytes = [0u8; 32];
232+
expected_r_bytes.copy_from_slice(&self.signature[0..32]);
233+
let expected_r =
234+
GeP3::from_bytes_vartime(&expected_r_bytes).ok_or(Error::InvalidSignature)?;
231235
let s = &self.signature[32..64];
232236

233237
let mut hash = self.hasher.finalize();
234238
sc_reduce(&mut hash);
235239

236-
let r = GeP2::double_scalarmult_vartime(hash.as_ref(), self.a, s);
237-
if r.to_bytes()
238-
.as_ref()
239-
.iter()
240-
.zip(self.signature.iter())
241-
.fold(0, |acc, (x, y)| acc | (x ^ y))
242-
!= 0
243-
{
244-
Err(Error::SignatureMismatch)
245-
} else {
240+
let r: GeP3 = GeP2::double_scalarmult_vartime(hash.as_ref(), self.a, s).into();
241+
if (expected_r - r).has_small_order() {
246242
Ok(())
243+
} else {
244+
Err(Error::SignatureMismatch)
247245
}
248246
}
249247
}

src/edwards25519.rs

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,17 @@ impl GeP1P1 {
7070
}
7171
}
7272

73+
impl From<GeP2> for GeP3 {
74+
fn from(p: GeP2) -> GeP3 {
75+
GeP3 {
76+
x: p.x,
77+
y: p.y,
78+
z: p.z,
79+
t: p.x * p.y,
80+
}
81+
}
82+
}
83+
7384
impl GeP2 {
7485
fn zero() -> GeP2 {
7586
GeP2 {
@@ -79,15 +90,6 @@ impl GeP2 {
7990
}
8091
}
8192

82-
pub fn to_bytes(&self) -> [u8; 32] {
83-
let recip = self.z.invert();
84-
let x = self.x * recip;
85-
let y = self.y * recip;
86-
let mut bs = y.to_bytes();
87-
bs[31] ^= (if x.is_negative() { 1 } else { 0 }) << 7;
88-
bs
89-
}
90-
9193
fn dbl(&self) -> GeP1P1 {
9294
let xx = self.x.square();
9395
let yy = self.y.square();
@@ -208,9 +210,9 @@ impl GeP3 {
208210

209211
let vxx = x.square() * v;
210212
let check = vxx - u;
211-
if check.is_nonzero() {
213+
if !check.is_zero() {
212214
let check2 = vxx + u;
213-
if check2.is_nonzero() {
215+
if !check2.is_zero() {
214216
return None;
215217
}
216218
x = x * FE_SQRTM1;
@@ -273,6 +275,31 @@ impl GeP3 {
273275
bs[31] ^= (if x.is_negative() { 1 } else { 0 }) << 7;
274276
bs
275277
}
278+
279+
pub fn has_small_order(&self) -> bool {
280+
let recip = self.z.invert();
281+
let x = self.x * recip;
282+
let y = self.y * recip;
283+
let x_neg = x.neg();
284+
let y_sqrtm1 = y * FE_SQRTM1;
285+
x.is_zero() | y.is_zero() | (y_sqrtm1 == x) | (y_sqrtm1 == x_neg)
286+
}
287+
}
288+
289+
impl Add<GeP3> for GeP3 {
290+
type Output = GeP3;
291+
292+
fn add(self, other: GeP3) -> GeP3 {
293+
(self + other.to_cached()).to_p3()
294+
}
295+
}
296+
297+
impl Sub<GeP3> for GeP3 {
298+
type Output = GeP3;
299+
300+
fn sub(self, other: GeP3) -> GeP3 {
301+
(self - other.to_cached()).to_p3()
302+
}
276303
}
277304

278305
impl Add<GeCached> for GeP3 {

src/field25519.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -596,8 +596,8 @@ impl Fe {
596596
z_255_21
597597
}
598598

599-
pub fn is_nonzero(&self) -> bool {
600-
self.to_bytes().iter().fold(0, |acc, x| acc | x) != 0
599+
pub fn is_zero(&self) -> bool {
600+
self.to_bytes().iter().fold(0, |acc, x| acc | x) == 0
601601
}
602602

603603
pub fn is_negative(&self) -> bool {

src/x25519.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ impl PublicKey {
132132
Fe::cswap2(&mut x2, &mut x3, &mut z2, &mut z3, swap);
133133
z2 = z2.invert();
134134
x2 = x2 * z2;
135-
if !x2.is_nonzero() {
135+
if x2.is_zero() {
136136
return Err(Error::WeakPublicKey);
137137
}
138138
Ok(x2.to_bytes())
@@ -248,7 +248,7 @@ impl KeyPair {
248248
pub fn generate() -> KeyPair {
249249
let mut sk = [0u8; SecretKey::BYTES];
250250
getrandom::getrandom(&mut sk).expect("getrandom");
251-
if !Fe::from_bytes(&sk).is_nonzero() {
251+
if Fe::from_bytes(&sk).is_zero() {
252252
panic!("All-zero secret key");
253253
}
254254
let sk = SecretKey(sk);

0 commit comments

Comments
 (0)