2017-01-08 19:39:25 +00:00
|
|
|
|
// -*- mode: rust; -*-
|
|
|
|
|
|
//
|
2017-08-15 05:09:20 +00:00
|
|
|
|
// This file is part of curve25519-dalek.
|
|
|
|
|
|
// Copyright (c) 2016-2017 Isis Lovecruft, Henry de Valence
|
|
|
|
|
|
// See LICENSE for licensing information.
|
2017-01-08 19:39:25 +00:00
|
|
|
|
//
|
|
|
|
|
|
// Authors:
|
|
|
|
|
|
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
|
|
|
|
|
|
// - Henry de Valence <hdevalence@hdevalence.ca>
|
|
|
|
|
|
|
|
|
|
|
|
//! This module contains various constants (such as curve parameters
|
|
|
|
|
|
//! and useful field elements like `sqrt(-1)`), as well as
|
|
|
|
|
|
//! lookup tables of pre-computed points.
|
|
|
|
|
|
|
|
|
|
|
|
#![allow(dead_code)]
|
2017-01-27 00:34:38 +00:00
|
|
|
|
#![allow(non_snake_case)]
|
2017-01-08 19:39:25 +00:00
|
|
|
|
#![allow(non_upper_case_globals)]
|
|
|
|
|
|
#![allow(missing_docs)]
|
2017-02-20 00:11:41 +00:00
|
|
|
|
#![allow(non_snake_case)]
|
2017-01-08 19:39:25 +00:00
|
|
|
|
|
2017-08-03 05:35:12 +00:00
|
|
|
|
use edwards::CompressedEdwardsY;
|
2017-04-26 01:52:45 +00:00
|
|
|
|
#[cfg(feature = "yolocrypto")]
|
2017-07-09 01:22:28 +00:00
|
|
|
|
use ristretto::{RistrettoPoint, RistrettoBasepointTable};
|
2017-09-07 20:31:06 +00:00
|
|
|
|
use montgomery::CompressedMontgomeryU;
|
2017-01-06 17:08:37 +00:00
|
|
|
|
use scalar::Scalar;
|
2017-01-08 19:39:25 +00:00
|
|
|
|
|
2017-03-13 06:18:31 +00:00
|
|
|
|
#[cfg(feature="radix_51")]
|
2017-07-30 21:35:12 +00:00
|
|
|
|
pub use constants_64bit::*;
|
2017-03-14 00:04:37 +00:00
|
|
|
|
#[cfg(not(feature="radix_51"))]
|
2017-07-30 21:35:12 +00:00
|
|
|
|
pub use constants_32bit::*;
|
2017-02-19 23:09:02 +00:00
|
|
|
|
|
2017-02-20 00:50:36 +00:00
|
|
|
|
/// (p-1)/2, in little-endian bytes.
|
|
|
|
|
|
pub const HALF_P_MINUS_1_BYTES: [u8; 32] =
|
|
|
|
|
|
[0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f];
|
|
|
|
|
|
|
2017-04-02 21:12:18 +00:00
|
|
|
|
/// `HALF_Q_MINUS_1_BYTES` is (2^255-20)/2 expressed in little endian form.
|
2017-01-08 19:39:25 +00:00
|
|
|
|
pub const HALF_Q_MINUS_1_BYTES: [u8; 32] = [ // halfQMinus1Bytes
|
2017-01-27 01:38:56 +00:00
|
|
|
|
0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
2017-01-08 19:39:25 +00:00
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, ];
|
|
|
|
|
|
|
2017-01-09 01:41:39 +00:00
|
|
|
|
/// Basepoint has y = 4/5.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Generated with Sage: these are the bytes of 4/5 in 𝔽_p. The
|
|
|
|
|
|
/// sign bit is 0 since the basepoint has x chosen to be positive.
|
2017-01-27 00:33:59 +00:00
|
|
|
|
pub const BASE_CMPRSSD: CompressedEdwardsY =
|
|
|
|
|
|
CompressedEdwardsY([0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
|
|
|
|
|
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
|
|
|
|
|
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
|
|
|
|
|
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]);
|
2017-01-09 01:41:39 +00:00
|
|
|
|
|
2017-09-07 20:31:06 +00:00
|
|
|
|
/// The X25519 basepoint, in compressed Montgomery form.
|
|
|
|
|
|
pub const BASE_COMPRESSED_MONTGOMERY: CompressedMontgomeryU =
|
|
|
|
|
|
CompressedMontgomeryU([0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-07-09 01:22:28 +00:00
|
|
|
|
/// The Ed25519 basepoint, as a `RistrettoPoint`. This is called `_POINT` to distinguish it from
|
2017-08-14 07:20:18 +00:00
|
|
|
|
/// `_TABLE`, which provides fast scalar multiplication.
|
2017-07-09 01:22:28 +00:00
|
|
|
|
#[cfg(feature = "yolocrypto")]
|
|
|
|
|
|
pub const RISTRETTO_BASEPOINT_POINT: RistrettoPoint = RistrettoPoint(ED25519_BASEPOINT_POINT);
|
2017-04-26 01:52:45 +00:00
|
|
|
|
|
2017-01-06 17:08:37 +00:00
|
|
|
|
/// `l` is the order of base point, i.e. 2^252 +
|
|
|
|
|
|
/// 27742317777372353535851937790883648493, in little-endian form
|
|
|
|
|
|
pub const l: Scalar = Scalar([ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
|
|
|
|
|
|
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 ]);
|
|
|
|
|
|
|
2017-04-29 05:54:00 +00:00
|
|
|
|
/// `l_minus_1` is the order of base point minus one, i.e. 2^252 +
|
2017-01-06 17:08:37 +00:00
|
|
|
|
/// 27742317777372353535851937790883648493 - 1, in little-endian form
|
2017-04-29 05:54:00 +00:00
|
|
|
|
pub const l_minus_1: Scalar = Scalar([ 0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
|
|
|
|
|
|
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 ]);
|
2017-04-29 05:59:56 +00:00
|
|
|
|
|
|
|
|
|
|
/// `lminus1` is the order of base point minus two, i.e. 2^252 +
|
|
|
|
|
|
/// 27742317777372353535851937790883648493 - 2, in little-endian form
|
|
|
|
|
|
pub const l_minus_2: Scalar = Scalar([ 0xeb, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
|
|
|
|
|
|
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 ]);
|
2017-04-29 05:54:00 +00:00
|
|
|
|
|
2017-04-26 01:52:45 +00:00
|
|
|
|
#[cfg(feature = "yolocrypto")]
|
2017-07-09 01:22:28 +00:00
|
|
|
|
/// The Ed25519 basepoint, as a RistrettoPoint
|
|
|
|
|
|
pub const RISTRETTO_BASEPOINT_TABLE: RistrettoBasepointTable
|
|
|
|
|
|
= RistrettoBasepointTable(ED25519_BASEPOINT_TABLE);
|
2017-04-26 01:52:45 +00:00
|
|
|
|
|
2017-01-08 19:51:00 +00:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod test {
|
|
|
|
|
|
use field::FieldElement;
|
2017-08-03 05:35:12 +00:00
|
|
|
|
use edwards::IsIdentity;
|
|
|
|
|
|
use edwards::ValidityCheck;
|
2017-01-08 19:51:00 +00:00
|
|
|
|
use constants;
|
|
|
|
|
|
|
2017-02-20 00:11:41 +00:00
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_eight_torsion() {
|
|
|
|
|
|
for i in 0..8 {
|
|
|
|
|
|
let Q = constants::EIGHT_TORSION[i].mult_by_pow_2(3);
|
|
|
|
|
|
assert!(Q.is_valid());
|
2017-02-21 23:11:24 +00:00
|
|
|
|
assert!(Q.is_identity());
|
2017-02-20 00:11:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_four_torsion() {
|
|
|
|
|
|
for i in (0..8).filter(|i| i % 2 == 0) {
|
|
|
|
|
|
let Q = constants::EIGHT_TORSION[i].mult_by_pow_2(2);
|
|
|
|
|
|
assert!(Q.is_valid());
|
2017-02-21 23:11:24 +00:00
|
|
|
|
assert!(Q.is_identity());
|
2017-02-20 00:11:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_two_torsion() {
|
|
|
|
|
|
for i in (0..8).filter(|i| i % 4 == 0) {
|
|
|
|
|
|
let Q = constants::EIGHT_TORSION[i].mult_by_pow_2(1);
|
|
|
|
|
|
assert!(Q.is_valid());
|
2017-02-21 23:11:24 +00:00
|
|
|
|
assert!(Q.is_identity());
|
2017-02-20 00:11:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-01-13 18:19:08 +00:00
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_half() {
|
2017-03-13 06:18:41 +00:00
|
|
|
|
let one = FieldElement::one();
|
|
|
|
|
|
let two = &one + &one;
|
2017-01-13 18:19:08 +00:00
|
|
|
|
assert_eq!(one, &two * &constants::HALF);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-03-13 06:18:41 +00:00
|
|
|
|
/// Test that the constant for sqrt(-486664) really is a square
|
|
|
|
|
|
/// root of -486664.
|
2017-03-07 08:03:59 +00:00
|
|
|
|
#[test]
|
2017-03-13 06:18:41 +00:00
|
|
|
|
#[cfg(feature="radix_51")]
|
|
|
|
|
|
fn sqrt_minus_aplus2() {
|
2017-07-30 21:35:12 +00:00
|
|
|
|
use field_64bit::FieldElement64;
|
|
|
|
|
|
let minus_aplus2 = -&FieldElement64([486664,0,0,0,0]);
|
2017-03-13 06:18:41 +00:00
|
|
|
|
let sqrt = constants::SQRT_MINUS_APLUS2;
|
|
|
|
|
|
let sq = &sqrt * &sqrt;
|
|
|
|
|
|
assert_eq!(sq, minus_aplus2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-03-07 08:03:59 +00:00
|
|
|
|
/// Test that the constant for sqrt(-486664) really is a square
|
|
|
|
|
|
/// root of -486664.
|
2017-03-13 06:18:41 +00:00
|
|
|
|
#[test]
|
2017-03-14 00:04:37 +00:00
|
|
|
|
#[cfg(not(feature="radix_51"))]
|
2017-03-07 08:03:59 +00:00
|
|
|
|
fn sqrt_minus_aplus2() {
|
2017-07-30 21:35:12 +00:00
|
|
|
|
use field_32bit::FieldElement32;
|
|
|
|
|
|
let minus_aplus2 = FieldElement32([-486664,0,0,0,0,0,0,0,0,0]);
|
2017-03-07 08:03:59 +00:00
|
|
|
|
let sqrt = constants::SQRT_MINUS_APLUS2;
|
|
|
|
|
|
let sq = &sqrt * &sqrt;
|
|
|
|
|
|
assert_eq!(sq, minus_aplus2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-01-08 19:51:00 +00:00
|
|
|
|
#[test]
|
2017-02-19 23:09:02 +00:00
|
|
|
|
/// Test that SQRT_M1 and MSQRT_M1 are square roots of -1
|
2017-01-08 19:51:00 +00:00
|
|
|
|
fn test_sqrt_minus_one() {
|
2017-03-13 06:18:41 +00:00
|
|
|
|
let minus_one = FieldElement::minus_one();
|
2017-01-08 19:51:00 +00:00
|
|
|
|
let sqrt_m1_sq = &constants::SQRT_M1 * &constants::SQRT_M1;
|
2017-02-19 23:09:02 +00:00
|
|
|
|
let msqrt_m1_sq = &constants::MSQRT_M1 * &constants::MSQRT_M1;
|
|
|
|
|
|
assert_eq!(minus_one, sqrt_m1_sq);
|
|
|
|
|
|
assert_eq!(minus_one, msqrt_m1_sq);
|
2017-01-08 19:51:00 +00:00
|
|
|
|
}
|
2017-01-08 19:56:52 +00:00
|
|
|
|
|
2017-02-20 01:00:19 +00:00
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_sqrt_constants_sign() {
|
2017-03-13 06:18:41 +00:00
|
|
|
|
let one = FieldElement::one();
|
|
|
|
|
|
let minus_one = FieldElement::minus_one();
|
2017-02-23 00:24:11 +00:00
|
|
|
|
let (was_nonzero_square, invsqrt_m1) = minus_one.invsqrt();
|
|
|
|
|
|
assert_eq!(was_nonzero_square, 1u8);
|
2017-02-20 01:00:19 +00:00
|
|
|
|
let sign_test_sqrt = &invsqrt_m1 * &constants::SQRT_M1;
|
|
|
|
|
|
let sign_test_msqrt = &invsqrt_m1 * &constants::MSQRT_M1;
|
|
|
|
|
|
// XXX it seems we have flipped the sign relative to
|
|
|
|
|
|
// the invsqrt function?
|
|
|
|
|
|
assert_eq!(sign_test_sqrt, minus_one);
|
|
|
|
|
|
assert_eq!(sign_test_msqrt, one);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-01-08 19:56:52 +00:00
|
|
|
|
/// Test that d = -121665/121666
|
2017-03-14 00:04:37 +00:00
|
|
|
|
#[cfg(not(feature="radix_51"))]
|
2017-03-13 06:18:41 +00:00
|
|
|
|
#[test]
|
2017-01-08 19:56:52 +00:00
|
|
|
|
fn test_d_vs_ratio() {
|
2017-07-30 21:35:12 +00:00
|
|
|
|
use field_32bit::FieldElement32;
|
|
|
|
|
|
let a = FieldElement32([-121665,0,0,0,0,0,0,0,0,0]);
|
|
|
|
|
|
let b = FieldElement32([ 121666,0,0,0,0,0,0,0,0,0]);
|
2017-01-08 19:56:52 +00:00
|
|
|
|
let d = &a * &b.invert();
|
|
|
|
|
|
let d2 = &d + &d;
|
|
|
|
|
|
assert_eq!(d, constants::d);
|
|
|
|
|
|
assert_eq!(d2, constants::d2);
|
|
|
|
|
|
}
|
2017-01-09 20:53:16 +00:00
|
|
|
|
|
2017-03-13 06:18:41 +00:00
|
|
|
|
/// Test that d = -121665/121666
|
|
|
|
|
|
#[cfg(feature="radix_51")]
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_d_vs_ratio() {
|
2017-07-30 21:35:12 +00:00
|
|
|
|
use field_64bit::FieldElement64;
|
|
|
|
|
|
let a = -&FieldElement64([121665,0,0,0,0]);
|
|
|
|
|
|
let b = FieldElement64([121666,0,0,0,0]);
|
2017-03-13 06:18:41 +00:00
|
|
|
|
let d = &a * &b.invert();
|
|
|
|
|
|
let d2 = &d + &d;
|
|
|
|
|
|
assert_eq!(d, constants::d);
|
|
|
|
|
|
assert_eq!(d2, constants::d2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-01-31 22:19:34 +00:00
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_d4() {
|
|
|
|
|
|
let mut four = FieldElement::zero();
|
2017-07-30 21:35:12 +00:00
|
|
|
|
// XXX should have a way to create small field elements
|
|
|
|
|
|
four.0[0] = 4;
|
2017-01-31 22:19:34 +00:00
|
|
|
|
assert_eq!(&constants::d * &four, constants::d4);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-10-03 20:27:08 +00:00
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_sqrt_ad_minus_one() {
|
|
|
|
|
|
let a = FieldElement::minus_one();
|
|
|
|
|
|
let ad_minus_one = &(&a * &constants::d) + &a;
|
|
|
|
|
|
let should_be_ad_minus_one = constants::sqrt_ad_minus_one.square();
|
|
|
|
|
|
assert_eq!(should_be_ad_minus_one, ad_minus_one);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-02-20 00:02:55 +00:00
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_a_minus_d() {
|
2017-03-13 06:18:41 +00:00
|
|
|
|
let a = FieldElement::minus_one();
|
2017-02-20 00:02:55 +00:00
|
|
|
|
let a_minus_d = &a - &constants::d;
|
|
|
|
|
|
assert_eq!(a_minus_d, constants::a_minus_d);
|
2017-05-20 23:17:14 +00:00
|
|
|
|
let (_, invsqrt_a_minus_d) = constants::a_minus_d.invsqrt();
|
|
|
|
|
|
assert_eq!(invsqrt_a_minus_d, constants::invsqrt_a_minus_d);
|
|
|
|
|
|
let inv_a_minus_d = invsqrt_a_minus_d.square();
|
|
|
|
|
|
assert_eq!(inv_a_minus_d, constants::inv_a_minus_d);
|
|
|
|
|
|
assert_eq!(&inv_a_minus_d * &a_minus_d, FieldElement::one());
|
2017-02-20 00:02:55 +00:00
|
|
|
|
}
|
2017-01-08 19:51:00 +00:00
|
|
|
|
}
|