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::ExtendedPoint;
use curve::AffineNielsPoint; use curve::AffineNielsPoint;
use curve::CompressedEdwardsY; use curve::CompressedEdwardsY;
use curve::BasepointTable;
use scalar::Scalar; use scalar::Scalar;
pub const d: FieldElement = FieldElement([ pub const d: FieldElement = FieldElement([
@ -100,7 +101,7 @@ pub const BASE_CMPRSSD: CompressedEdwardsY =
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]); 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]);
/// Basepoint has y = 4/5. /// 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]), X: FieldElement([-14297830, -7645148, 16144683, -16471763, 27570974, -2696100, -26142465, 8378389, 20764389, 8758491]),
Y: FieldElement([-26843541, -6710886, 13421773, -13421773, 26843546, 6710886, -13421773, 13421773, -26843546, -6710886]), Y: FieldElement([-26843541, -6710886, 13421773, -13421773, 26843546, 6710886, -13421773, 13421773, -26843546, -6710886]),
Z: FieldElement([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 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`, /// The table is defined so `constants::base[i][j-1] = j*(16^2i)*B`,
/// for `0 ≤ i < 32`, `1 ≤ j < 9`. /// for `0 ≤ i < 32`, `1 ≤ j < 9`.
pub const base: [[AffineNielsPoint; 8]; 32] = [ pub const ED25519_BASEPOINT_TABLE: BasepointTable = BasepointTable([
[ [
AffineNielsPoint{ AffineNielsPoint{
y_plus_x: FieldElement([25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605]), 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]), 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]), xy2d: FieldElement([-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476]),
}, },
]]; ]]);
#[cfg(test)] #[cfg(test)]
mod test { mod test {
@ -1670,23 +1671,4 @@ mod test {
let a_minus_d = &a - &constants::d; let a_minus_d = &a - &constants::d;
assert_eq!(a_minus_d, constants::a_minus_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 { impl BasepointMult<Scalar> for ExtendedPoint {
fn basepoint() -> ExtendedPoint { fn basepoint() -> ExtendedPoint {
constants::BASEPOINT constants::ED25519_BASEPOINT
} }
/// Construct an `ExtendedPoint` from a `Scalar`, `scalar`, by fn basepoint_mult(scalar: &Scalar) -> ExtendedPoint {
/// computing the multiple `aB` of the basepoint `B`. constants::ED25519_BASEPOINT_TABLE.basepoint_mult(scalar)
///
/// 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
} }
} }
@ -1222,7 +1181,7 @@ mod test {
/// Test Montgomery conversion against the X25519 basepoint. /// Test Montgomery conversion against the X25519 basepoint.
#[test] #[test]
fn basepoint_to_montgomery() { fn basepoint_to_montgomery() {
assert_eq!(constants::BASEPOINT.compress_montgomery().unwrap(), assert_eq!(constants::ED25519_BASEPOINT.compress_montgomery().unwrap(),
BASE_CMPRSSD_MONTY); BASE_CMPRSSD_MONTY);
} }
@ -1275,10 +1234,10 @@ mod test {
.decompress().unwrap(); .decompress().unwrap();
// Test projective coordinates exactly since we know they should // Test projective coordinates exactly since we know they should
// only differ by a flipped sign. // only differ by a flipped sign.
assert_eq!(minus_basepoint.X, -(&constants::BASEPOINT.X)); assert_eq!(minus_basepoint.X, -(&constants::ED25519_BASEPOINT.X));
assert_eq!(minus_basepoint.Y, constants::BASEPOINT.Y); assert_eq!(minus_basepoint.Y, constants::ED25519_BASEPOINT.Y);
assert_eq!(minus_basepoint.Z, constants::BASEPOINT.Z); assert_eq!(minus_basepoint.Z, constants::ED25519_BASEPOINT.Z);
assert_eq!(minus_basepoint.T, -(&constants::BASEPOINT.T)); assert_eq!(minus_basepoint.T, -(&constants::ED25519_BASEPOINT.T));
} }
/// Test that computing 1*basepoint gives the correct basepoint. /// Test that computing 1*basepoint gives the correct basepoint.
@ -1293,7 +1252,7 @@ mod test {
/// using basepoint + basepoint versus the 2*basepoint constant. /// using basepoint + basepoint versus the 2*basepoint constant.
#[test] #[test]
fn basepoint_plus_basepoint_vs_basepoint2() { fn basepoint_plus_basepoint_vs_basepoint2() {
let bp = constants::BASEPOINT; let bp = constants::ED25519_BASEPOINT;
let bp_added = &bp + &bp; let bp_added = &bp + &bp;
assert_eq!(bp_added.compress_edwards(), BASE2_CMPRSSD); assert_eq!(bp_added.compress_edwards(), BASE2_CMPRSSD);
} }
@ -1302,7 +1261,7 @@ mod test {
/// using the basepoint, basepoint2 constants /// using the basepoint, basepoint2 constants
#[test] #[test]
fn basepoint_plus_basepoint_projective_niels_vs_basepoint2() { 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(); let bp_added = (&bp + &bp.to_projective_niels()).to_extended();
assert_eq!(bp_added.compress_edwards(), BASE2_CMPRSSD); assert_eq!(bp_added.compress_edwards(), BASE2_CMPRSSD);
} }
@ -1311,7 +1270,7 @@ mod test {
/// using the basepoint, basepoint2 constants /// using the basepoint, basepoint2 constants
#[test] #[test]
fn basepoint_plus_basepoint_affine_niels_vs_basepoint2() { 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_affine_niels = bp.to_affine_niels();
let bp_added = (&bp + &bp_affine_niels).to_extended(); let bp_added = (&bp + &bp_affine_niels).to_extended();
assert_eq!(bp_added.compress_edwards(), BASE2_CMPRSSD); assert_eq!(bp_added.compress_edwards(), BASE2_CMPRSSD);
@ -1360,16 +1319,17 @@ mod test {
/// Test precomputed basepoint mult /// Test precomputed basepoint mult
#[test] #[test]
fn test_precomputed_basepoint_mult() { 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_1 = ExtendedPoint::basepoint_mult(&A_SCALAR);
let aB_2 = table.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 scalar_mult versus a known scalar multiple from ed25519.py
#[test] #[test]
fn scalar_mult_vs_ed25519py() { 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); assert_eq!(aB.compress_edwards(), A_TIMES_BASEPOINT);
} }
@ -1384,7 +1344,7 @@ mod test {
/// Test basepoint.double() versus the 2*basepoint constant. /// Test basepoint.double() versus the 2*basepoint constant.
#[test] #[test]
fn basepoint_double_vs_basepoint2() { fn basepoint_double_vs_basepoint2() {
assert_eq!(constants::BASEPOINT.double().compress_edwards(), assert_eq!(constants::ED25519_BASEPOINT.double().compress_edwards(),
BASE2_CMPRSSD); BASE2_CMPRSSD);
} }
@ -1399,14 +1359,15 @@ mod test {
/// Check that converting to projective and then back to extended round-trips. /// Check that converting to projective and then back to extended round-trips.
#[test] #[test]
fn basepoint_projective_extended_round_trip() { 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); constants::BASE_CMPRSSD);
} }
/// Test computing 16*basepoint vs mult_by_pow_2(4) /// Test computing 16*basepoint vs mult_by_pow_2(4)
#[test] #[test]
fn basepoint16_vs_mult_by_pow_2_4() { 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); assert_eq!(bp16.compress_edwards(), BASE16_CMPRSSD);
} }
@ -1415,7 +1376,7 @@ mod test {
fn conditional_assign_for_affine_niels_point() { fn conditional_assign_for_affine_niels_point() {
let id = AffineNielsPoint::identity(); let id = AffineNielsPoint::identity();
let mut p1 = 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); p1.conditional_assign(&bp, 0);
assert_eq!(p1, id); assert_eq!(p1, id);
@ -1426,7 +1387,7 @@ mod test {
#[test] #[test]
fn is_small_order() { fn is_small_order() {
// The basepoint has large prime 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. // constants::EIGHT_TORSION has all points of small order.
for torsion_point in &constants::EIGHT_TORSION { for torsion_point in &constants::EIGHT_TORSION {
assert!(torsion_point.is_small_order() == true); assert!(torsion_point.is_small_order() == true);
@ -1441,8 +1402,8 @@ mod test {
#[test] #[test]
fn is_identity() { fn is_identity() {
assert!(ExtendedPoint::identity().is_identity() == true); assert!( ExtendedPoint::identity().is_identity() == true);
assert!( constants::BASEPOINT.is_identity() == false); assert!(constants::ED25519_BASEPOINT.is_identity() == false);
} }
} }
@ -1464,13 +1425,13 @@ mod bench {
#[bench] #[bench]
fn scalar_mult(b: &mut Bencher) { fn scalar_mult(b: &mut Bencher) {
let bp = constants::BASEPOINT; let bp = constants::ED25519_BASEPOINT;
b.iter(|| bp.scalar_mult(&A_SCALAR)); b.iter(|| bp.scalar_mult(&A_SCALAR));
} }
#[bench] #[bench]
fn bench_select_precomputed_point(b: &mut Bencher) { 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] #[bench]
@ -1481,53 +1442,53 @@ mod bench {
#[bench] #[bench]
fn add_extended_and_cached_output_completed(b: &mut Bencher) { fn add_extended_and_cached_output_completed(b: &mut Bencher) {
let p1 = constants::BASEPOINT; let p1 = constants::ED25519_BASEPOINT;
let p2 = constants::BASEPOINT.to_projective_niels(); let p2 = constants::ED25519_BASEPOINT.to_projective_niels();
b.iter(|| &p1 + &p2); b.iter(|| &p1 + &p2);
} }
#[bench] #[bench]
fn add_extended_and_cached_output_extended(b: &mut Bencher) { fn add_extended_and_cached_output_extended(b: &mut Bencher) {
let p1 = constants::BASEPOINT; let p1 = constants::ED25519_BASEPOINT;
let p2 = constants::BASEPOINT.to_projective_niels(); let p2 = constants::ED25519_BASEPOINT.to_projective_niels();
b.iter(|| (&p1 + &p2).to_extended()); b.iter(|| (&p1 + &p2).to_extended());
} }
#[bench] #[bench]
fn add_extended_and_precomputed_output_completed(b: &mut Bencher) { fn add_extended_and_precomputed_output_completed(b: &mut Bencher) {
let p1 = constants::BASEPOINT; let p1 = constants::ED25519_BASEPOINT;
let p2 = select_precomputed_point(6, &constants::base[27]); let p2 = constants::ED25519_BASEPOINT.to_affine_niels();
b.iter(|| &p1 + &p2); b.iter(|| &p1 + &p2);
} }
#[bench] #[bench]
fn add_extended_and_precomputed_output_extended(b: &mut Bencher) { fn add_extended_and_precomputed_output_extended(b: &mut Bencher) {
let p1 = constants::BASEPOINT; let p1 = constants::ED25519_BASEPOINT;
let p2 = select_precomputed_point(6, &constants::base[27]); let p2 = constants::ED25519_BASEPOINT.to_affine_niels();
b.iter(|| (&p1 + &p2).to_extended()); b.iter(|| (&p1 + &p2).to_extended());
} }
#[bench] #[bench]
fn projective_double_output_completed(b: &mut Bencher) { 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() ); b.iter(|| p1.double() );
} }
#[bench] #[bench]
fn extended_double_output_extended(b: &mut Bencher) { fn extended_double_output_extended(b: &mut Bencher) {
let p1 = constants::BASEPOINT; let p1 = constants::ED25519_BASEPOINT;
b.iter(|| p1.double() ); b.iter(|| p1.double() );
} }
#[bench] #[bench]
fn mult_by_cofactor(b: &mut Bencher) { fn mult_by_cofactor(b: &mut Bencher) {
let p1 = constants::BASEPOINT; let p1 = constants::ED25519_BASEPOINT;
b.iter(|| p1.mult_by_cofactor() ); b.iter(|| p1.mult_by_cofactor() );
} }