diff --git a/src/curve.rs b/src/curve.rs index 34085d4..8130d24 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -79,7 +79,7 @@ use core::fmt::Debug; use core::iter::Iterator; -use core::ops::{Add, Sub, Neg, Index}; +use core::ops::{Add, Sub, Neg}; use core::cmp::{PartialEq, Eq}; use constants; @@ -106,21 +106,18 @@ pub struct CompressedEdwardsY(pub [u8; 32]); impl Debug for CompressedEdwardsY { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "CompressedPoint: {:?}", &self.0[..]) - } -} - -impl Index for CompressedEdwardsY { - type Output = u8; - - fn index<'a>(&'a self, _index: usize) -> &'a u8 { - let ret: &'a u8 = &(self.0[_index]); - ret + write!(f, "CompressedPoint: {:?}", self.as_bytes()) } } impl CompressedEdwardsY { /// View this `CompressedEdwardsY` as an array of bytes. + pub fn as_bytes<'a>(&'a self) -> &'a [u8;32] { + &self.0 + } + + /// Copy this `CompressedEdwardsY` to an array of bytes. + /// XXX is this useful? pub fn to_bytes(&self) -> [u8;32] { self.0 } @@ -130,7 +127,7 @@ impl CompressedEdwardsY { /// Returns `None` if the input is not the `y`-coordinate of a /// curve point. pub fn decompress(&self) -> Option { // FromBytes() - let Y = FieldElement::from_bytes(&self.0); + let Y = FieldElement::from_bytes(self.as_bytes()); let Z = FieldElement::one(); let YY = Y.square(); let u = &YY - &Z; // u = y²-1 @@ -140,7 +137,7 @@ impl CompressedEdwardsY { if is_nonzero_square != 1u8 { return None; } // Flip the sign of X if it's not correct - let compressed_sign_bit = self[31] >> 7; + let compressed_sign_bit = self.as_bytes()[31] >> 7; let current_sign_bit = X.is_negative_ed25519(); X.conditional_negate(current_sign_bit ^ compressed_sign_bit); @@ -221,6 +218,15 @@ pub trait Identity { fn identity() -> Self; } +impl Identity for CompressedEdwardsY { + fn identity() -> CompressedEdwardsY { + CompressedEdwardsY([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]) + } +} + impl Identity for ExtendedPoint { fn identity() -> ExtendedPoint { ExtendedPoint{ X: FieldElement::zero(), @@ -317,7 +323,8 @@ impl CTAssignable for AffineNielsPoint { impl CTEq for ExtendedPoint { fn ct_eq(&self, other: &ExtendedPoint) -> u8 { - arrays_equal_ct(&self.compress().0, &other.compress().0) + arrays_equal_ct( self.compress().as_bytes(), + other.compress().as_bytes()) } } @@ -977,7 +984,7 @@ mod test { /// Test sign handling in decompression #[test] fn test_decompression_sign_handling() { - let mut m_bp_bytes: [u8;32] = BASE_CMPRSSD.to_bytes().clone(); + let mut m_bp_bytes: [u8;32] = BASE_CMPRSSD.as_bytes().clone(); // Set the high bit of the last byte to flip the sign m_bp_bytes[31] |= 1 << 7; let m_bp = CompressedEdwardsY(m_bp_bytes).decompress().unwrap(); @@ -1163,6 +1170,12 @@ mod test { assert!(p2.is_small_order() == false); } + #[test] + fn test_compressed_identity() { + assert_eq!(ExtendedPoint::identity().compress(), + CompressedEdwardsY::identity()); + } + #[test] fn test_is_identity() { assert!(ExtendedPoint::identity().is_identity()); diff --git a/src/decaf.rs b/src/decaf.rs index 1b777c9..93f22e2 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -50,15 +50,15 @@ pub struct CompressedDecaf(pub [u8; 32]); /// The result of compressing a `DecafPoint`. impl CompressedDecaf { /// View this `CompressedDecaf` as an array of bytes. - pub fn to_bytes(&self) -> [u8;32] { - self.0 + pub fn as_bytes<'a>(&'a self) -> &'a [u8;32] { + &self.0 } /// Attempt to decompress to an `DecafPoint`. pub fn decompress(&self) -> Option { // XXX should decoding be CT ? // XXX need to check that xy is nonnegative and reject otherwise - let s = FieldElement::from_bytes(&self.0); + let s = FieldElement::from_bytes(self.as_bytes()); // Check that s = |s| and reject otherwise. let mut abs_s = s; @@ -267,7 +267,7 @@ impl BasepointMult for DecafPoint { impl Debug for CompressedDecaf { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "CompressedDecaf: {:?}", &self.0[..]) + write!(f, "CompressedDecaf: {:?}", self.as_bytes()) } } @@ -308,9 +308,7 @@ mod test { fn test_decaf_decompress_id() { let compressed_id = CompressedDecaf::identity(); let id = compressed_id.decompress().unwrap(); - // This should compress (as ed25519) to the following: - let mut bytes = [0u8; 32]; bytes[0] = 1; - assert_eq!(id.0.compress(), CompressedEdwardsY(bytes)); + assert_eq!(id.0.compress(), CompressedEdwardsY::identity()); } #[test] diff --git a/src/scalar.rs b/src/scalar.rs index 60d92ba..4aed3f4 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -30,8 +30,8 @@ //! limbs. use core::cmp::{Eq, PartialEq}; -use core::ops::{Index, IndexMut}; -use core::ops::{Neg}; +use core::ops::{Neg, Index, IndexMut}; +use core::fmt::Debug; #[cfg(feature = "std")] use rand::Rng; @@ -54,6 +54,12 @@ use subtle::arrays_equal_ct; #[derive(Copy, Clone)] pub struct Scalar(pub [u8; 32]); +impl Debug for Scalar { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "Scalar: {:?}", &self.0[..]) + } +} + impl Eq for Scalar{} impl PartialEq for Scalar { /// Test equality between two `Scalar`s. @@ -194,6 +200,11 @@ impl Scalar { Scalar::reduce(&output) } + /// View this `Scalar` as a sequence of bytes. + pub fn as_bytes<'a>(&'a self) -> &'a [u8;32] { + &self.0 + } + /// Construct the additive identity pub fn zero() -> Self { Scalar([0u8; 32])