Initial commit.

This commit is contained in:
Isis Lovecruft 2016-12-08 05:12:00 +00:00
commit 387a56fe2c
Failed to extract signature
9 changed files with 4406 additions and 0 deletions

11
.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
target
Cargo.lock
*~
\#*
.\#*
*.swp
*.orig
*.bak
*.s

69
Cargo.toml Normal file
View file

@ -0,0 +1,69 @@
[package]
name = "curve25519-dalek"
version = "0.1.0"
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>",
"Henry de Valence <hdevalence@hdevalence.ca>"]
readme = "README.md"
license-file = "LICENSE"
repository = "https://code.ciph.re/isis/curve25519-dalek"
homepage = "https://code.ciph.re/isis/curve25519-dalek"
documentation = "https://docs.rs/curve25519-dalek"
keywords = ["cryptography", "curve25519", "elliptic", "curve", "ECC"]
description = "A low-level cryptographic library for point, group, field, and scalar operations on a curve isomorphic to the twisted Edwards curve defined by x²+y² = 121665/121666 x²y² over GF(2²⁵⁵ - 19)."
exclude = [
".gitignore"
]
[dependencies]
arrayref = "0.3.2"
# The development profile, used for `cargo build`.
[profile.dev]
opt-level = 0 # controls the `--opt-level` the compiler builds with
debug = true # controls whether the compiler passes `-g`
rpath = false # controls whether the compiler passes `-C rpath`
lto = false # controls `-C lto` for binaries and staticlibs
debug-assertions = true # controls whether debug assertions are enabled
codegen-units = 1 # controls whether the compiler passes `-C codegen-units`
# `codegen-units` is ignored when `lto = true`
panic = 'unwind' # panic strategy (`-C panic=...`), can also be 'abort'
# The release profile, used for `cargo build --release`.
[profile.release]
opt-level = 3
debug = false
rpath = false
lto = false
debug-assertions = false
codegen-units = 1
panic = 'unwind'
# The testing profile, used for `cargo test`.
[profile.test]
opt-level = 0
debug = true
rpath = false
lto = false
debug-assertions = true
codegen-units = 1
panic = 'unwind'
# The benchmarking profile, used for `cargo bench`.
[profile.bench]
opt-level = 3
debug = false
rpath = false
lto = false
debug-assertions = false
codegen-units = 1
panic = 'unwind'
# The documentation profile, used for `cargo doc`.
[profile.doc]
opt-level = 0
debug = true
rpath = false
lto = false
debug-assertions = true
codegen-units = 1
panic = 'unwind'

129
LICENSE Normal file
View file

