Don't reject small-order verification keys
Fixes ZcashFoundation/redjubjub#127.
This commit is contained in:
parent
3db05e29f7
commit
a34b04c0ad
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -2,6 +2,21 @@
|
||||||
|
|
||||||
Entries are listed in reverse chronological order.
|
Entries are listed in reverse chronological order.
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
* Fixed a bug where small-order verification keys (including the identity) were
|
||||||
|
handled inconsistently: the `VerificationKey` parsing logic rejected them, but
|
||||||
|
the identity `VerificationKey` could be produced from the zero `SigningKey`.
|
||||||
|
The behaviour is now to consistently accept all small-order verification keys,
|
||||||
|
matching the RedDSA specification.
|
||||||
|
|
||||||
|
* Downstream users who currently rely on the inconsistent behaviour (for e.g.
|
||||||
|
consensus compatibility, either explicitly wanting to reject small-order
|
||||||
|
verification keys, or on the belief that this crate implemented the RedDSA
|
||||||
|
specification) should continue to use previous versions of this crate, until
|
||||||
|
they can either move the checks into their own code, or migrate their
|
||||||
|
consensus rules to match the RedDSA specification.
|
||||||
|
|
||||||
## 0.2.2
|
## 0.2.2
|
||||||
|
|
||||||
* Make `batch::Item: Clone + Debug` and add `batch::Item::verify_single`
|
* Make `batch::Item: Clone + Debug` and add `batch::Item::verify_single`
|
||||||
|
|
|
@ -99,15 +99,16 @@ impl<T: SigType> TryFrom<VerificationKeyBytes<T>> for VerificationKey<T> {
|
||||||
let maybe_point = jubjub::AffinePoint::from_bytes(bytes.bytes);
|
let maybe_point = jubjub::AffinePoint::from_bytes(bytes.bytes);
|
||||||
if maybe_point.is_some().into() {
|
if maybe_point.is_some().into() {
|
||||||
let point: jubjub::ExtendedPoint = maybe_point.unwrap().into();
|
let point: jubjub::ExtendedPoint = maybe_point.unwrap().into();
|
||||||
// This checks that the verification key is not of small order.
|
// Note that small-order verification keys (including the identity) are not
|
||||||
if <bool>::from(point.is_small_order()) == false {
|
// rejected here. Previously they were rejected, but this was a bug as the
|
||||||
|
// RedDSA specification allows them. Zcash Sapling rejects small-order points
|
||||||
|
// for the RedJubjub spend authorization key rk; this now occurs separately.
|
||||||
|
// Meanwhile, Zcash Orchard uses a prime-order group, so the only small-order
|
||||||
|
// point would be the identity, which is allowed in Orchard.
|
||||||
Ok(VerificationKey { point, bytes })
|
Ok(VerificationKey { point, bytes })
|
||||||
} else {
|
} else {
|
||||||
Err(Error::MalformedVerificationKey)
|
Err(Error::MalformedVerificationKey)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Err(Error::MalformedVerificationKey)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,20 @@ use jubjub::{AffinePoint, Fq};
|
||||||
use redjubjub::*;
|
use redjubjub::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn smallorder_publickey_fails() {
|
fn identity_publickey_passes() {
|
||||||
|
let identity = AffinePoint::identity();
|
||||||
|
assert_eq!(<bool>::from(identity.is_small_order()), true);
|
||||||
|
let bytes = identity.to_bytes();
|
||||||
|
let pk_bytes = VerificationKeyBytes::<SpendAuth>::from(bytes);
|
||||||
|
assert!(VerificationKey::<SpendAuth>::try_from(pk_bytes).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn smallorder_publickey_passes() {
|
||||||
// (1,0) is a point of order 4 on any Edwards curve
|
// (1,0) is a point of order 4 on any Edwards curve
|
||||||
let order4 = AffinePoint::from_raw_unchecked(Fq::one(), Fq::zero());
|
let order4 = AffinePoint::from_raw_unchecked(Fq::one(), Fq::zero());
|
||||||
assert_eq!(<bool>::from(order4.is_small_order()), true);
|
assert_eq!(<bool>::from(order4.is_small_order()), true);
|
||||||
let bytes = order4.to_bytes();
|
let bytes = order4.to_bytes();
|
||||||
let pk_bytes = VerificationKeyBytes::<SpendAuth>::from(bytes);
|
let pk_bytes = VerificationKeyBytes::<SpendAuth>::from(bytes);
|
||||||
assert!(VerificationKey::<SpendAuth>::try_from(pk_bytes).is_err());
|
assert!(VerificationKey::<SpendAuth>::try_from(pk_bytes).is_ok());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue