Wrap the existing basepoint table as a BasepointTable

This commit is contained in:
Henry de Valence 2017-03-06 21:48:31 -08:00
parent 05fa1318b9
commit 640f40287f
2 changed files with 40 additions and 97 deletions

View file

@ -23,6 +23,7 @@ use field::FieldElement;
use curve::ExtendedPoint;
use curve::AffineNielsPoint;
use curve::CompressedEdwardsY;
use curve::BasepointTable;
use scalar::Scalar;
pub const d: FieldElement = FieldElement([
@ -100,7 +101,7 @@ pub const BASE_CMPRSSD: CompressedEdwardsY =
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]);
/// Basepoint has y = 4/5.
pub const BASEPOINT: ExtendedPoint = ExtendedPoint{
pub const ED25519_BASEPOINT: ExtendedPoint = ExtendedPoint{
X: FieldElement([-14297830, -7645148, 16144683, -16471763, 27570974, -2696100, -26142465, 8378389, 20764389, 8758491]),
Y: FieldElement([-26843541, -6710886, 13421773, -13421773, 26843546, 6710886, -13421773, 13421773, -26843546, -6710886]),
Z: FieldElement([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
@ -225,7 +226,7 @@ pub const bi: [AffineNielsPoint; 8] = [
///
/// The table is defined so `constants::base[i][j-1] = j*(16^2i)*B`,
/// for `0 ≤ i < 32`, `1 ≤ j < 9`.
pub const base: [[AffineNielsPoint; 8]; 32] = [
pub const ED25519_BASEPOINT_TABLE: BasepointTable = BasepointTable([
[
AffineNielsPoint{
y_plus_x: FieldElement([25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605]),
@ -1569,7 +1570,7 @@ pub const base: [[AffineNielsPoint; 8]; 32] = [
y_minus_x: FieldElement([29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684]),
xy2d: FieldElement([-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476]),
},
]];
]]);
#[cfg(test)]
mod test {
@ -1670,23 +1671,4 @@ mod test {
let a_minus_d = &a - &constants::d;
assert_eq!(a_minus_d, constants::a_minus_d);
}
/// Test the values in the lookup table of precomputed multiples
/// of the basepoint.
#[test]
fn test_precomputed_basepoint_multiples() {
let bp = constants::BASE_CMPRSSD.decompress().unwrap();
let mut P = bp;
for i in 0..32 {
// P = (16^2)^i * B
let mut jP = P.to_affine_niels();
for j in 1..9 {
// constants::base[i][j-1] is supposed to be
// j * (16^2)^i * B
assert_eq!(constants::base[i][j-1], jP);
jP = (&P + &jP).to_extended().to_affine_niels();
}
P = P.mult_by_pow_2(8);
}
}
}

View file

@ -912,52 +912,11 @@ pub trait BasepointMult<S> {
impl BasepointMult<Scalar> for ExtendedPoint {
fn basepoint() -> ExtendedPoint {
constants::BASEPOINT
constants::ED25519_BASEPOINT
}
/// Construct an `ExtendedPoint` from a `Scalar`, `scalar`, by
/// computing the multiple `aB` of the basepoint `B`.
///
/// Precondition: the scalar must be reduced.
///
/// The computation proceeds as follows, as described on page 13
/// of the Ed25519 paper. Write the scalar `a` in radix 16 with
/// coefficients in [-8,8), i.e.,
///
/// a = a_0 + a_1*16^1 + ... + a_63*16^63,
///
/// with -8 ≤ a_i < 8. Then
///
/// a*B = a_0*B + a_1*16^1*B + ... + a_63*16^63*B.
///
/// Grouping even and odd coefficients gives
///
/// a*B = a_0*16^0*B + a_2*16^2*B + ... + a_62*16^62*B
/// + a_1*16^1*B + a_3*16^3*B + ... + a_63*16^63*B
/// = (a_0*16^0*B + a_2*16^2*B + ... + a_62*16^62*B)
/// + 16*(a_1*16^0*B + a_3*16^2*B + ... + a_63*16^62*B).
///
/// We then use the `select_precomputed_point` function, which
/// takes `-8 ≤ x < 8` and `[16^2i * B, ..., 8 * 16^2i * B]`,
/// and returns `x * 16^2i * B` in constant time.
fn basepoint_mult(scalar: &Scalar) -> ExtendedPoint { //GeScalarMultBase
let e = scalar.to_radix_16();
let mut h = ExtendedPoint::identity();
let mut t: CompletedPoint;
for i in (0..64).filter(|x| x % 2 == 1) {
t = &h + &select_precomputed_point(e[i], &constants::base[i/2]);
h = t.to_extended();
}
h = h.mult_by_pow_2(4);
for i in (0..64).filter(|x| x % 2 == 0) {
t = &h + &select_precomputed_point(e[i], &constants::base[i/2]);
h = t.to_extended();
}
h
fn basepoint_mult(scalar: &Scalar) -> ExtendedPoint {
constants::ED25519_BASEPOINT_TABLE.basepoint_mult(scalar)
}
}
@ -1222,7 +1181,7 @@ mod test {
/// Test Montgomery conversion against the X25519 basepoint.
#[test]
fn basepoint_to_montgomery() {
assert_eq!(constants::BASEPOINT.compress_montgomery().unwrap(),
assert_eq!(constants::ED25519_BASEPOINT.compress_montgomery().unwrap(),
BASE_CMPRSSD_MONTY);
}
@ -1275,10 +1234,10 @@ mod test {
.decompress().unwrap();
// Test projective coordinates exactly since we know they should
// only differ by a flipped sign.
assert_eq!(minus_basepoint.X, -(&constants::BASEPOINT.X));
assert_eq!(minus_basepoint.Y, constants::BASEPOINT.Y);
assert_eq!(minus_basepoint.Z, constants::BASEPOINT.Z);
assert_eq!(minus_basepoint.T, -(&constants::BASEPOINT.T));
assert_eq!(minus_basepoint.X, -(&constants::ED25519_BASEPOINT.X));
assert_eq!(minus_basepoint.Y, constants::ED25519_BASEPOINT.Y);
assert_eq!(minus_basepoint.Z, constants::ED25519_BASEPOINT.Z);
assert_eq!(minus_basepoint.T, -(&constants::ED25519_BASEPOINT.T));
}
/// Test that computing 1*basepoint gives the correct basepoint.
@ -1293,7 +1252,7 @@ mod test {
/// using basepoint + basepoint versus the 2*basepoint constant.
#[test]
fn basepoint_plus_basepoint_vs_basepoint2() {
let bp = constants::BASEPOINT;
let bp = constants::ED25519_BASEPOINT;
let bp_added = &bp + &bp;
assert_eq!(bp_added.compress_edwards(), BASE2_CMPRSSD);
}
@ -1302,7 +1261,7 @@ mod test {
/// using the basepoint, basepoint2 constants
#[test]
fn basepoint_plus_basepoint_projective_niels_vs_basepoint2() {
let bp = constants::BASEPOINT;
let bp = constants::ED25519_BASEPOINT;
let bp_added = (&bp + &bp.to_projective_niels()).to_extended();
assert_eq!(bp_added.compress_edwards(), BASE2_CMPRSSD);
}
@ -1311,7 +1270,7 @@ mod test {
/// using the basepoint, basepoint2 constants
#[test]
fn basepoint_plus_basepoint_affine_niels_vs_basepoint2() {
let bp = constants::BASEPOINT;
let bp = constants::ED25519_BASEPOINT;
let bp_affine_niels = bp.to_affine_niels();
let bp_added = (&bp + &bp_affine_niels).to_extended();
assert_eq!(bp_added.compress_edwards(), BASE2_CMPRSSD);
@ -1360,16 +1319,17 @@ mod test {
/// Test precomputed basepoint mult
#[test]
fn test_precomputed_basepoint_mult() {
let table = BasepointTable::create(&constants::BASEPOINT);
let table = BasepointTable::create(&constants::ED25519_BASEPOINT);
let aB_1 = ExtendedPoint::basepoint_mult(&A_SCALAR);
let aB_2 = table.basepoint_mult(&A_SCALAR);
assert_eq!(aB_1.compress(), aB_2.compress());
assert_eq!(aB_1.compress_edwards(),
aB_2.compress_edwards());
}
/// Test scalar_mult versus a known scalar multiple from ed25519.py
#[test]
fn scalar_mult_vs_ed25519py() {
let aB = constants::BASEPOINT.scalar_mult(&A_SCALAR);
let aB = constants::ED25519_BASEPOINT.scalar_mult(&A_SCALAR);
assert_eq!(aB.compress_edwards(), A_TIMES_BASEPOINT);
}
@ -1384,7 +1344,7 @@ mod test {
/// Test basepoint.double() versus the 2*basepoint constant.
#[test]
fn basepoint_double_vs_basepoint2() {
assert_eq!(constants::BASEPOINT.double().compress_edwards(),
assert_eq!(constants::ED25519_BASEPOINT.double().compress_edwards(),
BASE2_CMPRSSD);
}
@ -1399,14 +1359,15 @@ mod test {
/// Check that converting to projective and then back to extended round-trips.
#[test]
fn basepoint_projective_extended_round_trip() {
assert_eq!(constants::BASEPOINT.to_projective().to_extended().compress_edwards(),
assert_eq!(constants::ED25519_BASEPOINT
.to_projective().to_extended().compress_edwards(),
constants::BASE_CMPRSSD);
}
/// Test computing 16*basepoint vs mult_by_pow_2(4)
#[test]
fn basepoint16_vs_mult_by_pow_2_4() {
let bp16 = constants::BASEPOINT.mult_by_pow_2(4);
let bp16 = constants::ED25519_BASEPOINT.mult_by_pow_2(4);
assert_eq!(bp16.compress_edwards(), BASE16_CMPRSSD);
}
@ -1415,7 +1376,7 @@ mod test {
fn conditional_assign_for_affine_niels_point() {
let id = AffineNielsPoint::identity();
let mut p1 = AffineNielsPoint::identity();
let bp = constants::BASEPOINT.to_affine_niels();
let bp = constants::ED25519_BASEPOINT.to_affine_niels();
p1.conditional_assign(&bp, 0);
assert_eq!(p1, id);
@ -1426,7 +1387,7 @@ mod test {
#[test]
fn is_small_order() {
// The basepoint has large prime order
assert!(constants::BASEPOINT.is_small_order() == false);
assert!(constants::ED25519_BASEPOINT.is_small_order() == false);
// constants::EIGHT_TORSION has all points of small order.
for torsion_point in &constants::EIGHT_TORSION {
assert!(torsion_point.is_small_order() == true);
@ -1441,8 +1402,8 @@ mod test {
#[test]
fn is_identity() {
assert!(ExtendedPoint::identity().is_identity() == true);
assert!( constants::BASEPOINT.is_identity() == false);
assert!( ExtendedPoint::identity().is_identity() == true);
assert!(constants::ED25519_BASEPOINT.is_identity() == false);
}
}
@ -1464,13 +1425,13 @@ mod bench {
#[bench]
fn scalar_mult(b: &mut Bencher) {
let bp = constants::BASEPOINT;
let bp = constants::ED25519_BASEPOINT;
b.iter(|| bp.scalar_mult(&A_SCALAR));
}
#[bench]
fn bench_select_precomputed_point(b: &mut Bencher) {
b.iter(|| select_precomputed_point(0, &constants::base[12]));
b.iter(|| select_precomputed_point(0, &constants::ED25519_BASEPOINT_TABLE.0[0]));
}
#[bench]
@ -1481,53 +1442,53 @@ mod bench {
#[bench]
fn add_extended_and_cached_output_completed(b: &mut Bencher) {
let p1 = constants::BASEPOINT;
let p2 = constants::BASEPOINT.to_projective_niels();
let p1 = constants::ED25519_BASEPOINT;
let p2 = constants::ED25519_BASEPOINT.to_projective_niels();
b.iter(|| &p1 + &p2);
}
#[bench]
fn add_extended_and_cached_output_extended(b: &mut Bencher) {
let p1 = constants::BASEPOINT;
let p2 = constants::BASEPOINT.to_projective_niels();
let p1 = constants::ED25519_BASEPOINT;
let p2 = constants::ED25519_BASEPOINT.to_projective_niels();
b.iter(|| (&p1 + &p2).to_extended());
}
#[bench]
fn add_extended_and_precomputed_output_completed(b: &mut Bencher) {
let p1 = constants::BASEPOINT;
let p2 = select_precomputed_point(6, &constants::base[27]);
let p1 = constants::ED25519_BASEPOINT;
let p2 = constants::ED25519_BASEPOINT.to_affine_niels();
b.iter(|| &p1 + &p2);
}
#[bench]
fn add_extended_and_precomputed_output_extended(b: &mut Bencher) {
let p1 = constants::BASEPOINT;
let p2 = select_precomputed_point(6, &constants::base[27]);
let p1 = constants::ED25519_BASEPOINT;
let p2 = constants::ED25519_BASEPOINT.to_affine_niels();
b.iter(|| (&p1 + &p2).to_extended());
}
#[bench]
fn projective_double_output_completed(b: &mut Bencher) {
let p1 = constants::BASEPOINT.to_projective();
let p1 = constants::ED25519_BASEPOINT.to_projective();
b.iter(|| p1.double() );
}
#[bench]
fn extended_double_output_extended(b: &mut Bencher) {
let p1 = constants::BASEPOINT;
let p1 = constants::ED25519_BASEPOINT;
b.iter(|| p1.double() );
}
#[bench]
fn mult_by_cofactor(b: &mut Bencher) {
let p1 = constants::BASEPOINT;
let p1 = constants::ED25519_BASEPOINT;
b.iter(|| p1.mult_by_cofactor() );
}