@ -0,0 +1,129 @@
To the extent possible under law, the author(s) have waived all copyright and related or
neighboring rights to curve25519-dalek, using the Creative Commons "CC0" public domain dedication.
Creative Commons CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL
SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT
RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS"
BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT
OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR
DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator and
subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the
purpose of contributing to a commons of creative, cultural and scientific
works ("Commons") that the public can reliably and without fear of later
claims of infringement build upon, modify, incorporate in other works, reuse
and redistribute as freely as possible in any form whatsoever and for any
purposes, including without limitation commercial purposes. These owners may
contribute to the Commons to promote the ideal of a free culture and the
further production of creative, cultural and scientific works, or to gain
reputation or greater distribution for their Work in part through the use and
efforts of others.
For these and/or other purposes and motivations, and without any expectation
of additional consideration or compensation, the person associating CC0 with a
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
and publicly distribute the Work under its terms, with knowledge of his or her
Copyright and Related Rights in the Work and the meaning and intended legal
effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not limited
to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation thereof,
including any amended or successor version of such directive); and
vii. other similar, equivalent or corresponding rights throughout the world
based on applicable law or treaty, and any national implementations
thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention of,
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
and Related Rights and associated claims and causes of action, whether now
known or unknown (including existing as well as future claims and causes of
action), in the Work (i) in all territories worldwide, (ii) for the maximum
duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number of
copies, and (iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
the Waiver for the benefit of each member of the public at large and to the
detriment of Affirmer's heirs and successors, fully intending that such Waiver
shall not be subject to revocation, rescission, cancellation, termination, or
any other legal or equitable action to disrupt the quiet enjoyment of the Work
by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be
judged legally invalid or ineffective under applicable law, then the Waiver
shall be preserved to the maximum extent permitted taking into account
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
is so judged Affirmer hereby grants to each affected person a royalty-free,
non transferable, non sublicensable, non exclusive, irrevocable and
unconditional license to exercise Affirmer's Copyright and Related Rights in
the Work (i) in all territories worldwide, (ii) for the maximum duration
provided by applicable law or treaty (including future time extensions), (iii)
in any current or future medium and for any number of copies, and (iv) for any
purpose whatsoever, including without limitation commercial, advertising or
promotional purposes (the "License"). The License shall be deemed effective as
of the date CC0 was applied by Affirmer to the Work. Should any part of the
License for any reason be judged legally invalid or ineffective under
applicable law, such partial invalidity or ineffectiveness shall not
invalidate the remainder of the License, and in such case Affirmer hereby
affirms that he or she will not (i) exercise any of his or her remaining
Copyright and Related Rights in the Work or (ii) assert any associated claims
and causes of action with respect to the Work, in either case contrary to
Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied, statutory
or otherwise, including without limitation warranties of title,
merchantability, fitness for a particular purpose, non infringement, or
the absence of latent or other defects, accuracy, or the present or
absence of errors, whether or not discoverable, all to the greatest
extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the
Work. Further, Affirmer disclaims responsibility for obtaining any
necessary consents, permissions or other rights required for any use of
the Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

28
README.md Normal file
View file

@ -0,0 +1,28 @@
# curve25519-dalek [](https://docs.rs/curve25519-dalek/badge.svg)
*A low-level cryptographic library for point, group, field, and scalar
operations on a curve isomorphic to the twisted Edwards curve defined by x²+y²
= 121665/121666 x²y² over GF(2²⁵⁵ - 19).*
*SPOILER ALERT:* **The Twelfth Doctor's first encounter with the Daleks is in
his second full episode, "Into the Dalek". A beleaguered ship of the "Combined
Galactic Resistance" has discovered a broken Dalek that has turned "good",
desiring to kill all other Daleks. The Doctor, Clara and a team of soldiers
are miniaturized and enter the Dalek, which the Doctor names Rusty. They
repair the damage, but accidentally restore it to its original nature, causing
it to go on the rampage and alert the Dalek fleet to the whereabouts of the
rebel ship. However, the Doctor manages to return Rusty to its previous state
by linking his mind with the Dalek's: Rusty shares the Doctor's view of the
universe's beauty, but also his deep hatred of the Daleks. Rusty destroys the
other Daleks and departs the ship, determined to track down and bring an end
to the Dalek race.**
Significant portions of this code are ported from
[Adam Langley's Golang ed25519 library](https://github.com/agl/ed25519), along
with referencing the ref10 implementation.
## TODO
* Implement hashing to a point on the curve.
* Maybe implement Mike Hamburg's Decaf point compression format.

1121
src/curve.rs Normal file

File diff suppressed because it is too large Load diff

972
src/field.rs Normal file
View file

@ -0,0 +1,972 @@
// -*- mode: rust; coding: utf-8; -*-
//
// To the extent possible under law, the authors have waived all
// copyright and related or neighboring rights to curve25519-dalek,
// using the Creative Commons "CC0" public domain dedication. See
// <http://creativecommons.org/publicdomain/zero/.0/> for full
// details.
//
// Authors:
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
// - Henry de Valence <hdevalence@hdevalence.ca>
//! Field arithmetic for /(2²⁵⁵-19).
//!
//! Based on Adam Langley's curve25519-donna and (Golang) ed25519
//! implementations.
use std::clone::Clone;
use std::fmt::Debug;
use std::ops::{Add, AddAssign};
use std::ops::{Sub, SubAssign};
use std::ops::{Mul, MulAssign};
use std::ops::{Index, IndexMut};
use std::cmp::{Eq, PartialEq};
use std::ops::Neg;
use util::byte_is_nonzero;
/// FieldElements are represented as an array of ten "Limbs", which are radix
/// 25.5, that is, each Limb of a FieldElement alternates between being
/// represented as a factor of 2^25 or 2^26 more than the last corresponding
/// integer.
pub type Limb = i32;
/// FieldElement represents an element of the field GF(2^255 - 19). An element
/// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
/// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
/// context.
#[derive(Copy, Clone)]
pub struct FieldElement(pub [Limb; 10]);
impl PartialEq for FieldElement {
/// Test equality between two FieldElements by converting them to bytes.
///
/// # Warning
///
/// This comparison is *not* constant time. It could easily be
/// made to be, but the main use of an `Eq` implementation is for
/// branching, so it seems pointless.
///
/// XXX it would be good to encode constant-time considerations
/// (no data flow from secret information) into Rust's type
/// system.
fn eq(&self, other: &FieldElement) -> bool {
let self_bytes = self.to_bytes();
let other_bytes = other.to_bytes();
let mut are_equal: bool = true;
for i in 0..32 {
are_equal &= self_bytes[i] == other_bytes[i];
}
return are_equal;
}
}
impl Eq for FieldElement {}
impl Debug for FieldElement {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "FieldElement: {:?}", &self.0[..])
}
}
impl Index<usize> for FieldElement {
type Output = Limb;
fn index<'a>(&'a self, _index: usize) -> &'a Limb {
let ret: &'a Limb = &(self.0[_index]);
ret
}
}
impl IndexMut<usize> for FieldElement {
fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut Limb {
let ret: &'a mut Limb = &mut(self.0[_index]);
ret
}
}
impl<'b> AddAssign<&'b FieldElement> for FieldElement {
fn add_assign(&mut self, _rhs: &'b FieldElement) { // fsum()
for i in 0..10 {
self[i] += _rhs[i];
}
}
}
impl<'a, 'b> Add<&'b FieldElement> for &'a FieldElement {
type Output = FieldElement;
fn add(self, _rhs: &'b FieldElement) -> FieldElement {
let mut output = self.clone();
output += _rhs;
output
}
}
impl<'b> SubAssign<&'b FieldElement> for FieldElement {
fn sub_assign(&mut self, _rhs: &'b FieldElement) { // fdifference()
for i in 0..10 {
self[i] -= _rhs[i];
}
}
}
impl<'a, 'b> Sub<&'b FieldElement> for &'a FieldElement {
type Output = FieldElement;
fn sub(self, _rhs: &'b FieldElement) -> FieldElement {
let mut output = self.clone();
output -= _rhs;
output
}
}
impl<'b> MulAssign<&'b FieldElement> for FieldElement {
fn mul_assign(&mut self, _rhs: &'b FieldElement) {
self.0 = self.multiply(_rhs).0;
}
}
impl<'a, 'b> Mul<&'b FieldElement> for &'a FieldElement {
type Output = FieldElement;
fn mul(self, _rhs: &'b FieldElement) -> FieldElement {
self.multiply(_rhs)
}
}
impl<'a> Neg for &'a FieldElement {
type Output = FieldElement;
fn neg(self) -> FieldElement {
let mut output = self.clone();
output.negate();
output
}
}
/// Convert an array of (at least) three bytes into an i64.
#[inline]
#[allow(dead_code)]
pub fn load3(input: &[u8]) -> i64 {
(input[0] as i64)
| ((input[1] as i64) << 8)
| ((input[2] as i64) << 16)
}
/// Convert an array of (at least) four bytes into an i64.
#[inline]
#[allow(dead_code)]
pub fn load4(input: &[u8]) -> i64 {
(input[0] as i64)
| ((input[1] as i64) << 8)
| ((input[2] as i64) << 16)
| ((input[3] as i64) << 24)
}
impl FieldElement {
/// Invert the sign of this field element
pub fn negate(&mut self) {
for i in 0..10 {
self[i] = -self[i];
}
}
/// Construct the additive identity
pub fn zero() -> FieldElement {
FieldElement([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ])
}
/// Construct the multiplicative identity
pub fn one() -> FieldElement {
FieldElement([ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ])
}
/// Overwrite this FieldElement with one of the inputs without branching.
/// Like `conditional_assign`, but chooses between two inputs instead of
/// one input and the original value.
///
/// If `choice == 0`, replace `self` with `f`:
///
/// ```
/// # use curve25519_dalek::field::FieldElement;
/// let f = FieldElement([1,1,1,1,1,1,1,1,1,1]);
/// let g = FieldElement([2,2,2,2,2,2,2,2,2,2]);
/// let mut h = FieldElement([0,0,0,0,0,0,0,0,0,0]);
/// h.conditional_choose(&f, &g, 0);
/// assert!(h == f);
/// ```
///
/// If `choice == 1`, replace `self` with `g`:
///
/// ```
/// # use curve25519_dalek::field::FieldElement;
/// # let f = FieldElement([1,1,1,1,1,1,1,1,1,1]);
/// # let g = FieldElement([2,2,2,2,2,2,2,2,2,2]);
/// # let mut h = FieldElement([0,0,0,0,0,0,0,0,0,0]);
/// h.conditional_choose(&f, &g, 1);
/// assert!(h == g);
/// ```
///
/// # Preconditions
///
/// * `b` in {0,1}
pub fn conditional_choose(&mut self,
f: &FieldElement,
g: &FieldElement,
choice: u8)
{
let mask = -(choice as Limb);
for i in 0..10 {
self[i] = f[i] ^ (mask & (f[i] ^ g[i]));
}
}
/// Conditionally assign the Limbs of another FieldElement to this
/// one. Like `conditional_choose`, but choosing between one
/// input and the original value.
///
/// If `choice == 0`, replace `self` with `self`:
///
/// ```
/// # use curve25519_dalek::field::FieldElement;
/// let f = FieldElement([1,1,1,1,1,1,1,1,1,1]);
/// let g = FieldElement([2,2,2,2,2,2,2,2,2,2]);
/// let mut h = FieldElement([1,1,1,1,1,1,1,1,1,1]);
/// h.conditional_assign(&g, 0);
/// assert!(h == f);
/// ```
///
/// If `choice == 1`, replace `self` with `f`:
///
/// ```
/// # use curve25519_dalek::field::FieldElement;
/// # let f = FieldElement([1,1,1,1,1,1,1,1,1,1]);
/// # let g = FieldElement([2,2,2,2,2,2,2,2,2,2]);
/// # let mut h = FieldElement([1,1,1,1,1,1,1,1,1,1]);
/// h.conditional_assign(&g, 1);
/// assert!(h == g);
/// ```
///
/// # Preconditions
///
/// * `choice` in {0,1}
pub fn conditional_assign(&mut self, f: &FieldElement, choice: u8) {
let mask = -(choice as Limb);
for i in 0..10 {
self[i] ^= mask & (self[i] ^ f[i]);
}
}
fn combine_coeffs(input: &[i64;10]) -> FieldElement { //FeCombine
let mut c = [0i64;10];
let mut h = input.clone();
/*
|h[0]| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
i.e. |h[0]| <= 1.2*2^59; narrower ranges for h[2], h[4], h[6], h[8]
|h[1]| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
i.e. |h[1]| <= 1.5*2^58; narrower ranges for h[3], h[5], h[7], h[9]
*/
c[0] = (h[0] + (1 << 25)) >> 26;
h[1] += c[0];
h[0] -= c[0] << 26;
c[4] = (h[4] + (1 << 25)) >> 26;
h[5] += c[4];
h[4] -= c[4] << 26;
/* |h[0]| <= 2^25 */
/* |h[4]| <= 2^25 */
/* |h[1]| <= 1.51*2^58 */
/* |h[5]| <= 1.51*2^58 */
c[1] = (h[1] + (1 << 24)) >> 25;
h[2] += c[1];
h[1] -= c[1] << 25;
c[5] = (h[5] + (1 << 24)) >> 25;
h[6] += c[5];
h[5] -= c[5] << 25;
/* |h[1]| <= 2^24; from now on fits into int32 */
/* |h[5]| <= 2^24; from now on fits into int32 */
/* |h[2]| <= 1.21*2^59 */
/* |h[6]| <= 1.21*2^59 */
c[2] = (h[2] + (1 << 25)) >> 26;
h[3] += c[2];
h[2] -= c[2] << 26;
c[6] = (h[6] + (1 << 25)) >> 26;
h[7] += c[6];
h[6] -= c[6] << 26;
/* |h[2]| <= 2^25; from now on fits into int32 unchanged */
/* |h[6]| <= 2^25; from now on fits into int32 unchanged */
/* |h[3]| <= 1.51*2^58 */
/* |h[7]| <= 1.51*2^58 */
c[3] = (h[3] + (1 << 24)) >> 25;
h[4] += c[3];
h[3] -= c[3] << 25;
c[7] = (h[7] + (1 << 24)) >> 25;
h[8] += c[7];
h[7] -= c[7] << 25;
/* |h[3]| <= 2^24; from now on fits into int32 unchanged */
/* |h[7]| <= 2^24; from now on fits into int32 unchanged */
/* |h[4]| <= 1.52*2^33 */
/* |h[8]| <= 1.52*2^33 */
c[4] = (h[4] + (1 << 25)) >> 26;
h[5] += c[4];
h[4] -= c[4] << 26;
c[8] = (h[8] + (1 << 25)) >> 26;
h[9] += c[8];
h[8] -= c[8] << 26;
/* |h[4]| <= 2^25; from now on fits into int32 unchanged */
/* |h[8]| <= 2^25; from now on fits into int32 unchanged */
/* |h[5]| <= 1.01*2^24 */
/* |h[9]| <= 1.51*2^58 */
c[9] = (h[9] + (1 << 24)) >> 25;
h[0] += c[9] * 19;
h[9] -= c[9] << 25;
/* |h[9]| <= 2^24; from now on fits into int32 unchanged */
/* |h[0]| <= 1.8*2^37 */
c[0] = (h[0] + (1 << 25)) >> 26;
h[1] += c[0];
h[0] -= c[0] << 26;
/* |h[0]| <= 2^25; from now on fits into int32 unchanged */
/* |h[1]| <= 1.01*2^24 */
let mut output = FieldElement([0i32;10]);
output[0] = h[0] as i32;
output[1] = h[1] as i32;
output[2] = h[2] as i32;
output[3] = h[3] as i32;
output[4] = h[4] as i32;
output[5] = h[5] as i32;
output[6] = h[6] as i32;
output[7] = h[7] as i32;
output[8] = h[8] as i32;
output[9] = h[9] as i32;
output
}
/// Create a FieldElement by demarshalling an array of 32 bytes.
///
/// # Example
///
/// ```
/// # use curve25519_dalek::field::FieldElement;
/// let data: [u8; 32] = [ 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 ];
/// let fe: FieldElement = FieldElement::from_bytes(&data);
/// assert_eq!(fe,
/// FieldElement([ 197121, -4095679, 21045505, 6840408, 4209720,
/// 1249809, -7665014, -12377341, 30523826, 8420472]))
/// ```
///
/// # Return
///
/// Returns a new FieldElement.
pub fn from_bytes(data: &[u8;32]) -> FieldElement { //FeFromBytes
let mut h = [0i64;10];
h[0] = load4(&data[ 0..]);
h[1] = load3(&data[ 4..]) << 6;
h[2] = load3(&data[ 7..]) << 5;
h[3] = load3(&data[10..]) << 3;
h[4] = load3(&data[13..]) << 2;
h[5] = load4(&data[16..]);
h[6] = load3(&data[20..]) << 7;
h[7] = load3(&data[23..]) << 5;
h[8] = load3(&data[26..]) << 4;
h[9] = (load3(&data[29..]) & 8388607) << 2;
FieldElement::combine_coeffs(&h)
}
/// Marshal this FieldElement into a 32-byte array.
///
/// # Preconditions
///
/// * `|h[i]|` bounded by 1.1*2^25, 1.1*2^24, 1.1*2^25, 1.1*2^24, etc.
///
/// # Lemma
///
/// Write p = 2^255 - 19 and q = floor(h/p).
///
/// Basic claim: q = floor(2^(-255)(h + 19 * 2^-25 h9 + 2^-1)).
///
/// # Proof
///
/// Have |h|<=p so |q|<=1 so |19^2 * 2^-255 * q| < 1/4.
///
/// Also have |h-2^230 * h9| < 2^230 so |19 * 2^-255 * (h-2^230 * h9)| < 1/4.
///
/// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9), then 0<y<1.
///
/// Write r = h - pq.
///
/// Have 0 <= r< = p-1 = 2^255 - 20.
///
/// Thus 0 <= r + 19 * 2^-255 * r < r + 19 * 2^-255 * 2^255 <= 2^255 - 1.
///
/// Write x = r + 19 * 2^-255 * r + y.
///
/// Then 0 < x < 2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
///
/// Have q+2^(-255)x = 2^-255 * (h + 19 * 2^-25 * h9 + 2^-1),
/// so floor(2^-255 * (h + 19 * 2^-25 * h9 + 2^-1)) = q.
///
/// # Example
///
/// Continuing from the previous example in `FieldElement::from_bytes`:
///
/// ```
/// # use curve25519_dalek::field::FieldElement;
/// let data: [u8; 32] = [ 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 ];
/// let fe: FieldElement = FieldElement([ 197121, -4095679, 21045505, 6840408, 4209720,
/// 1249809, -7665014, -12377341, 30523826, 8420472]);
/// let bytes: [u8; 32] = fe.to_bytes();
/// assert!(data == bytes);
/// ```
pub fn to_bytes(&self) -> [u8;32] { //FeToBytes
let mut carry = [0i32; 10];
let mut h = self.clone();
let mut q:i32 = (19*h[9] + (1 << 24)) >> 25;
q = (h[0] + q) >> 26;
q = (h[1] + q) >> 25;
q = (h[2] + q) >> 26;
q = (h[3] + q) >> 25;
q = (h[4] + q) >> 26;
q = (h[5] + q) >> 25;
q = (h[6] + q) >> 26;
q = (h[7] + q) >> 25;
q = (h[8] + q) >> 26;
q = (h[9] + q) >> 25;
// Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
h[0] += 19 * q;
// Goal: Output h-2^255 q, which is between 0 and 2^255-20.
carry[0] = h[0] >> 26;
h[1] += carry[0];
h[0] -= carry[0] << 26;
carry[1] = h[1] >> 25;
h[2] += carry[1];
h[1] -= carry[1] << 25;
carry[2] = h[2] >> 26;
h[3] += carry[2];
h[2] -= carry[2] << 26;
carry[3] = h[3] >> 25;
h[4] += carry[3];
h[3] -= carry[3] << 25;
carry[4] = h[4] >> 26;
h[5] += carry[4];
h[4] -= carry[4] << 26;
carry[5] = h[5] >> 25;
h[6] += carry[5];
h[5] -= carry[5] << 25;
carry[6] = h[6] >> 26;
h[7] += carry[6];
h[6] -= carry[6] << 26;
carry[7] = h[7] >> 25;
h[8] += carry[7];
h[7] -= carry[7] << 25;
carry[8] = h[8] >> 26;
h[9] += carry[8];
h[8] -= carry[8] << 26;
carry[9] = h[9] >> 25;
h[9] -= carry[9] << 25;
// h10 = carry9
// Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
// Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
// evidently 2^255 h10-2^255 q = 0.
// Goal: Output h[0]+...+2^230 h[9].
let mut s = [0u8;32];
s[0] = (h[0] >> 0) as u8;
s[1] = (h[0] >> 8) as u8;
s[2] = (h[0] >> 16) as u8;
s[3] = ((h[0] >> 24) | (h[1] << 2)) as u8;
s[4] = (h[1] >> 6) as u8;
s[5] = (h[1] >> 14) as u8;
s[6] = ((h[1] >> 22) | (h[2] << 3)) as u8;
s[7] = (h[2] >> 5) as u8;
s[8] = (h[2] >> 13) as u8;
s[9] = ((h[2] >> 21) | (h[3] << 5)) as u8;
s[10] = (h[3] >> 3) as u8;
s[11] = (h[3] >> 11) as u8;
s[12] = ((h[3] >> 19) | (h[4] << 6)) as u8;
s[13] = (h[4] >> 2) as u8;
s[14] = (h[4] >> 10) as u8;
s[15] = (h[4] >> 18) as u8;
s[16] = (h[5] >> 0) as u8;
s[17] = (h[5] >> 8) as u8;
s[18] = (h[5] >> 16) as u8;
s[19] = ((h[5] >> 24) | (h[6] << 1)) as u8;
s[20] = (h[6] >> 7) as u8;
s[21] = (h[6] >> 15) as u8;
s[22] = ((h[6] >> 23) | (h[7] << 3)) as u8;
s[23] = (h[7] >> 5) as u8;
s[24] = (h[7] >> 13) as u8;
s[25] = ((h[7] >> 21) | (h[8] << 4)) as u8;
s[26] = (h[8] >> 4) as u8;
s[27] = (h[8] >> 12) as u8;
s[28] = ((h[8] >> 20) | (h[9] << 6)) as u8;
s[29] = (h[9] >> 2) as u8;
s[30] = (h[9] >> 10) as u8;
s[31] = (h[9] >> 18) as u8;
//Clear high bit
s[31] &= 127u8;
s
}
/// XXX clarify documentation
/// Determine if this field element, represented as a byte array,
/// is less than or equal to another field element represented as
/// a byte array.
///
/// # Returns
///
/// Returns `1u8` if `self.to_bytes() <= other.to_bytes()`, and `0u8` otherwise.
pub fn bytes_equal_less_than(&self, other: &[u8; 32]) -> u8 { // feBytesLess
// XXX cleanup
let mut equal_so_far: i32 = -1i32;
let mut greater: i32 = 0i32;
let this: [u8; 32] = self.to_bytes();
for i in 32 .. 0 {
let x: i32 = this[i-1] as i32;
let y: i32 = other[i-1] as i32;
greater = (!equal_so_far & greater) | (equal_so_far & ((x - y) >> 31));
equal_so_far = equal_so_far & (((x ^ y) - 1) >> 31);
}
(!equal_so_far & 1 & greater) as u8
}
/// Determine if this `FieldElement` is negative.
///
/// # Return
///
/// If negative, return `1i32`. Otherwise, return `0i32`.
// XXX should return u8
pub fn is_negative(&self) -> i32 { //FeIsNegative
let bytes = self.to_bytes();
(bytes[0] & 1) as i32
}
/// Determine if this `FieldElement` is non-zero.
///
/// # Return
///
/// If non-zero, return `1u8`. Otherwise, return `0u8`.
pub fn is_nonzero(&self) -> u8 { //FeIsNonZero
let bytes = self.to_bytes();
let mut x = 0u8;
for b in &bytes {
x |= *b;
}
return byte_is_nonzero(x);
}
/// Calculates h = f * g. Can overlap h with f or g.
///
/// # Preconditions
///
/// * |f[i]| bounded by 1.1*2^26, 1.1*2^25, 1.1*2^26, 1.1*2^25, etc.
/// * |g[i]| bounded by 1.1*2^26, 1.1*2^25, 1.1*2^26, 1.1*2^25, etc.
///
/// # Postconditions
///
/// * |h| bounded by 1.1*2^25, 1.1*2^24, 1.1*2^25, 1.1*2^24, etc.
///
/// ## Notes on implementation strategy
///
/// * Using schoolbook multiplication.
/// * Karatsuba would save a little in some cost models.
///
/// * Most multiplications by 2 and 19 are 32-bit precomputations;
/// cheaper than 64-bit postcomputations.
///
/// * There is one remaining multiplication by 19 in the carry chain;
/// one *19 precomputation can be merged into this,
/// but the resulting data flow is considerably less clean.
///
/// * There are 12 carries below.
/// 10 of them are 2-way parallelizable and vectorizable.
/// Can get away with 11 carries, but then data flow is much deeper.
///
/// * With tighter constraints on inputs can squeeze carries into int32.
pub fn multiply(&self, _rhs: &FieldElement) -> FieldElement {
let f0 = self[0] as i64;
let f1 = self[1] as i64;
let f2 = self[2] as i64;
let f3 = self[3] as i64;
let f4 = self[4] as i64;
let f5 = self[5] as i64;
let f6 = self[6] as i64;
let f7 = self[7] as i64;
let f8 = self[8] as i64;
let f9 = self[9] as i64;
let f1_2 = (2 * self[1]) as i64;
let f3_2 = (2 * self[3]) as i64;
let f5_2 = (2 * self[5]) as i64;
let f7_2 = (2 * self[7]) as i64;
let f9_2 = (2 * self[9]) as i64;
let g0 = _rhs[0] as i64;
let g1 = _rhs[1] as i64;
let g2 = _rhs[2] as i64;
let g3 = _rhs[3] as i64;
let g4 = _rhs[4] as i64;
let g5 = _rhs[5] as i64;
let g6 = _rhs[6] as i64;
let g7 = _rhs[7] as i64;
let g8 = _rhs[8] as i64;
let g9 = _rhs[9] as i64;
let g1_19 = (19 * _rhs[1]) as i64; /* 1.4*2^29 */
let g2_19 = (19 * _rhs[2]) as i64; /* 1.4*2^30; still ok */
let g3_19 = (19 * _rhs[3]) as i64;
let g4_19 = (19 * _rhs[4]) as i64;
let g5_19 = (19 * _rhs[5]) as i64;
let g6_19 = (19 * _rhs[6]) as i64;
let g7_19 = (19 * _rhs[7]) as i64;
let g8_19 = (19 * _rhs[8]) as i64;
let g9_19 = (19 * _rhs[9]) as i64;
let h0 = f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19;
let h1 = f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19;
let h2 = f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19;
let h3 = f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19;
let h4 = f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19;
let h5 = f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19;
let h6 = f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19;
let h7 = f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19;
let h8 = f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19;
let h9 = f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0;
FieldElement::combine_coeffs(&[h0, h1, h2, h3, h4, h5, h6, h7, h8, h9])
}
fn square_inner(&self) -> [i64;10] {
let f0 = self[0] as i64;
let f1 = self[1] as i64;
let f2 = self[2] as i64;
let f3 = self[3] as i64;
let f4 = self[4] as i64;
let f5 = self[5] as i64;
let f6 = self[6] as i64;
let f7 = self[7] as i64;
let f8 = self[8] as i64;
let f9 = self[9] as i64;
let f0_2 = (2 * self[0]) as i64;
let f1_2 = (2 * self[1]) as i64;
let f2_2 = (2 * self[2]) as i64;
let f3_2 = (2 * self[3]) as i64;
let f4_2 = (2 * self[4]) as i64;
let f5_2 = (2 * self[5]) as i64;
let f6_2 = (2 * self[6]) as i64;
let f7_2 = (2 * self[7]) as i64;
let f5_38 = 38 * f5; // 1.31*2^30
let f6_19 = 19 * f6; // 1.31*2^30
let f7_38 = 38 * f7; // 1.31*2^30
let f8_19 = 19 * f8; // 1.31*2^30
let f9_38 = 38 * f9; // 1.31*2^30
let mut h = [0i64;10];
h[0] = f0*f0 + f1_2*f9_38 + f2_2*f8_19 + f3_2*f7_38 + f4_2*f6_19 + f5*f5_38;
h[1] = f0_2*f1 + f2*f9_38 + f3_2*f8_19 + f4*f7_38 + f5_2*f6_19;
h[2] = f0_2*f2 + f1_2*f1 + f3_2*f9_38 + f4_2*f8_19 + f5_2*f7_38 + f6*f6_19;
h[3] = f0_2*f3 + f1_2*f2 + f4*f9_38 + f5_2*f8_19 + f6*f7_38;
h[4] = f0_2*f4 + f1_2*f3_2 + f2*f2 + f5_2*f9_38 + f6_2*f8_19 + f7*f7_38;
h[5] = f0_2*f5 + f1_2*f4 + f2_2*f3 + f6*f9_38 + f7_2*f8_19;
h[6] = f0_2*f6 + f1_2*f5_2 + f2_2*f4 + f3_2*f3 + f7_2*f9_38 + f8*f8_19;
h[7] = f0_2*f7 + f1_2*f6 + f2_2*f5 + f3_2*f4 + f8*f9_38;
h[8] = f0_2*f8 + f1_2*f7_2 + f2_2*f6 + f3_2*f5_2 + f4*f4 + f9*f9_38;
h[9] = f0_2*f9 + f1_2*f8 + f2_2*f7 + f3_2*f6 + f4_2*f5;
h
}
/// Calculates h = f*f. Can overlap h with f.
///
/// # Preconditions
///
/// * |f[i]| bounded by 1.1*2^26, 1.1*2^25, 1.1*2^26, 1.1*2^25, etc.
///
/// # Postconditions
///
/// * |h[i]| bounded by 1.1*2^25, 1.1*2^24, 1.1*2^25, 1.1*2^24, etc.
pub fn square(&self) -> FieldElement {
FieldElement::combine_coeffs(&self.square_inner())
}
/// Square this field element and multiply the result by 2.
///
/// # Preconditions
///
/// * |f[i]| bounded by 1.65*2^26, 1.65*2^25, 1.65*2^26, 1.65*2^25, etc.
///
/// # Postconditions
///
/// * |h[i]| bounded by 1.01*2^25, 1.01*2^24, 1.01*2^25, 1.01*2^24, etc.
///
/// # Notes
///
/// See fe_mul.c in ref10 implementation for discussion of implementation
/// strategy.
pub fn square2(&self) -> FieldElement {
let mut coeffs = self.square_inner();
for i in 0..10 {
coeffs[i] += coeffs[i];
}
FieldElement::combine_coeffs(&coeffs)
}
#[inline]
#[allow(dead_code)]
/// Requires k > 0; raise self to the 2^(2^k)-th power.
fn pow2k(&self, k: u32) -> FieldElement {
let mut z = self.square();
for _ in 1..k { z = z.square(); }
z
}
/// Compute (self^(2^250-1), self^11), used as a helper function
/// within invert() and pow22523().
///
/// XXX This returns an extra intermediate to save computation in
/// finding inverses, at the cost of an extra copy when it's not
/// used (e.g., when raising to (p-1)/2 or (p-5)/8). Good idea?
fn pow22501(&self) -> (FieldElement,FieldElement) {
// Instead of managing which temporary variables are used
// for what, we define as many as we need and trust the
// compiler to reuse stack space as appropriate.
//
// XXX testing some examples suggests that this does happen,
// but it would be good to check asm for this function.
//
// Each temporary variable t_i is of the form (self)^e_i.
// Squaring t_i corresponds to multiplying e_i by 2,
// so the pow2k function shifts e_i left by k places.
// Multiplying t_i and t_j corresponds to adding e_i + e_j.
//
// Temporary t_i Nonzero bits of e_i
//
let t0 = self.square(); // 1 e_0 = 2^1
let t1 = t0.square().square(); // 3 e_1 = 2^3
let t2 = self * &t1; // 3,0 e_2 = 2^3 + 2^0
let t3 = &t0 * &t2; // 3,1,0
let t4 = t3.square(); // 4,2,1
let t5 = &t2 * &t4; // 4,3,2,1,0
let t6 = t5.pow2k(5); // 9,8,7,6,5
let t7 = &t6 * &t5; // 9,8,7,6,5,4,3,2,1,0
let t8 = t7.pow2k(10); // 19..10
let t9 = &t8 * &t7; // 19..0
let t10 = t9.pow2k(20); // 39..20
let t11 = &t10 * &t9; // 39..0
let t12 = t11.pow2k(10); // 49..10
let t13 = &t12 * &t7; // 49..0
let t14 = t13.pow2k(50); // 99..50
let t15 = &t14 * &t13; // 99..0
let t16 = t15.pow2k(100); // 199..100
let t17 = &t16 * &t15; // 199..0
let t18 = t17.pow2k(50); // 249..50
let t19 = &t18 * &t13; // 249..0
(t19, t3)
}
/// Given a nonzero field element, compute its inverse.
/// The inverse is computed as self^(p-2), since
/// x^(p-2)x = x^(p-1) = 1 (mod p).
pub fn invert(&self) -> FieldElement {
// The bits of p-2 = 2^255 -19 -2 are 11010111111...11.
//
// nonzero bits of exponent
let (t19, t3) = self.pow22501(); // t19: 249..0 ; t3: 3,1,0
let t20 = t19.pow2k(5); // 254..5
let t21 = &t20 * &t3; // 254..5,3,1,0
t21
}
/// Raise this field element to the power (p-5)/8 = 2^252 -3.
/// Used in decoding.
pub fn pow_p58(&self) -> FieldElement {
// The bits of (p-5)/8 are 101111.....11.
//
// nonzero bits of exponent
let (t19, _) = self.pow22501(); // 249..0
let t20 = t19.pow2k(2); // 251..2
let t21 = self * &t20; // 251..2,0
t21
}
/// chi calculates `self^((p-1)/2)`.
///
/// # Return
///
/// * If this element is a non-zero square, returns `1`.
/// * If it is zero, returns `0`.
/// * If it is non-square, returns `-1`.
pub fn chi(&self) -> FieldElement { // extra25519.chi
// The bits of (p-1)/2 = 2^254 -10 are 0110111111...11.
//
// nonzero bits of exponent
let (t19, _) = self.pow22501(); // 249..0
let t20 = t19.pow2k(4); // 253..4
let t21 = self.square(); // 1
let t22 = t21.square(); // 2
let t23 = &t22 * &t21; // 2,1
let t24 = &t20 * &t23; // 253..4,2,1
t24
}
}
#[cfg(test)]
mod test {
use field::*;
use test::Bencher;
#[bench]
fn bench_fieldelement_a_mul_a(b: &mut Bencher) {
let a = FieldElement::from_bytes(&A_BYTES);
b.iter(|| &a*&a);
}
#[bench]
fn bench_fieldelement_a_sq(b: &mut Bencher) {
let a = FieldElement::from_bytes(&A_BYTES);
b.iter(|| a.square());
}
#[bench]
fn bench_fieldelement_a_inv(b: &mut Bencher) {
let a = FieldElement::from_bytes(&A_BYTES);
b.iter(|| a.invert());
}
/// Random element a of GF(2^255-19), from Sage
/// a = 1070314506888354081329385823235218444233221\
/// 2228051251926706380353716438957572
static A_BYTES: [u8;32] =
[ 0x04, 0xfe, 0xdf, 0x98, 0xa7, 0xfa, 0x0a, 0x68,
0x84, 0x92, 0xbd, 0x59, 0x08, 0x07, 0xa7, 0x03,
0x9e, 0xd1, 0xf6, 0xf2, 0xe1, 0xd9, 0xe2, 0xa4,
0xa4, 0x51, 0x47, 0x36, 0xf3, 0xc3, 0xa9, 0x17];
/// Byte representation of a**2
static ASQ_BYTES: [u8;32] =
[ 0x75, 0x97, 0x24, 0x9e, 0xe6, 0x06, 0xfe, 0xab,
0x24, 0x04, 0x56, 0x68, 0x07, 0x91, 0x2d, 0x5d,
0x0b, 0x0f, 0x3f, 0x1c, 0xb2, 0x6e, 0xf2, 0xe2,
0x63, 0x9c, 0x12, 0xba, 0x73, 0x0b, 0xe3, 0x62];
/// Byte representation of 1/a
static AINV_BYTES: [u8;32] =
[0x96, 0x1b, 0xcd, 0x8d, 0x4d, 0x5e, 0xa2, 0x3a,
0xe9, 0x36, 0x37, 0x93, 0xdb, 0x7b, 0x4d, 0x70,
0xb8, 0x0d, 0xc0, 0x55, 0xd0, 0x4c, 0x1d, 0x7b,
0x90, 0x71, 0xd8, 0xe9, 0xb6, 0x18, 0xe6, 0x30];
/// Byte representation of a^((p-5)/8)
static AP58_BYTES: [u8;32] =
[0x6a, 0x4f, 0x24, 0x89, 0x1f, 0x57, 0x60, 0x36,
0xd0, 0xbe, 0x12, 0x3c, 0x8f, 0xf5, 0xb1, 0x59,
0xe0, 0xf0, 0xb8, 0x1b, 0x20, 0xd2, 0xb5, 0x1f,
0x15, 0x21, 0xf9, 0xe3, 0xe1, 0x61, 0x21, 0x55];
#[test]
fn test_fieldelement_a_mul_a() {
let a = FieldElement::from_bytes(&A_BYTES);
let asq = FieldElement::from_bytes(&ASQ_BYTES);
assert_eq!(asq, &a*&a);
assert_eq!(asq, a.square());
}
#[test]
fn test_fieldelement_a_square2() {
let a = FieldElement::from_bytes(&A_BYTES);
let asq = FieldElement::from_bytes(&ASQ_BYTES);
assert_eq!(a.square2(), &asq+&asq);
}
#[test]
fn test_fieldelement_a_inv() {
let a = FieldElement::from_bytes(&A_BYTES);
let ainv = FieldElement::from_bytes(&AINV_BYTES);
assert_eq!(ainv, a.invert());
}
#[test]
fn test_fieldelement_a_p58() {
let a = FieldElement::from_bytes(&A_BYTES);
let ap58 = FieldElement::from_bytes(&AP58_BYTES);
assert_eq!(ap58, a.pow_p58());
}
#[test]
fn test_fieldelement_a_chi() {
let a = FieldElement::from_bytes(&A_BYTES);
// a is square
assert_eq!(a.chi(), FieldElement::one());
}
#[test]
fn test_fieldelement_eq() {
let a = FieldElement::from_bytes(&A_BYTES);
let ainv = FieldElement::from_bytes(&AINV_BYTES);
assert!(a == a);
assert!(a != ainv);
}
/// Notice that the last element has the high bit set, which
/// should be ignored
static B_BYTES: [u8;32] =
[113, 191, 169, 143, 91, 234, 121, 15, 241, 131, 217, 36, 230, 101, 92, 234, 8, 208, 170, 251, 97, 127, 70, 210, 58, 23, 166, 87, 240, 169, 184, 178];
static B_LIMBS: FieldElement = FieldElement(
[-5652623, 8034020, 8266223, -13556020, -5672552, -5582839, -12603138, 15161929, -16418207, 13296296]);
#[test]
fn test_fieldelement_frombytes_highbit_is_ignored() {
let mut cleared_bytes = B_BYTES.clone();
cleared_bytes[31] &= 127u8;
let orig_elt = FieldElement::from_bytes(&B_BYTES);
let cleared_elt = FieldElement::from_bytes(&cleared_bytes);
for i in 0..10 {
assert!(orig_elt[i] == cleared_elt[i]);
}
}
#[test]
fn test_fieldelement_to_bytes() {
let test_elt = FieldElement::from_bytes(&B_BYTES);
for i in 0..10 {
assert!(test_elt[i] == B_LIMBS[i]);
}
}
#[test]
fn test_fieldelement_from_bytes() {
let test_bytes = B_LIMBS.to_bytes();
for i in 0..31 {
assert!(test_bytes[i] == B_BYTES[i]);
}
// high bit is set to zero in to_bytes
assert!(test_bytes[31] == (B_BYTES[31] & 127u8));
}
}

1481
src/lib.rs Normal file

File diff suppressed because it is too large Load diff

527
src/scalar.rs Normal file
View file

@ -0,0 +1,527 @@
// -*- mode: rust; -*-
//
// To the extent possible under law, the authors have waived all
// copyright and related or neighboring rights to curve25519-dalek,
// using the Creative Commons "CC0" public domain dedication. See
// <http://creativecommons.org/publicdomain/zero/.0/> for full
// details.
//
// Authors:
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
// - Henry de Valence <hdevalence@hdevalence.ca>
//! Arithmetic for scalar multiplication.
//!
//! The Ed25519 basepoint P has prime order
//!
//! l = 2^252 + 27742317777372353535851937790883648493.
//!
//! Thus a multiple `aP` of the basepoint (with a ∈ ) depends only
//! on the value of `a (mod l)`, or equivalently, the image of `a` in
//! the quotient /l.
//!
//! The `Scalar` struct represents an element in /l.
//!
//! Arithmetic operations on `Scalar`s are done using 12 21-bit limbs.
//! However, in contrast to `FieldElement`s, `Scalar`s are stored in
//! memory as bytes, allowing easy access to the bits of the `Scalar`.
use std::clone::Clone;
use std::ops::{Index, IndexMut};
use field::{load3, load4};
/// The `Scalar` struct represents an element in /l, where
///
/// l = 2^252 + 27742317777372353535851937790883648493
///
/// is the order of the basepoint.
#[derive(Copy)]
pub struct Scalar(pub [u8; 32]);
impl Clone for Scalar {
fn clone(&self) -> Scalar { *self }
}
impl Index<usize> for Scalar {
type Output = u8;
fn index<'a>(&'a self, _index: usize) -> &'a u8 {
let ret: &'a u8 = &(self.0[_index]);
ret
}
}
impl IndexMut<usize> for Scalar {
fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut u8 {
let ret: &'a mut u8 = &mut(self.0[_index]);
ret
}
}
impl Scalar {
/// Construct the additive identity
pub fn zero() -> Self {
Scalar([0u8; 32])
}
/// Construct the multiplicative identity
pub fn one() -> Self {
Scalar([ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ])
}
/// Compute a width-5 "Non-Adjacent Form" of this scalar.
///
/// A width-`w` NAF of a positive integer `k` is an expression
/// `k = sum(k[i]*2^i for i in range(l))`, where each nonzero
/// coefficient `k[i]` is odd and bounded by `|k[i]| < 2^(w-1)`,
/// `k[l-1]` is nonzero, and at most one of any `w` consecutive
/// coefficients is nonzero. (Hankerson, Menezes, Vanstone; def 3.32).
///
/// Intuitively, this is like a binary expansion, except that we
/// allow some coefficients to grow up to `2^(w-1)` so that the
/// nonzero coefficients are as sparse as possible.
pub fn non_adjacent_form(&self) -> [i8;256] {
// Step 1: write out bits of the scalar
let mut naf = [0i8; 256];
for i in 0..256 {
// As i runs from 0..256, the bottom 3 bits index the bit,
// while the upper bits index the byte.
naf[i] = ((self.0[i>>3] >> (i&7)) & 1u8) as i8;
}
// Step 2: zero coefficients by carrying them upwards or downwards
'bits: for i in 0..256 {
if naf[i] == 0 { continue 'bits; }
'window: for b in 1..6 {
if i+b >= 256 { break 'window; }
if naf[i+b] == 0 { continue 'window; }
let potential_carry = naf[i+b] << b;
if naf[i+b] + potential_carry <= 15 {
// Eliminate naf[i+b] by carrying its value onto naf[i]
naf[i] += potential_carry;
naf[i+b] = 0;
} else if naf[i+b] - potential_carry >= -15 {
// Eliminate naf[i+b] by carrying its value upwards.
naf[i] -= potential_carry; // Subtract 2^(i+b)
'carry: for k in i+b..256 {
if naf[k] != 0 {
// Since naf[k] = 0 or 1 for k > i, naf[k] == 1.
naf[k] = 0; // Subtract 2^k
} else {
// By now we have subtracted 2^k =
// 2^(i+b) + 2^(i+b) + 2^(i+b+1) + ... + 2^(k-1).
naf[k] = 1; // Add back 2^k.
break 'carry;
}
}
}
}
}
naf
}
/// Create a scalar by packing 12 21-bit limbs into bytes.
fn pack_limbs(limbs: &[i64;12]) -> Scalar {
let mut s = Scalar::zero();
s[0] = (limbs[ 0] >> 0) as u8;
s[1] = (limbs[ 0] >> 8) as u8;
s[2] = ((limbs[ 0] >> 16) | (limbs[ 1] << 5)) as u8;
s[3] = (limbs[ 1] >> 3) as u8;
s[4] = (limbs[ 1] >> 11) as u8;
s[5] = ((limbs[ 1] >> 19) | (limbs[ 2] << 2)) as u8;
s[6] = (limbs[ 2] >> 6) as u8;
s[7] = ((limbs[ 2] >> 14) | (limbs[ 3] << 7)) as u8;
s[8] = (limbs[ 3] >> 1) as u8;
s[9] = (limbs[ 3] >> 9) as u8;
s[10] = ((limbs[ 3] >> 17) | (limbs[ 4] << 4)) as u8;
s[11] = (limbs[ 4] >> 4) as u8;
s[12] = (limbs[ 4] >> 12) as u8;
s[13] = ((limbs[ 4] >> 20) | (limbs[ 5] << 1)) as u8;
s[14] = (limbs[ 5] >> 7) as u8;
s[15] = ((limbs[ 5] >> 15) | (limbs[ 6] << 6)) as u8;
s[16] = (limbs[ 6] >> 2) as u8;
s[17] = (limbs[ 6] >> 10) as u8;
s[18] = ((limbs[ 6] >> 18) | (limbs[ 7] << 3)) as u8;
s[19] = (limbs[ 7] >> 5) as u8;
s[20] = (limbs[ 7] >> 13) as u8;
s[21] = (limbs[ 8] >> 0) as u8;
s[22] = (limbs[ 8] >> 8) as u8;
s[23] = ((limbs[ 8] >> 16) | (limbs[ 9] << 5)) as u8;
s[24] = (limbs[ 9] >> 3) as u8;
s[25] = (limbs[ 9] >> 11) as u8;
s[26] = ((limbs[ 9] >> 19) | (limbs[10] << 2)) as u8;
s[27] = (limbs[10] >> 6) as u8;
s[28] = ((limbs[10] >> 14) | (limbs[11] << 7)) as u8;
s[29] = (limbs[11] >> 1) as u8;
s[30] = (limbs[11] >> 9) as u8;
s[31] = (limbs[11] >> 17) as u8;
s
}
// Unpack a scalar into 12 21-bit limbs.
fn unpack_limbs(&self) -> [i64;12] {
let mask_21bits: i64 = (1 << 21) -1;
let mut a = [0i64;12];
a[ 0] = mask_21bits & load3(&self.0[ 0..]) ;
a[ 1] = mask_21bits & (load4(&self.0[ 2..]) >> 5);
a[ 2] = mask_21bits & (load3(&self.0[ 5..]) >> 2);
a[ 3] = mask_21bits & (load4(&self.0[ 7..]) >> 7);
a[ 4] = mask_21bits & (load4(&self.0[10..]) >> 4);
a[ 5] = mask_21bits & (load3(&self.0[13..]) >> 1);
a[ 6] = mask_21bits & (load4(&self.0[15..]) >> 6);
a[ 7] = mask_21bits & (load3(&self.0[18..]) >> 3);
a[ 8] = mask_21bits & load3(&self.0[21..]) ;
a[ 9] = mask_21bits & (load4(&self.0[23..]) >> 5);
a[10] = mask_21bits & (load3(&self.0[26..]) >> 2);
a[11] = load4(&self.0[28..]) >> 7 ;
a
}
/// Write this scalar in radix 16, with coefficients in `[-8,8)`,
/// i.e., compute `a_i` such that
///
/// a = a_0 + a_1*16^1 + ... + a_63*16^63,
///
/// with `-8 ≤ a_i < 8` for `0 ≤ i < 63` and `-8 ≤ a_63 ≤ 8`.
///
/// Precondition: self[31] <= 127. This is the case whenever
/// `self` is reduced.
pub fn to_radix_16(&self) -> [i8;64] {
debug_assert!(self[31] <= 127);
let mut output = [0i8; 64];
// Step 1: change radix.
// Convert from radix 256 (bytes) to radix 16 (nibbles)
#[inline(always)]
fn bot_half(x: u8) -> u8 { (x >> 0) & 15 }
#[inline(always)]
fn top_half(x: u8) -> u8 { (x >> 4) & 15 }
for i in 0..32 {
output[2*i ] = bot_half(self[i]) as i8;
output[2*i+1] = top_half(self[i]) as i8;
}
// Precondition note: since self[31] <= 127, output[63] <= 7
// Step 2: recenter coefficients from [0,16) to [-8,8)
for i in 0..63 {
let carry = (output[i] + 8) >> 4;
output[i ] -= carry << 4;
output[i+1] += carry;
}
// Precondition note: output[63] is not recentered. It
// increases by carry <= 1. Thus output[63] <= 8.
output
}
/// Reduce limbs in-place. Reduction is mod
///
/// l = 2^252 + 27742317777372353535851937790883648493,
///
/// so
///
/// 2^252 = -27742317777372353535851937790883648493 (mod l).
///
/// We can write the right-hand side in 21-bit limbs as
///
/// rhs = 666643 * 2^0
/// + 470296 * 2^21
/// + 654183 * 2^42
/// - 997805 * 2^63
/// + 136657 * 2^84
/// - 683901 * 2^105
///
/// The (12+k)-th limb of `limbs` is the coefficient of
///
/// 2^(252 + 21*k)
///
/// since 12*21 = 252. By the above, we have that
///
/// c * 2^(252 + 21*k) = c * 666643 * 2^(21*k)
/// + c * 470296 * 2^(42*k) + ...
///
/// so we can eliminate it by adding those values to the lower
/// limbs. Reduction mod l amounts to eliminating all of the
/// high limbs while carrying as appropriate to prevent
/// overflows in the lower limbs.
fn reduce_limbs(mut limbs: &mut [i64;24]) {
#[inline]
#[allow(dead_code)]
fn do_reduction(limbs: &mut [i64;24], i:usize) {
limbs[i - 12] += limbs[i] * 666643;
limbs[i - 11] += limbs[i] * 470296;
limbs[i - 10] += limbs[i] * 654183;
limbs[i - 9] -= limbs[i] * 997805;
limbs[i - 8] += limbs[i] * 136657;
limbs[i - 7] -= limbs[i] * 683901;
limbs[i] = 0;
}
/// Carry excess from the `i`-th limb into the `(i+1)`-th limb.
/// Postcondition: `0 <= limbs[i] < 2^21`.
#[inline]
#[allow(dead_code)]
fn do_carry_uncentered(limbs: &mut [i64; 24], i: usize) {
let carry: i64 = limbs[i] >> 21;
limbs[i+1] += carry;
limbs[i ] -= carry << 21;
}
#[inline]
#[allow(dead_code)]
/// Carry excess from the `i`-th limb into the `(i+1)`-th limb.
/// Postcondition: `-2^20 <= limbs[i] < 2^20`.
fn do_carry_centered(limbs: &mut [i64;24], i:usize) {
let carry: i64 = (limbs[i] + (1<<20)) >> 21;
limbs[i+1] += carry;
limbs[i ] -= carry << 21;
}
for i in 0..23 {
do_carry_centered(&mut limbs, i);
}
for i in (0..23).filter(|x| x % 2 == 1) {
do_carry_centered(&mut limbs, i);
}
do_reduction(&mut limbs, 23);
do_reduction(&mut limbs, 22);
do_reduction(&mut limbs, 21);
do_reduction(&mut limbs, 20);
do_reduction(&mut limbs, 19);
do_reduction(&mut limbs, 18);
for i in (6..18).filter(|x| x % 2 == 0) {
do_carry_centered(&mut limbs, i);
}
for i in (6..16).filter(|x| x % 2 == 1) {
do_carry_centered(&mut limbs, i);
}
do_reduction(&mut limbs, 17);
do_reduction(&mut limbs, 16);
do_reduction(&mut limbs, 15);
do_reduction(&mut limbs, 14);
do_reduction(&mut limbs, 13);
do_reduction(&mut limbs, 12);
for i in (0..12).filter(|x| x % 2 == 0) {
do_carry_centered(&mut limbs, i);
}
for i in (0..12).filter(|x| x % 2 == 1) {
do_carry_centered(&mut limbs, i);
}
do_reduction(&mut limbs, 12);
for i in 0..12 {
do_carry_uncentered(&mut limbs, i);
}
do_reduction(&mut limbs, 12);
for i in 0..11 {
do_carry_uncentered(&mut limbs, i);
}
}
/// Compute `ab+c (mod l)`.
pub fn multiply_add(a: &Scalar, b: &Scalar, c: &Scalar) -> Scalar {
// Unpack scalars into limbs
let al = a.unpack_limbs();
let bl = b.unpack_limbs();
let cl = c.unpack_limbs();
let mut result = [0i64;24];
// Multiply a and b, and add c
result[0] = cl[0] + al[0]*bl[0];
result[1] = cl[1] + al[0]*bl[1] + al[1]*bl[0];
result[2] = cl[2] + al[0]*bl[2] + al[1]*bl[1] + al[2]*bl[0];
result[3] = cl[3] + al[0]*bl[3] + al[1]*bl[2] + al[2]*bl[1] + al[3]*bl[0];
result[4] = cl[4] + al[0]*bl[4] + al[1]*bl[3] + al[2]*bl[2] + al[3]*bl[1] + al[4]*bl[0];
result[5] = cl[5] + al[0]*bl[5] + al[1]*bl[4] + al[2]*bl[3] + al[3]*bl[2] + al[4]*bl[1] + al[5]*bl[0];
result[6] = cl[6] + al[0]*bl[6] + al[1]*bl[5] + al[2]*bl[4] + al[3]*bl[3] + al[4]*bl[2] + al[5]*bl[1] + al[6]*bl[0];
result[7] = cl[7] + al[0]*bl[7] + al[1]*bl[6] + al[2]*bl[5] + al[3]*bl[4] + al[4]*bl[3] + al[5]*bl[2] + al[6]*bl[1] + al[7]*bl[0];
result[8] = cl[8] + al[0]*bl[8] + al[1]*bl[7] + al[2]*bl[6] + al[3]*bl[5] + al[4]*bl[4] + al[5]*bl[3] + al[6]*bl[2] + al[7]*bl[1] + al[8]*bl[0];
result[9] = cl[9] + al[0]*bl[9] + al[1]*bl[8] + al[2]*bl[7] + al[3]*bl[6] + al[4]*bl[5] + al[5]*bl[4] + al[6]*bl[3] + al[7]*bl[2] + al[8]*bl[1] + al[9]*bl[0];
result[10] = cl[10] + al[0]*bl[10] + al[1]*bl[9] + al[2]*bl[8] + al[3]*bl[7] + al[4]*bl[6] + al[5]*bl[5] + al[6]*bl[4] + al[7]*bl[3] + al[8]*bl[2] + al[9]*bl[1] + al[10]*bl[0];
result[11] = cl[11] + al[0]*bl[11] + al[1]*bl[10] + al[2]*bl[9] + al[3]*bl[8] + al[4]*bl[7] + al[5]*bl[6] + al[6]*bl[5] + al[7]*bl[4] + al[8]*bl[3] + al[9]*bl[2] + al[10]*bl[1] + al[11]*bl[0];
result[12] = al[1]*bl[11] + al[2]*bl[10] + al[3]*bl[9] + al[4]*bl[8] + al[5]*bl[7] + al[6]*bl[6] + al[7]*bl[5] + al[8]*bl[4] + al[9]*bl[3] + al[10]*bl[2] + al[11]*bl[1];
result[13] = al[2]*bl[11] + al[3]*bl[10] + al[4]*bl[9] + al[5]*bl[8] + al[6]*bl[7] + al[7]*bl[6] + al[8]*bl[5] + al[9]*bl[4] + al[10]*bl[3] + al[11]*bl[2];
result[14] = al[3]*bl[11] + al[4]*bl[10] + al[5]*bl[9] + al[6]*bl[8] + al[7]*bl[7] + al[8]*bl[6] + al[9]*bl[5] + al[10]*bl[4] + al[11]*bl[3];
result[15] = al[4]*bl[11] + al[5]*bl[10] + al[6]*bl[9] + al[7]*bl[8] + al[8]*bl[7] + al[9]*bl[6] + al[10]*bl[5] + al[11]*bl[4];
result[16] = al[5]*bl[11] + al[6]*bl[10] + al[7]*bl[9] + al[8]*bl[8] + al[9]*bl[7] + al[10]*bl[6] + al[11]*bl[5];
result[17] = al[6]*bl[11] + al[7]*bl[10] + al[8]*bl[9] + al[9]*bl[8] + al[10]*bl[7] + al[11]*bl[6];
result[18] = al[7]*bl[11] + al[8]*bl[10] + al[9]*bl[9] + al[10]*bl[8] + al[11]*bl[7];
result[19] = al[8]*bl[11] + al[9]*bl[10] + al[10]*bl[9] + al[11]*bl[8];
result[20] = al[9]*bl[11] + al[10]*bl[10] + al[11]*bl[9];
result[21] = al[10]*bl[11] + al[11]*bl[10];
result[22] = al[11]*bl[11];
result[23] = 0i64;
// reduce limbs and pack into output
Scalar::reduce_limbs(&mut result);
Scalar::pack_limbs(array_ref!(result, 0, 12))
}
/// Reduce a 512-bit little endian number mod l
pub fn reduce(input: &[u8;64]) -> Scalar {
let mut s = [0i64;24];
// XXX express this as two unpack_limbs
// some issues re: masking with the top byte of the 32byte input
let mask_21bits: i64 = (1 << 21) -1;
s[0] = mask_21bits & load3(&input[ 0..]) ;
s[1] = mask_21bits & (load4(&input[ 2..]) >> 5);
s[2] = mask_21bits & (load3(&input[ 5..]) >> 2);
s[3] = mask_21bits & (load4(&input[ 7..]) >> 7);
s[4] = mask_21bits & (load4(&input[10..]) >> 4);
s[5] = mask_21bits & (load3(&input[13..]) >> 1);
s[6] = mask_21bits & (load4(&input[15..]) >> 6);
s[7] = mask_21bits & (load3(&input[18..]) >> 3);
s[8] = mask_21bits & load3(&input[21..]) ;
s[9] = mask_21bits & (load4(&input[23..]) >> 5);
s[10] = mask_21bits & (load3(&input[26..]) >> 2);
s[11] = mask_21bits & (load4(&input[28..]) >> 7);
s[12] = mask_21bits & (load4(&input[31..]) >> 4);
s[13] = mask_21bits & (load3(&input[34..]) >> 1);
s[14] = mask_21bits & (load4(&input[36..]) >> 6);
s[15] = mask_21bits & (load3(&input[39..]) >> 3);
s[16] = mask_21bits & load3(&input[42..]) ;
s[17] = mask_21bits & (load4(&input[44..]) >> 5);
s[18] = mask_21bits & (load3(&input[47..]) >> 2);
s[19] = mask_21bits & (load4(&input[49..]) >> 7);
s[20] = mask_21bits & (load4(&input[52..]) >> 4);
s[21] = mask_21bits & (load3(&input[55..]) >> 1);
s[22] = mask_21bits & (load4(&input[57..]) >> 6);
s[23] = load4(&input[60..]) >> 3 ;
// XXX replacing the previous code in this function with the
// call to reduce_limbs adds two extra carry passes (the ones
// at the top of the reduce_limbs function). Otherwise they
// are identical. The test seems to work OK but it would be
// good to check that this really is OK to add.
Scalar::reduce_limbs(&mut s);
Scalar::pack_limbs(array_ref!(s,0,12))
}
}
#[cfg(test)]
mod test {
use super::*;
use test::Bencher;
#[bench]
fn bench_scalar_multiply_add(b: &mut Bencher) {
b.iter(|| Scalar::multiply_add(&X, &Y, &Z) );
}
/// x = 2238329342913194256032495932344128051776374960164957527413114840482143558222
static X: Scalar = Scalar(
[0x4e, 0x5a, 0xb4, 0x34, 0x5d, 0x47, 0x08, 0x84,
0x59, 0x13, 0xb4, 0x64, 0x1b, 0xc2, 0x7d, 0x52,
0x52, 0xa5, 0x85, 0x10, 0x1b, 0xcc, 0x42, 0x44,
0xd4, 0x49, 0xf4, 0xa8, 0x79, 0xd9, 0xf2, 0x04]);
/// y = 2592331292931086675770238855846338635550719849568364935475441891787804997264
static Y: Scalar = Scalar(
[0x90, 0x76, 0x33, 0xfe, 0x1c, 0x4b, 0x66, 0xa4,
0xa2, 0x8d, 0x2d, 0xd7, 0x67, 0x83, 0x86, 0xc3,
0x53, 0xd0, 0xde, 0x54, 0x55, 0xd4, 0xfc, 0x9d,
0xe8, 0xef, 0x7a, 0xc3, 0x1f, 0x35, 0xbb, 0x05]);
/// z = 5033871415930814945849241457262266927579821285980625165479289807629491019013
static Z: Scalar = Scalar(
[0x05, 0x9d, 0x3e, 0x0b, 0x09, 0x26, 0x50, 0x3d,
0xa3, 0x84, 0xa1, 0x3c, 0x92, 0x7a, 0xc2, 0x06,
0x41, 0x98, 0xcf, 0x34, 0x3a, 0x24, 0xd5, 0xb7,
0xeb, 0x33, 0x6a, 0x2d, 0xfc, 0x11, 0x21, 0x0b]);
/// w = 3486911242272497535104403593250518247409663771668155364040899665266216860804
static W: Scalar = Scalar(
[0x84, 0xfc, 0xbc, 0x4f, 0x78, 0x12, 0xa0, 0x06,
0xd7, 0x91, 0xd9, 0x7a, 0x3a, 0x27, 0xdd, 0x1e,
0x21, 0x43, 0x45, 0xf7, 0xb1, 0xb9, 0x56, 0x7a,
0x81, 0x30, 0x73, 0x44, 0x96, 0x85, 0xb5, 0x07]);
/// x*y = 5690045403673944803228348699031245560686958845067437804563560795922180092780
static X_TIMES_Y: Scalar = Scalar(
[0x6c, 0x33, 0x74, 0xa1, 0x89, 0x4f, 0x62, 0x21,
0x0a, 0xaa, 0x2f, 0xe1, 0x86, 0xa6, 0xf9, 0x2c,
0xe0, 0xaa, 0x75, 0xc2, 0x77, 0x95, 0x81, 0xc2,
0x95, 0xfc, 0x08, 0x17, 0x9a, 0x73, 0x94, 0x0c]);
static A_SCALAR: Scalar = Scalar([
0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d,
0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d,
0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1,
0x58, 0x9e, 0x7b, 0x7f, 0x23, 0x76, 0xef, 0x09]);
static A_NAF: [i8;256] =
[0,13,0,0,0,0,0,0,0,7,0,0,0,0,0,0,-9,0,0,0,0,-11,0,0,0,0,3,0,0,0,0,1,
0,0,0,0,9,0,0,0,0,-5,0,0,0,0,0,0,3,0,0,0,0,11,0,0,0,0,11,0,0,0,0,0,
-9,0,0,0,0,0,-3,0,0,0,0,9,0,0,0,0,0,1,0,0,0,0,0,0,-1,0,0,0,0,0,9,0,
0,0,0,-15,0,0,0,0,-7,0,0,0,0,-9,0,0,0,0,0,5,0,0,0,0,13,0,0,0,0,0,-3,0,
0,0,0,-11,0,0,0,0,-7,0,0,0,0,-13,0,0,0,0,11,0,0,0,0,-9,0,0,0,0,0,1,0,0,
0,0,0,-15,0,0,0,0,1,0,0,0,0,7,0,0,0,0,0,0,0,0,5,0,0,0,0,0,13,0,0,0,
0,0,0,11,0,0,0,0,0,15,0,0,0,0,0,-9,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,7,
0,0,0,0,0,-15,0,0,0,0,0,15,0,0,0,0,15,0,0,0,0,15,0,0,0,0,0,1,0,0,0,0];
#[test]
fn test_non_adjacent_form() {
let naf = A_SCALAR.non_adjacent_form();
for i in 0..256 {
assert_eq!(naf[i], A_NAF[i]);
}
}
#[test]
fn test_scalar_multiply_by_one() {
let one = Scalar::one();
let zero = Scalar::zero();
let test_scalar = Scalar::multiply_add(&X, &one, &zero);
for i in 0..32 {
assert!(test_scalar[i] == X[i]);
}
}
#[test]
fn test_scalar_multiply_only() {
let zero = Scalar::zero();
let test_scalar = Scalar::multiply_add(&X, &Y, &zero);
for i in 0..32 {
assert!(test_scalar[i] == X_TIMES_Y[i]);
}
}
#[test]
fn test_scalar_multiply_add() {
let test_scalar = Scalar::multiply_add(&X, &Y, &Z);
for i in 0..32 {
assert!(test_scalar[i] == W[i]);
}
}
#[test]
fn test_scalar_reduce() {
let mut bignum = [0u8;64];
// set bignum = x + 2^256x
for i in 0..32 {
bignum[ i] = X[i];
bignum[32+i] = X[i];
}
// 3958878930004874126169954872055634648693766179881526445624823978500314864344
// = x + 2^256x (mod l)
let reduced = Scalar([216, 154, 179, 139, 210, 121, 2, 71,
69, 99, 158, 216, 23, 173, 63, 100,
204, 0, 91, 50, 219, 153, 57, 249,
28, 82, 31, 197, 100, 165, 192, 8]);
let test_red = Scalar::reduce(&bignum);
for i in 0..32 {
assert!(test_red[i] == reduced[i]);
}
}
}

