From 608634a7bd1075120f3be319a14cd38c7a69c20e Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 15 May 2017 21:06:26 -0700 Subject: [PATCH 01/12] Implement DecafPoint::{random, hash_from_bytes, from_hash} using Decaf-flavoured elligator --- src/curve.rs | 9 +-- src/decaf.rs | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 4 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 552e736..276024c 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -308,11 +308,12 @@ pub struct ProjectivePoint { /// A `CompletedPoint` is a point ((X:Z), (Y:T)) in ๐—ฃยน(๐”ฝโ‚š)ร—๐—ฃยน(๐”ฝโ‚š). /// A point (x,y) in the affine model corresponds to ((x:1),(y:1)). #[derive(Copy, Clone)] +#[allow(missing_docs)] pub struct CompletedPoint { - X: FieldElement, - Y: FieldElement, - Z: FieldElement, - T: FieldElement, + pub X: FieldElement, + pub Y: FieldElement, + pub Z: FieldElement, + pub T: FieldElement, } /// A pre-computed point in the affine model for the curve, represented as diff --git a/src/decaf.rs b/src/decaf.rs index 9d36c10..4106e70 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -24,6 +24,12 @@ use core::fmt::Debug; +#[cfg(feature = "std")] +use rand::Rng; + +use digest::Digest; +use generic_array::typenum::U32; + use constants; use field::FieldElement; use subtle::CTAssignable; @@ -33,7 +39,9 @@ use core::ops::{Add, Sub, Neg}; use core::ops::{Mul, MulAssign}; use curve; +use curve::ValidityCheck; use curve::ExtendedPoint; +use curve::CompletedPoint; use curve::EdwardsBasepointTable; use curve::Identity; use scalar::Scalar; @@ -192,6 +200,140 @@ impl DecafPoint { , &self.0 + &constants::EIGHT_TORSION[6] ] } + + /// Computes the Elligator map as described in the Decaf paper. + /// + /// # Note + /// + /// This method is not public because it's just used for hashing + /// to a point -- proper elligator support is deferred for now. + fn elligator_decaf_flavour(r_0: &FieldElement) -> DecafPoint { + // Follows Appendix C of the Decaf paper. + // Use n = 2 as the quadratic nonresidue so that n*x = x + x. + + // 1. Compute r <--- nr_0^2. + let r_0_squared = r_0.square(); + let r = &r_0_squared + &r_0_squared; + + // 2. Compute D <--- (dr + (a-d)) * (dr - (d + ar)) + let dr = &constants::d * &r; + // D = (dr + (a-d)) * (dr - (d + ar)) = (dr + (a-d))*(dr - (d-r)) since a=-1 + let D = &(&dr + &constants::a_minus_d) * &(&dr - &(&constants::d - &r)); + + // 3. Compute N <--- (r+1) * (a-2d) + let minus_one = -&FieldElement::one(); + let N = &(&r + &FieldElement::one()) * &(&minus_one - &constants::d2); + + // 4. Compute + // / +1, 1 / sqrt(ND) if ND is square + // c, e <--- | +1, 0 if N or D = 0 + // \ -1, nr_0 / sqrt(nND) otherwise + let ND = &N * &D; + let nND = &ND + &ND; + let mut c = FieldElement::one(); + let mut e = FieldElement::zero(); + let (ND_is_nonzero_square, ND_invsqrt) = ND.invsqrt(); + e.conditional_assign(&ND_invsqrt, ND_is_nonzero_square); + let (nND_is_nonzero_square, nND_invsqrt) = nND.invsqrt(); + let nr_0_nND_invsqrt = &nND_invsqrt * &(r_0 + r_0); + c.conditional_assign(&minus_one, nND_is_nonzero_square); + e.conditional_assign(&nr_0_nND_invsqrt, nND_is_nonzero_square); + + // 5. Compute s <--- c*|N*e| + let mut s = &N * &e; + let neg = s.is_negative_decaf(); + s.conditional_negate(neg); + s *= &c; + + // 6. Compute t <--- -c*N*(r-1)* ((a-2d)*e)^2 -1 + let a_minus_2d_e_sq = (&(&minus_one-&constants::d2)*&e).square(); + let c_N_r_minus_1 = &c * &(&N * &(&r + &minus_one)); + let t = &minus_one - &(&c_N_r_minus_1 * &a_minus_2d_e_sq); + + // 7. Apply the isogeny: + // (x,y) = ((2s)/(1+as^2), (1-as^2)/(t)) + let as_sq = &minus_one * &s.square(); + let P = CompletedPoint{ + X: &s + &s, + Z: &FieldElement::one() + &as_sq, + Y: &FieldElement::one() - &as_sq, + T: t, + }; + + // Convert to extended and return. + DecafPoint(P.to_extended()) + } + + /// Return a `DecafPoint` chosen uniformly at random using a user-provided RNG. + /// + /// # Inputs + /// + /// * `rng`: any RNG which implements the `rand::Rng` interface. + /// + /// # Returns + /// + /// A random element of the Decaf group. + /// + /// # Implementation + /// + /// Uses the Decaf-flavoured Elligator 2 map, so that the discrete log of the + /// output point with respect to any other point should be unknown. + #[cfg(feature = "std")] + pub fn random(rng: &mut T) -> Self { + let mut field_bytes = [0u8; 32]; + rng.fill_bytes(&mut field_bytes); + let r_0 = FieldElement::from_bytes(&field_bytes); + DecafPoint::elligator_decaf_flavour(&r_0) + } + + /// Hash a slice of bytes into a `DecafPoint`. + /// + /// Takes a type parameter `D`, which is any `Digest` producing 32 + /// bytes (256 bits) of output. + /// + /// Convenience wrapper around `from_hash`. + /// + /// # Implementation + /// + /// Uses the Decaf-flavoured Elligator 2 map, so that the discrete log of the + /// output point with respect to any other point should be unknown. + /// + /// # Example + /// + /// ``` + /// # extern crate curve25519_dalek; + /// # use curve25519_dalek::decaf::DecafPoint; + /// extern crate sha2; + /// use sha2::Sha256; + /// + /// # // Need fn main() here in comment so the doctest compiles + /// # // See https://doc.rust-lang.org/book/documentation.html#documentation-as-tests + /// # fn main() { + /// let msg = "To really appreciate architecture, you may even need to commit a murder"; + /// let P = DecafPoint::hash_from_bytes::(msg.as_bytes()); + /// # } + /// ``` + /// + pub fn hash_from_bytes(input: &[u8]) -> DecafPoint + where D: Digest + Default { + let mut hash = D::default(); + hash.input(input); + DecafPoint::from_hash(hash) + } + + /// Construct a `DecafPoint` from an existing `Digest` instance. + /// + /// Use this instead of `hash_from_bytes` if it is more convenient + /// to stream data into the `Digest` than to pass a single byte + /// slice. + pub fn from_hash(hash: D) -> DecafPoint + where D: Digest + Default { + // XXX this seems clumsy + let mut output = [0u8; 32]; + output.copy_from_slice(hash.result().as_slice()); + let r_0 = FieldElement::from_bytes(&output); + DecafPoint::elligator_decaf_flavour(&r_0) + } } impl Identity for DecafPoint { @@ -442,6 +584,18 @@ mod test { assert_eq!(P, Q); } } + + #[test] + fn decaf_random_is_valid() { + let mut rng = OsRng::new().unwrap(); + for _ in 0..100 { + let P = DecafPoint::random(&mut rng); + // Check that P is on the curve + assert!(P.0.is_valid()); + // Check that P is in the image of the decaf map + let compressed_P = P.compress(); + } + } } #[cfg(all(test, feature = "bench"))] From 7c32271346caad0b1bfd8dca78eb8c66b4669751 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sat, 13 May 2017 22:40:51 -0700 Subject: [PATCH 02/12] Initial work on Serde support --- Cargo.toml | 9 +++++++ src/curve.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/decaf.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 5 ++++ 4 files changed, 155 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 1e06fd9..eab9733 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,15 @@ exclude = [ [badges] travis-ci = { repository = "isislovecruft/curve25519-dalek", branch = "master"} +[dependencies.serde] +version = "1.0" + +[dependencies.serde_json] +version = "1.0" + +[dependencies.serde_cbor] +version = "0.6" + [dependencies.arrayref] version = "0.3.3" diff --git a/src/curve.rs b/src/curve.rs index 552e736..b516321 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -278,6 +278,59 @@ impl CompressedMontgomeryU { } } +// ------------------------------------------------------------------------ +// Serde support +// ------------------------------------------------------------------------ +// Serializes to and from `ExtendedPoint` directly, doing compression +// and decompression internally. This means that users can create +// structs containing `ExtendedPoint`s and use Serde's derived +// serializers to serialize those structures. + +use serde::{Serialize, Deserialize}; +use serde::{Serializer, Deserializer}; +use serde::de::Visitor; +use serde; + +impl Serialize for ExtendedPoint { + fn serialize(&self, serializer: S) -> Result + where S: Serializer + { + serializer.serialize_bytes(self.compress_edwards().as_bytes()) + } +} + +impl<'de> Deserialize<'de> for ExtendedPoint { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + struct ExtendedPointVisitor; + + impl<'de> Visitor<'de> for ExtendedPointVisitor { + type Value = ExtendedPoint; + + fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + formatter.write_str("a valid point in Edwards y + sign format") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where E: serde::de::Error + { + println!("VISIT_BYTES"); + if v.len() == 32 { + let arr32 = array_ref!(v,0,32); // &[u8;32] from &[u8] + CompressedEdwardsY(*arr32).decompress() + .ok_or(serde::de::Error::custom("decompression failed")) + } else { + Err(serde::de::Error::invalid_length(v.len(), &self)) + } + } + } + + println!("DESERIALIZE"); + deserializer.deserialize_bytes(ExtendedPointVisitor) + } +} + // ------------------------------------------------------------------------ // Internal point representations // ------------------------------------------------------------------------ @@ -1576,6 +1629,29 @@ mod test { assert_eq!(result.compress_edwards(), DOUBLE_SCALAR_MULT_RESULT); } } + + use serde_cbor; + + #[test] + fn serde_cbor_basepoint_roundtrip() { + let output = serde_cbor::to_vec(&constants::ED25519_BASEPOINT).unwrap(); + let parsed: ExtendedPoint = serde_cbor::from_slice(&output).unwrap(); + assert_eq!(parsed.compress_edwards(), constants::BASE_CMPRSSD); + } + + /* + use serde_json; + + #[test] + fn serde_json_basepoint_roundtrip() { + let output = serde_json::to_string(&constants::ED25519_BASEPOINT).unwrap(); + println!("{:?}", output); + println!("{:?}", constants::BASE_CMPRSSD); + let parsed: ExtendedPoint = serde_json::from_str(&output).unwrap(); + println!("{:?}", parsed); + panic!(); + } + */ } // ------------------------------------------------------------------------ diff --git a/src/decaf.rs b/src/decaf.rs index 9d36c10..95eb65c 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -108,6 +108,61 @@ impl Identity for CompressedDecaf { } } +// ------------------------------------------------------------------------ +// Serde support +// ------------------------------------------------------------------------ +// Serializes to and from `DecafPoint` directly, doing compression +// and decompression internally. This means that users can create +// structs containing `DecafPoint`s and use Serde's derived +// serializers to serialize those structures. + +use serde::{Serialize, Deserialize}; +use serde::{Serializer, Deserializer}; +use serde::de::Visitor; +use serde; + +impl Serialize for DecafPoint { + fn serialize(&self, serializer: S) -> Result + where S: Serializer + { + serializer.serialize_bytes(self.compress().as_bytes()) + } +} + +impl<'de> Deserialize<'de> for DecafPoint { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + struct DecafPointVisitor; + + impl<'de> Visitor<'de> for DecafPointVisitor { + type Value = DecafPoint; + + fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + formatter.write_str("a valid point in Decaf format") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where E: serde::de::Error + { + if v.len() == 32 { + let arr32 = array_ref!(v,0,32); // &[u8;32] from &[u8] + CompressedDecaf(*arr32).decompress() + .ok_or(serde::de::Error::custom("decompression failed")) + } else { + Err(serde::de::Error::invalid_length(v.len(), &self)) + } + } + } + + deserializer.deserialize_bytes(DecafPointVisitor) + } +} + +// ------------------------------------------------------------------------ +// Internal point representations +// ------------------------------------------------------------------------ + /// A point in a prime-order group. /// /// XXX think about how this API should work @@ -381,6 +436,16 @@ mod test { use curve::Identity; use super::*; + use serde_cbor; + + #[test] + fn serde_cbor_basepoint_roundtrip() { + let output = serde_cbor::to_vec(&constants::DECAF_ED25519_BASEPOINT).unwrap(); + let parsed: DecafPoint = serde_cbor::from_slice(&output).unwrap(); + assert_eq!(parsed, constants::DECAF_ED25519_BASEPOINT); + } + + #[test] fn decaf_decompress_negative_s_fails() { // constants::d is neg, so decompression should fail as |d| != d. diff --git a/src/lib.rs b/src/lib.rs index 40efe8b..91491d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,11 @@ extern crate arrayref; extern crate generic_array; extern crate digest; +//#[cfg(feature = "serde")] +extern crate serde; +extern crate serde_cbor; +extern crate serde_json; + #[cfg(feature = "std")] extern crate core; From 69fd268aa484888ad704b7f433570524ac9046c9 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 14 May 2017 18:06:59 -0700 Subject: [PATCH 03/12] Make serde an optional feature --- .travis.yml | 1 + Cargo.toml | 10 ++++------ src/curve.rs | 12 ++++++++---- src/decaf.rs | 10 +++++++--- src/lib.rs | 4 ++-- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 709f428..f9f46f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ rust: env: - TEST_COMMAND=test FEATURES=--features="yolocrypto" + - TEST_COMMAND=test FEATURES=--features="yolocrypto serde" - TEST_COMMAND=test FEATURES=--features="yolocrypto nightly" - TEST_COMMAND=bench FEATURES=--features="yolocrypto bench" - TEST_COMMAND=bench FEATURES=--features="yolocrypto nightly bench" diff --git a/Cargo.toml b/Cargo.toml index eab9733..5bdd3bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,12 +20,7 @@ travis-ci = { repository = "isislovecruft/curve25519-dalek", branch = "master"} [dependencies.serde] version = "1.0" - -[dependencies.serde_json] -version = "1.0" - -[dependencies.serde_cbor] -version = "0.6" +optional = true [dependencies.arrayref] version = "0.3.3" @@ -44,6 +39,9 @@ version = "^0.6" [dev-dependencies.sha2] version = "0.4" +[dev-dependencies.serde_cbor] +version = "0.6" + [features] nightly = ["radix_51"] default = ["std"] diff --git a/src/curve.rs b/src/curve.rs index b516321..d191a0f 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -286,11 +286,12 @@ impl CompressedMontgomeryU { // structs containing `ExtendedPoint`s and use Serde's derived // serializers to serialize those structures. -use serde::{Serialize, Deserialize}; -use serde::{Serializer, Deserializer}; +#[cfg(feature = "serde")] +use serde::{self, Serialize, Deserialize, Serializer, Deserializer}; +#[cfg(feature = "serde")] use serde::de::Visitor; -use serde; +#[cfg(feature = "serde")] impl Serialize for ExtendedPoint { fn serialize(&self, serializer: S) -> Result where S: Serializer @@ -299,6 +300,7 @@ impl Serialize for ExtendedPoint { } } +#[cfg(feature = "serde")] impl<'de> Deserialize<'de> for ExtendedPoint { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> @@ -1610,7 +1612,7 @@ mod test { mod vartime { use super::super::*; use super::{A_SCALAR, B_SCALAR, A_TIMES_BASEPOINT, DOUBLE_SCALAR_MULT_RESULT}; - + /// Test double_scalar_mult_vartime vs ed25519.py #[test] fn double_scalar_mult_basepoint_vs_ed25519py() { @@ -1630,9 +1632,11 @@ mod test { } } + #[cfg(feature = "serde")] use serde_cbor; #[test] + #[cfg(feature = "serde")] fn serde_cbor_basepoint_roundtrip() { let output = serde_cbor::to_vec(&constants::ED25519_BASEPOINT).unwrap(); let parsed: ExtendedPoint = serde_cbor::from_slice(&output).unwrap(); diff --git a/src/decaf.rs b/src/decaf.rs index 95eb65c..fa259e5 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -116,11 +116,12 @@ impl Identity for CompressedDecaf { // structs containing `DecafPoint`s and use Serde's derived // serializers to serialize those structures. -use serde::{Serialize, Deserialize}; -use serde::{Serializer, Deserializer}; +#[cfg(feature = "serde")] +use serde::{self, Serialize, Deserialize, Serializer, Deserializer}; +#[cfg(feature = "serde")] use serde::de::Visitor; -use serde; +#[cfg(feature = "serde")] impl Serialize for DecafPoint { fn serialize(&self, serializer: S) -> Result where S: Serializer @@ -129,6 +130,7 @@ impl Serialize for DecafPoint { } } +#[cfg(feature = "serde")] impl<'de> Deserialize<'de> for DecafPoint { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> @@ -436,9 +438,11 @@ mod test { use curve::Identity; use super::*; + #[cfg(feature = "serde")] use serde_cbor; #[test] + #[cfg(feature = "serde")] fn serde_cbor_basepoint_roundtrip() { let output = serde_cbor::to_vec(&constants::DECAF_ED25519_BASEPOINT).unwrap(); let parsed: DecafPoint = serde_cbor::from_slice(&output).unwrap(); diff --git a/src/lib.rs b/src/lib.rs index 91491d5..408d7ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,10 +47,10 @@ extern crate arrayref; extern crate generic_array; extern crate digest; -//#[cfg(feature = "serde")] +#[cfg(feature = "serde")] extern crate serde; +#[cfg(all(test, feature = "serde"))] extern crate serde_cbor; -extern crate serde_json; #[cfg(feature = "std")] extern crate core; From d3515e8cbf82039076ec89e89eeba2c4afc87d4a Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 14 May 2017 21:56:19 -0700 Subject: [PATCH 04/12] Add test that decompressing an invalid point with serde fails --- src/curve.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index d191a0f..67f569f 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1643,19 +1643,16 @@ mod test { assert_eq!(parsed.compress_edwards(), constants::BASE_CMPRSSD); } - /* - use serde_json; - #[test] - fn serde_json_basepoint_roundtrip() { - let output = serde_json::to_string(&constants::ED25519_BASEPOINT).unwrap(); - println!("{:?}", output); - println!("{:?}", constants::BASE_CMPRSSD); - let parsed: ExtendedPoint = serde_json::from_str(&output).unwrap(); - println!("{:?}", parsed); - panic!(); + #[cfg(feature = "serde")] + fn serde_cbor_decode_invalid_fails() { + let mut output = serde_cbor::to_vec(&constants::ED25519_BASEPOINT).unwrap(); + // CBOR apparently has two bytes of overhead for a 32-byte string. + // Set the low byte of the compressed point to 1 to make it invalid. + output[2] = 1; + let parsed: Result = serde_cbor::from_slice(&output); + assert!(parsed.is_err()); } - */ } // ------------------------------------------------------------------------ From 69c62a8a170e25ccbecd8aa1d68b84dd7b036b46 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 15 May 2017 02:54:40 -0700 Subject: [PATCH 05/12] Serde Scalar support --- src/scalar.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/scalar.rs b/src/scalar.rs index 34a45ba..7f90624 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -185,6 +185,50 @@ impl CTAssignable for Scalar { } } +#[cfg(feature = "serde")] +use serde::{self, Serialize, Deserialize, Serializer, Deserializer}; +#[cfg(feature = "serde")] +use serde::de::Visitor; + +#[cfg(feature = "serde")] +impl Serialize for Scalar { + fn serialize(&self, serializer: S) -> Result + where S: Serializer + { + serializer.serialize_bytes(self.as_bytes()) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for Scalar { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + struct ScalarVisitor; + + impl<'de> Visitor<'de> for ScalarVisitor { + type Value = Scalar; + + fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + formatter.write_str("a 32-byte scalar value") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where E: serde::de::Error + { + if v.len() == 32 { + // array_ref turns &[u8] into &[u8;32] + Ok(Scalar(*array_ref!(v,0,32))) + } else { + Err(serde::de::Error::invalid_length(v.len(), &self)) + } + } + } + + deserializer.deserialize_bytes(ScalarVisitor) + } +} + impl Scalar { /// Return a `Scalar` chosen uniformly at random using a user-provided RNG. /// @@ -827,6 +871,17 @@ mod test { assert_eq!(should_be_X, X); } + + #[cfg(feature = "serde")] + use serde_cbor; + + #[test] + #[cfg(feature = "serde")] + fn serde_cbor_scalar_roundtrip() { + let output = serde_cbor::to_vec(&X).unwrap(); + let parsed: Scalar = serde_cbor::from_slice(&output).unwrap(); + assert_eq!(parsed, X); + } } #[cfg(all(test, feature = "bench"))] From aea15e8612e186bf5e88be867e770338c379bf2c Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 15 May 2017 17:53:36 -0700 Subject: [PATCH 06/12] remove debugging println!s --- src/curve.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 67f569f..f8a6edd 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -317,7 +317,6 @@ impl<'de> Deserialize<'de> for ExtendedPoint { fn visit_bytes(self, v: &[u8]) -> Result where E: serde::de::Error { - println!("VISIT_BYTES"); if v.len() == 32 { let arr32 = array_ref!(v,0,32); // &[u8;32] from &[u8] CompressedEdwardsY(*arr32).decompress() @@ -328,7 +327,6 @@ impl<'de> Deserialize<'de> for ExtendedPoint { } } - println!("DESERIALIZE"); deserializer.deserialize_bytes(ExtendedPointVisitor) } } From 0b70ab36382b52a24aeb1d4161d06e894af9b278 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Thu, 18 May 2017 02:57:10 +0000 Subject: [PATCH 07/12] Move `DecafPoint * Scalar` definition to decaf module. --- src/curve.rs | 10 ---------- src/decaf.rs | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 870d82d..ce09627 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -897,16 +897,6 @@ impl<'a, 'b> Mul<&'b ExtendedPoint> for &'a Scalar { } } -#[cfg(feature = "yolocrypto")] -impl<'a, 'b> Mul<&'b DecafPoint> for &'a Scalar { - type Output = DecafPoint; - - /// Scalar multiplication: compute `self * scalar`. - fn mul(self, point: &'b DecafPoint) -> DecafPoint { - DecafPoint(self * &point.0) - } -} - /// Precomputation #[derive(Clone)] diff --git a/src/decaf.rs b/src/decaf.rs index 07c24c6..1b9cccb 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -458,6 +458,16 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a DecafPoint { } } +impl<'a, 'b> Mul<&'b DecafPoint> for &'a Scalar { + type Output = DecafPoint; + + /// Scalar multiplication: compute `self * scalar`. + fn mul(self, point: &'b DecafPoint) -> DecafPoint { + DecafPoint(self * &point.0) + } +} + + /// Precomputation #[derive(Clone)] pub struct DecafBasepointTable(pub EdwardsBasepointTable); From 891cf76aab5f315cc206ff153916d6f3a4526df0 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Thu, 18 May 2017 03:42:31 +0000 Subject: [PATCH 08/12] Remove unused imports in curve::bench module. --- src/curve.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/curve.rs b/src/curve.rs index ce09627..3575af7 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1654,7 +1654,7 @@ mod bench { use test::Bencher; use constants; use super::*; - use super::test::{A_SCALAR, A_TIMES_BASEPOINT, B_SCALAR}; + use super::test::{A_SCALAR}; #[bench] fn basepoint_mult(b: &mut Bencher) { From 767c99adf5b2e878963b1ecac9bdde7683f1e67e Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Thu, 18 May 2017 03:43:15 +0000 Subject: [PATCH 09/12] Remove unused assignment in a decaf test. --- src/decaf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/decaf.rs b/src/decaf.rs index 1b9cccb..414f921 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -672,7 +672,7 @@ mod test { // Check that P is on the curve assert!(P.0.is_valid()); // Check that P is in the image of the decaf map - let compressed_P = P.compress(); + P.compress(); } } } From cc86091224220a5426b79b5c7a2c69f8e0916fcd Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Thu, 18 May 2017 03:43:42 +0000 Subject: [PATCH 10/12] Remove unused import of DecafPoint in curve module. --- src/curve.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 3575af7..a9387a6 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -87,8 +87,6 @@ use core::ops::{Mul, MulAssign}; use core::ops::Index; use constants; -#[cfg(feature = "yolocrypto")] -use decaf::DecafPoint; use field::FieldElement; use scalar::Scalar; use subtle::arrays_equal_ct; From b97868beb80170e734563d2ba8a546acfa40c90d Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Thu, 18 May 2017 03:44:42 +0000 Subject: [PATCH 11/12] Remove unused import of ExtendedPoint in decaf::test module. --- src/decaf.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/decaf.rs b/src/decaf.rs index 414f921..a97347f 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -586,7 +586,6 @@ mod test { use scalar::Scalar; use constants; use curve::CompressedEdwardsY; - use curve::ExtendedPoint; use curve::Identity; use super::*; From 562318d4b89c8195a7deb6aa28834421c3856883 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Thu, 18 May 2017 06:25:58 +0000 Subject: [PATCH 12/12] Bump curve25519-dalek version to 0.8.0. --- Cargo.toml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5bdd3bc..f2f6534 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "curve25519-dalek" -version = "0.7.1" +version = "0.8.0" authors = ["Isis Lovecruft ", "Henry de Valence "] readme = "README.md" diff --git a/README.md b/README.md index ecd519f..7258558 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Extensive documentation is available [here](https://docs.rs/curve25519-dalek). To install, add the following to the dependencies section of your project's `Cargo.toml`: - curve25519-dalek = "^0.7" + curve25519-dalek = "^0.8" Then, in your library or executable source, add: