1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
// -*- mode: rust; -*-
//
// This file is part of curve25519-dalek.
// Copyright (c) 2016-2017 Isis Lovecruft, Henry de Valence
// See LICENSE for licensing information.
//
// 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)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(missing_docs)]
#![allow(non_snake_case)]

use edwards::CompressedEdwardsY;
#[cfg(feature = "yolocrypto")]
use decaf::{DecafPoint, DecafBasepointTable};
use scalar::Scalar;

#[cfg(feature="radix_51")]
pub use constants_64bit::*;
#[cfg(not(feature="radix_51"))]
pub use constants_32bit::*;

/// (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];

/// `HALF_Q_MINUS_1_BYTES` is (2^255-20)/2 expressed in little endian form.
pub const HALF_Q_MINUS_1_BYTES: [u8; 32] = [ // halfQMinus1Bytes
    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, ];

/// 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.
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]);

/// The Ed25519 basepoint, as a `DecafPoint`.  This is called `_POINT` to distinguish it from
/// `_TABLE`, which provides fast scalar multiplication.
#[cfg(feature = "yolocrypto")] pub const DECAF_ED25519_BASEPOINT_POINT: DecafPoint =
DecafPoint(ED25519_BASEPOINT_POINT);

/// `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 ]);

/// `l_minus_1` is the order of base point minus one, i.e. 2^252 +
/// 27742317777372353535851937790883648493 - 1, in little-endian form
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 ]);

/// `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 ]);

#[cfg(feature = "yolocrypto")]
/// The Ed25519 basepoint
pub const DECAF_ED25519_BASEPOINT_TABLE: DecafBasepointTable
    = DecafBasepointTable(ED25519_BASEPOINT_TABLE);

#[cfg(test)]
mod test {
    use field::FieldElement;
    use edwards::IsIdentity;
    use edwards::ValidityCheck;
    use constants;

    #[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());
            assert!(Q.is_identity());
        }
    }

    #[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());
            assert!(Q.is_identity());
        }
    }

    #[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());
            assert!(Q.is_identity());
        }
    }

    #[test]
    fn test_half() {
        let one = FieldElement::one();
        let two = &one + &one;
        assert_eq!(one, &two * &constants::HALF);
    }

    /// Test that the constant for sqrt(-486664) really is a square
    /// root of -486664.
    #[test]
    #[cfg(feature="radix_51")]
    fn sqrt_minus_aplus2() {
        use field_64bit::FieldElement64;
        let minus_aplus2 = -&FieldElement64([486664,0,0,0,0]);
        let sqrt = constants::SQRT_MINUS_APLUS2;
        let sq = &sqrt * &sqrt;
        assert_eq!(sq, minus_aplus2);
    }

    /// Test that the constant for sqrt(-486664) really is a square
    /// root of -486664.
    #[test]
    #[cfg(not(feature="radix_51"))]
    fn sqrt_minus_aplus2() {
        use field_32bit::FieldElement32;
        let minus_aplus2 = FieldElement32([-486664,0,0,0,0,0,0,0,0,0]);
        let sqrt = constants::SQRT_MINUS_APLUS2;
        let sq = &sqrt * &sqrt;
        assert_eq!(sq, minus_aplus2);
    }

    #[test]
    /// Test that SQRT_M1 and MSQRT_M1 are square roots of -1
    fn test_sqrt_minus_one() {
        let minus_one = FieldElement::minus_one();
        let sqrt_m1_sq = &constants::SQRT_M1 * &constants::SQRT_M1;
        let msqrt_m1_sq = &constants::MSQRT_M1 * &constants::MSQRT_M1;
        assert_eq!(minus_one,  sqrt_m1_sq);
        assert_eq!(minus_one, msqrt_m1_sq);
    }

    #[test]
    fn test_sqrt_constants_sign() {
        let one       = FieldElement::one();
        let minus_one = FieldElement::minus_one();
        let (was_nonzero_square, invsqrt_m1) = minus_one.invsqrt();
        assert_eq!(was_nonzero_square, 1u8);
        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);
    }

    /// Test that d = -121665/121666
    #[cfg(not(feature="radix_51"))]
    #[test]
    fn test_d_vs_ratio() {
        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]);
        let d = &a * &b.invert();
        let d2 = &d + &d;
        assert_eq!(d, constants::d);
        assert_eq!(d2, constants::d2);
    }

    /// Test that d = -121665/121666
    #[cfg(feature="radix_51")]
    #[test]
    fn test_d_vs_ratio() {
        use field_64bit::FieldElement64;
        let a = -&FieldElement64([121665,0,0,0,0]);
        let b =   FieldElement64([121666,0,0,0,0]);
        let d = &a * &b.invert();
        let d2 = &d + &d;
        assert_eq!(d, constants::d);
        assert_eq!(d2, constants::d2);
    }

    #[test]
    fn test_d4() {
        let mut four = FieldElement::zero();
        // XXX should have a way to create small field elements
        four.0[0] = 4;
        assert_eq!(&constants::d * &four, constants::d4);
    }

    #[test]
    fn test_a_minus_d() {
        let a = FieldElement::minus_one();
        let a_minus_d = &a - &constants::d;
        assert_eq!(a_minus_d, constants::a_minus_d);
        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());
    }
}