68
src/util.rs Normal file
View file

@ -0,0 +1,68 @@
// -*- mode: rust; -*-
//
// To the extent possible under law, the authors have waived all copyright and
// related or neighboring rights to curve25519-dalek, using the Creative
// Commons "CC0" public domain dedication. See
// <http://creativecommons.org/publicdomain/zero/.0/> for full details.
//
// Authors:
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
// - Henry de Valence <hdevalence@hdevalence.ca>
//! Utility functions and tools for constant-time comparisons.
/// Check equality of two bytes in constant time.
///
/// # Return
///
/// Returns 1 if `a == b` and 0 otherwise.
#[inline(always)]
pub fn bytes_equal_ct(a: u8, b: u8) -> u8 {
let mut x: u8;
x = !(a ^ b);
x &= x >> 4;
x &= x >> 2;
x &= x >> 1;
x
}
/// Test if a byte is non-zero in constant time.
///
/// ```rust,ignore
/// let mut x: u8;
/// x = 0;
/// assert!(byte_is_nonzero(x));
/// x = 3;
/// assert!(byte_is_nonzero(x) == 1);
/// ```
///
/// # Return
///
/// * If b != 0, returns 1u8.
/// * If b == 0, returns 0u8.
#[inline(always)]
pub fn byte_is_nonzero(b: u8) -> u8 {
let mut x = b;
x |= x >> 4;
x |= x >> 2;
x |= x >> 1;
(x & 1)
}
/// Check equality of two 32-byte arrays in constant time.
///
/// # Return
///
/// Returns 1 if `a == b` and 0 otherwise.
#[inline(always)]
// We don't use this in curve25519-dalek, but it's useful for e.g. an ed25519 implementation.
#[allow(dead_code)]
pub fn arrays_equal_ct(a: &[u8; 32], b: &[u8; 32]) -> u8 {
let mut x: u8 = 0;
for i in 0..32 {
x |= a[i] ^ b[i];
}
bytes_equal_ct(x, 0)
}