diff --git a/crates/obfs4/src/common/mod.rs b/crates/obfs4/src/common/mod.rs index 3ea0ed6..ecd3442 100644 --- a/crates/obfs4/src/common/mod.rs +++ b/crates/obfs4/src/common/mod.rs @@ -5,7 +5,7 @@ use hmac::Hmac; use sha2::Sha256; pub(crate) mod ct; -pub(crate) mod curve25519; +pub(crate) mod x25519_elligator2; pub(crate) mod kdf; mod skip; diff --git a/crates/obfs4/src/common/curve25519.rs b/crates/obfs4/src/common/x25519_elligator2.rs similarity index 95% rename from crates/obfs4/src/common/curve25519.rs rename to crates/obfs4/src/common/x25519_elligator2.rs index 1ee28e0..481c09e 100644 --- a/crates/obfs4/src/common/curve25519.rs +++ b/crates/obfs4/src/common/x25519_elligator2.rs @@ -8,7 +8,7 @@ pub use x25519_dalek::{PublicKey, SharedSecret, StaticSecret}; pub use curve25519_elligator2::elligator2::representative_from_privkey; -pub(crate) struct EphemeralSecret (x25519_dalek::EphemeralSecret, u8); +pub(crate) struct EphemeralSecret (x25519_dalek::StaticSecret, u8); impl EphemeralSecret { pub(crate) fn random() -> Self {} @@ -117,7 +117,7 @@ impl<'a> From<&'a [u8; 32]> for PublicRepresentative { impl<'a> From<&'a EphemeralSecret> for Option { /// Given an x25519 [`EphemeralSecret`] key, compute its corresponding [`PublicRepresentative`]. fn from(secret: &'a EphemeralSecret) -> Option { - let repres = representative_from_privkey(&secret.0, secret.1); + let repres = representative_from_privkey(&secret.0.to_bytes(), secret.1); let res: Option<[u8; 32]> = repres; Some(PublicRepresentative(res?)) } @@ -187,7 +187,12 @@ impl Keys { /// Generate a new Elligator2 representable ['StaticSecret']. pub fn random_static() -> StaticSecret { let mut private = StaticSecret::random(); - let mut repres: Option = (&private).into(); + let mut tweak = [0u8]; + getrandom::getrandom(&mut tweak).expect("failed to get random bytes"); + + let mut key = EphemeralSecret(private, tweak[0]); + + let mut repres: Option = &key.into(); for _ in 0..Self::RETRY_LIMIT { if repres.is_some() { diff --git a/crates/obfs4/src/constants.rs b/crates/obfs4/src/constants.rs index db8a870..0982300 100644 --- a/crates/obfs4/src/constants.rs +++ b/crates/obfs4/src/constants.rs @@ -3,7 +3,7 @@ use tor_llcrypto::pk::rsa::RSA_ID_LEN; use crate::{ - common::{curve25519::REPRESENTATIVE_LENGTH, drbg}, + common::{x25519_elligator2::REPRESENTATIVE_LENGTH, drbg}, framing, handshake::AUTHCODE_LENGTH, }; diff --git a/crates/obfs4/src/framing/handshake.rs b/crates/obfs4/src/framing/handshake.rs index 025d225..d242867 100644 --- a/crates/obfs4/src/framing/handshake.rs +++ b/crates/obfs4/src/framing/handshake.rs @@ -1,6 +1,6 @@ use crate::{ common::{ - curve25519::{PublicKey, PublicRepresentative}, + x25519_elligator2::{PublicKey, PublicRepresentative}, HmacSha256, }, constants::*, diff --git a/crates/obfs4/src/framing/messages_v1/crypto.rs b/crates/obfs4/src/framing/messages_v1/crypto.rs index b0058ec..908bd39 100644 --- a/crates/obfs4/src/framing/messages_v1/crypto.rs +++ b/crates/obfs4/src/framing/messages_v1/crypto.rs @@ -58,7 +58,7 @@ impl Message for KyberAcceptMessage { mod tests { use pqc_kyber::*; - use crate::common::curve25519::{PublicKey, Representable}; + use crate::common::x25519_elligator2::{PublicKey, Keys}; use crate::handshake::Obfs4NtorSecretKey; type Result = std::result::Result; @@ -124,7 +124,7 @@ mod tests { let mut rng = rand::thread_rng(); // Generate Keypair - let alice_secret = Representable::ephemeral_from_rng(&mut rng); + let alice_secret = Keys::ephemeral_from_rng(&mut rng); let alice_public = PublicKey::from(&alice_secret); let keys_alice = keypair(&mut rng)?; // alice -> bob public keys @@ -133,7 +133,7 @@ mod tests { assert_eq!(kyber1024x_pubkey.len(), 1600); - let bob_secret = Representable::ephemeral_from_rng(&mut rng); + let bob_secret = Keys::ephemeral_from_rng(&mut rng); let bob_public = PublicKey::from(&bob_secret); // Bob encapsulates a shared secret using Alice's public key diff --git a/crates/obfs4/src/handshake/handshake_client.rs b/crates/obfs4/src/handshake/handshake_client.rs index 1a90edc..0e772d0 100644 --- a/crates/obfs4/src/handshake/handshake_client.rs +++ b/crates/obfs4/src/handshake/handshake_client.rs @@ -1,7 +1,7 @@ use super::*; use crate::{ common::{ - curve25519::{PublicRepresentative, REPRESENTATIVE_LENGTH}, + x25519_elligator2::{PublicRepresentative, REPRESENTATIVE_LENGTH}, HmacSha256, }, framing::handshake::{ClientHandshakeMessage, ServerHandshakeMessage}, @@ -49,7 +49,7 @@ pub(super) fn client_handshake_obfs4( materials: &HandshakeMaterials, ) -> Result<(NtorHandshakeState, Vec)> { let rng = rand::thread_rng(); - let my_sk = Representable::static_from_rng(rng); + let my_sk = Keys::static_from_rng(rng); client_handshake_obfs4_no_keygen(my_sk, materials.clone()) } diff --git a/crates/obfs4/src/handshake/handshake_server.rs b/crates/obfs4/src/handshake/handshake_server.rs index 9303c73..10fa356 100644 --- a/crates/obfs4/src/handshake/handshake_server.rs +++ b/crates/obfs4/src/handshake/handshake_server.rs @@ -1,7 +1,7 @@ use super::*; use crate::{ common::{ - curve25519::{PublicRepresentative, REPRESENTATIVE_LENGTH}, + x25519_elligator2::{PublicRepresentative, REPRESENTATIVE_LENGTH}, HmacSha256, }, framing::{build_and_marshall, ClientHandshakeMessage, MessageTypes, ServerHandshakeMessage}, @@ -56,7 +56,7 @@ impl Server { T: AsRef<[u8]>, { let rng = thread_rng(); - let session_sk = Representable::ephemeral_from_rng(rng); + let session_sk = Keys::ephemeral_from_rng(rng); self.server_handshake_obfs4_no_keygen(session_sk, msg, materials) } diff --git a/crates/obfs4/src/handshake/integration.rs b/crates/obfs4/src/handshake/integration.rs index 0f16d92..ec72da8 100644 --- a/crates/obfs4/src/handshake/integration.rs +++ b/crates/obfs4/src/handshake/integration.rs @@ -267,8 +267,8 @@ fn about_half() -> Result<()> { let mut not_found = 0; let mut not_match = 0; for _ in 0..1_000 { - let sk = curve25519::StaticSecret::random_from_rng(&mut rng); - let rp: Option = (&sk).into(); + let sk = x25519_elligator2::StaticSecret::random_from_rng(&mut rng); + let rp: Option = (&sk).into(); let repres = match rp { Some(r) => r, None => { @@ -277,9 +277,9 @@ fn about_half() -> Result<()> { } }; - let pk = curve25519::PublicKey::from(&sk); + let pk = x25519_elligator2::PublicKey::from(&sk); - let decoded_pk = curve25519::PublicKey::from(&repres); + let decoded_pk = x25519_elligator2::PublicKey::from(&repres); if hex::encode(pk) != hex::encode(decoded_pk) { not_match += 1; continue; @@ -303,9 +303,9 @@ fn keypair() -> Result<()> { let kp = Obfs4NtorSecretKey::generate_for_test(&mut rng); let pk = kp.pk.pk.to_bytes(); - let repres: Option = (&kp.sk).into(); + let repres: Option = (&kp.sk).into(); - let pubkey = curve25519::PublicKey::from(&repres.unwrap()); + let pubkey = x25519_elligator2::PublicKey::from(&repres.unwrap()); assert_eq!(hex::encode(pk), hex::encode(pubkey.to_bytes())); } Ok(()) diff --git a/crates/obfs4/src/handshake/mod.rs b/crates/obfs4/src/handshake/mod.rs index 4a61332..cd714f4 100644 --- a/crates/obfs4/src/handshake/mod.rs +++ b/crates/obfs4/src/handshake/mod.rs @@ -3,7 +3,7 @@ use crate::{ common::{ ct, - curve25519::{EphemeralSecret, PublicKey, Representable, SharedSecret, StaticSecret}, + x25519_elligator2::{EphemeralSecret, PublicKey, Keys, SharedSecret, StaticSecret}, kdf::{Kdf, Ntor1Kdf}, ntor_arti::{ AuxDataReply, ClientHandshake, KeyGenerator, RelayHandshakeError, RelayHandshakeResult, @@ -185,7 +185,7 @@ impl Obfs4NtorSecretKey { /// Construct a new ['Obfs4NtorSecretKey'] from a CSPRNG. pub(crate) fn getrandom() -> Self { - let sk = Representable::random_static(); + let sk = Keys::random_static(); let mut id = [0_u8; NODE_ID_LENGTH]; getrandom::getrandom(&mut id).expect("internal randomness error"); Self::new(sk, RsaIdentity::from(id)) @@ -198,7 +198,7 @@ impl Obfs4NtorSecretKey { // Random bytes will work for testing, but aren't necessarily actually a valid id. rng.fill_bytes(&mut id); - let sk = Representable::static_from_rng(rng); + let sk = Keys::static_from_rng(rng); let pk = Obfs4NtorPublicKey { pk: (&sk).into(), diff --git a/crates/obfs4/src/lib.rs b/crates/obfs4/src/lib.rs index 22daa4a..41d76f1 100644 --- a/crates/obfs4/src/lib.rs +++ b/crates/obfs4/src/lib.rs @@ -50,7 +50,7 @@ pub mod dev { #[cfg(test)] mod test { use super::*; - use crate::common::curve25519::StaticSecret; + use crate::common::x25519_elligator2::StaticSecret; use crate::constants::*; use crate::handshake::Obfs4NtorSecretKey; use crate::{ClientBuilder, ServerBuilder}; diff --git a/crates/obfs4/src/server.rs b/crates/obfs4/src/server.rs index 0c2f3c5..8f237db 100644 --- a/crates/obfs4/src/server.rs +++ b/crates/obfs4/src/server.rs @@ -5,7 +5,7 @@ use crate::{ client::ClientBuilder, common::{ colorize, - curve25519::{PublicKey, StaticSecret}, + x25519_elligator2::{PublicKey, StaticSecret}, drbg, replay_filter::{self, ReplayFilter}, HmacSha256,