Skip to content

Commit

Permalink
revert x25519 interface changes
Browse files Browse the repository at this point in the history
  • Loading branch information
jmwample committed Jun 26, 2024
1 parent 545f4d1 commit 1718ad9
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 158 deletions.
2 changes: 1 addition & 1 deletion curve25519-dalek/src/montgomery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ mod test {

#[test]
#[cfg(feature = "alloc")]
#[cfg(feature = "elligator2")]
#[cfg(feature = "digest")]
fn montgomery_elligator_correct() {
let bytes: Vec<u8> = (0u8..32u8).collect();
let bits_in: [u8; 32] = (&bytes[..]).try_into().expect("Range invariant broken");
Expand Down
1 change: 0 additions & 1 deletion x25519-dalek/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
// README.md as the crate documentation.

#![no_std]
#![cfg_attr(feature = "bench", feature(test))]
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg, doc_cfg_hide))]
#![cfg_attr(docsrs, doc(cfg_hide(docsrs)))]
#![deny(missing_docs)]
Expand Down
163 changes: 7 additions & 156 deletions x25519-dalek/src/x25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ impl AsRef<[u8]> for PublicKey {
/// secret is used at most once.
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
#[cfg_attr(feature = "zeroize", zeroize(drop))]
pub struct EphemeralSecret(pub(crate) [u8; 32], pub(crate) u8);
pub struct EphemeralSecret(pub(crate) [u8; 32]);

impl EphemeralSecret {
/// Perform a Diffie-Hellman key agreement between `self` and
Expand All @@ -94,13 +94,8 @@ impl EphemeralSecret {
pub fn random_from_rng<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
// The secret key is random bytes. Clamping is done later.
let mut bytes = [0u8; 32];
let mut tweak = [0u8; 1];
csprng.fill_bytes(&mut bytes);
if cfg!(feature = "elligator2") {
// read an extra byte for elligator representative randomness
csprng.fill_bytes(&mut tweak);
}
EphemeralSecret(bytes, tweak[0])
EphemeralSecret(bytes)
}

/// Generate a new [`EphemeralSecret`].
Expand Down Expand Up @@ -139,7 +134,7 @@ impl<'a> From<&'a EphemeralSecret> for PublicKey {
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
#[cfg_attr(feature = "zeroize", zeroize(drop))]
#[derive(Clone)]
pub struct ReusableSecret(pub(crate) [u8; 32], pub(crate) u8);
pub struct ReusableSecret(pub(crate) [u8; 32]);

#[cfg(feature = "reusable_secrets")]
impl ReusableSecret {
Expand All @@ -162,13 +157,8 @@ impl ReusableSecret {
pub fn random_from_rng<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
// The secret key is random bytes. Clamping is done later.
let mut bytes = [0u8; 32];
let mut tweak = [0u8; 1];
csprng.fill_bytes(&mut bytes);
if cfg!(feature = "elligator2") {
// read an extra byte for elligator representative randomness
csprng.fill_bytes(&mut tweak);
}
ReusableSecret(bytes, tweak[0])
ReusableSecret(bytes)
}

/// Generate a new [`ReusableSecret`].
Expand Down Expand Up @@ -205,7 +195,7 @@ impl<'a> From<&'a ReusableSecret> for PublicKey {
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
#[cfg_attr(feature = "zeroize", zeroize(drop))]
#[derive(Clone)]
pub struct StaticSecret([u8; 32], u8);
pub struct StaticSecret([u8; 32]);

#[cfg(feature = "static_secrets")]
impl StaticSecret {
Expand All @@ -228,13 +218,8 @@ impl StaticSecret {
pub fn random_from_rng<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
// The secret key is random bytes. Clamping is done later.
let mut bytes = [0u8; 32];
let mut tweak = [0u8; 1];
csprng.fill_bytes(&mut bytes);
if cfg!(feature = "elligator2") {
// read an extra byte for elligator representative randomness
csprng.fill_bytes(&mut tweak);
}
StaticSecret(bytes, tweak[0])
StaticSecret(bytes)
}

/// Generate a new [`StaticSecret`].
Expand All @@ -260,7 +245,7 @@ impl StaticSecret {
impl From<[u8; 32]> for StaticSecret {
/// Load a secret key from a byte array.
fn from(bytes: [u8; 32]) -> StaticSecret {
StaticSecret(bytes, 0u8)
StaticSecret(bytes)
}
}

Expand Down Expand Up @@ -390,137 +375,3 @@ pub fn x25519(k: [u8; 32], u: [u8; 32]) -> [u8; 32] {
pub const X25519_BASEPOINT_BYTES: [u8; 32] = [
9, 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,
];

/// [`PublicKey`] transformation to a format indistinguishable from uniform
/// random. Requires feature `elligator2`.
///
/// This allows public keys to be sent over an insecure channel without
/// revealing that an x25519 public key is being shared.
///
/// # Example
#[cfg_attr(feature = "elligator2", doc = "```")]
#[cfg_attr(not(feature = "elligator2"), doc = "```ignore")]
/// use rand_core::OsRng;
/// use rand_core::RngCore;
///
/// use x25519_dalek::x25519;
/// use x25519_dalek::EphemeralSecret;
/// use x25519_dalek::{PublicKey, PublicRepresentative};
///
/// // ~50% of points are not encodable as elligator representatives, but we
/// // want to ensure we select a keypair that is.
/// fn get_representable_ephemeral() -> EphemeralSecret {
/// for i in 0_u8..255 {
/// let secret = EphemeralSecret::random_from_rng(&mut OsRng);
/// match Option::<PublicRepresentative>::from(&secret) {
/// Some(_) => return secret,
/// None => continue,
/// }
/// }
/// panic!("we should definitely have found a key by now")
/// }
///
/// // Generate Alice's key pair.
/// let alice_secret = get_representable_ephemeral();
/// let alice_representative = Option::<PublicRepresentative>::from(&alice_secret).unwrap();
///
/// // Generate Bob's key pair.
/// let bob_secret = get_representable_ephemeral();
/// let bob_representative = Option::<PublicRepresentative>::from(&bob_secret).unwrap();
///
/// // Alice and Bob should now exchange their representatives and reveal the
/// // public key from the other person.
/// let bob_public = PublicKey::from(&bob_representative);
///
/// let alice_public = PublicKey::from(&alice_representative);
///
/// // Once they've done so, they may generate a shared secret.
/// let alice_shared = alice_secret.diffie_hellman(&bob_public);
/// let bob_shared = bob_secret.diffie_hellman(&alice_public);
///
/// assert_eq!(alice_shared.as_bytes(), bob_shared.as_bytes());
/// ```
#[cfg(feature = "elligator2")]
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub struct PublicRepresentative([u8; 32]);

#[cfg(feature = "elligator2")]
impl PublicRepresentative {
/// View this public representative as a byte array.
#[inline]
pub fn as_bytes(&self) -> &[u8; 32] {
&self.0
}

/// Extract this representative's bytes for serialization.
#[inline]
pub fn to_bytes(&self) -> [u8; 32] {
self.0
}
}

#[cfg(feature = "elligator2")]
impl AsRef<[u8]> for PublicRepresentative {
/// View this shared secret key as a byte array.
#[inline]
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}

#[cfg(feature = "elligator2")]
impl From<[u8; 32]> for PublicRepresentative {
/// Build a Elligator2 Public key Representative from bytes
fn from(r: [u8; 32]) -> PublicRepresentative {
PublicRepresentative(r)
}
}

#[cfg(feature = "elligator2")]
impl<'a> From<&'a [u8; 32]> for PublicRepresentative {
/// Build a Elligator2 Public key Representative from bytes by reference
fn from(r: &'a [u8; 32]) -> PublicRepresentative {
PublicRepresentative(*r)
}
}

#[cfg(feature = "elligator2")]
impl<'a> From<&'a EphemeralSecret> for Option<PublicRepresentative> {
/// Given an x25519 [`EphemeralSecret`] key, compute its corresponding [`PublicRepresentative`].
fn from(secret: &'a EphemeralSecret) -> Option<PublicRepresentative> {
let repres = curve25519_dalek::elligator2::representative_from_privkey(&secret.0, secret.1);
let res: Option<[u8; 32]> = repres;
Some(PublicRepresentative(res?))
}
}

#[cfg(feature = "reusable_secrets")]
#[cfg(feature = "elligator2")]
impl<'a> From<&'a ReusableSecret> for Option<PublicRepresentative> {
/// Given an x25519 [`ReusableSecret`] key, compute its corresponding [`PublicRepresentative`].
fn from(secret: &'a ReusableSecret) -> Option<PublicRepresentative> {
let repres = curve25519_dalek::elligator2::representative_from_privkey(&secret.0, secret.1);
let res: Option<[u8; 32]> = repres;
Some(PublicRepresentative(res?))
}
}

#[cfg(feature = "static_secrets")]
#[cfg(feature = "elligator2")]
impl<'a> From<&'a StaticSecret> for Option<PublicRepresentative> {
/// Given an x25519 [`StaticSecret`] key, compute its corresponding [`PublicRepresentative`].
fn from(secret: &'a StaticSecret) -> Option<PublicRepresentative> {
let repres = curve25519_dalek::elligator2::representative_from_privkey(&secret.0, secret.1);
let res: Option<[u8; 32]> = repres;
Some(PublicRepresentative(res?))
}
}

#[cfg(feature = "elligator2")]
impl<'a> From<&'a PublicRepresentative> for PublicKey {
/// Given an elligator2 [`PublicRepresentative`], compute its corresponding [`PublicKey`].
fn from(representative: &'a PublicRepresentative) -> PublicKey {
let point = MontgomeryPoint::map_to_point(&representative.0);
PublicKey(point)
}
}

0 comments on commit 1718ad9

Please sign in to comment.