T1.5: Migrate emit/parse sites to v2 wire format
This commit is contained in:
@@ -156,7 +156,11 @@ mod tests {
|
||||
fn sequential_accepted() {
|
||||
let mut w = AntiReplayWindow::new();
|
||||
for i in 0..200 {
|
||||
assert!(w.check_and_update(i).is_ok(), "seq {} should be accepted", i);
|
||||
assert!(
|
||||
w.check_and_update(i).is_ok(),
|
||||
"seq {} should be accepted",
|
||||
i
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ use ed25519_dalek::{Signer, SigningKey, Verifier, VerifyingKey};
|
||||
use hkdf::Hkdf;
|
||||
use rand::rngs::OsRng;
|
||||
use sha2::{Digest, Sha256};
|
||||
use x25519_dalek::{PublicKey as X25519PublicKey, StaticSecret};
|
||||
use wzp_proto::{CryptoError, CryptoSession, KeyExchange};
|
||||
use x25519_dalek::{PublicKey as X25519PublicKey, StaticSecret};
|
||||
|
||||
use crate::session::ChaChaSession;
|
||||
|
||||
@@ -95,12 +95,11 @@ impl KeyExchange for WarzoneKeyExchange {
|
||||
&self,
|
||||
peer_ephemeral_pub: &[u8; 32],
|
||||
) -> Result<Box<dyn CryptoSession>, CryptoError> {
|
||||
let secret = self
|
||||
.ephemeral_secret
|
||||
.as_ref()
|
||||
.ok_or_else(|| {
|
||||
CryptoError::Internal("no ephemeral key generated; call generate_ephemeral first".into())
|
||||
})?;
|
||||
let secret = self.ephemeral_secret.as_ref().ok_or_else(|| {
|
||||
CryptoError::Internal(
|
||||
"no ephemeral key generated; call generate_ephemeral first".into(),
|
||||
)
|
||||
})?;
|
||||
|
||||
let peer_public = X25519PublicKey::from(*peer_ephemeral_pub);
|
||||
// Use diffie_hellman with a clone of the StaticSecret
|
||||
|
||||
@@ -79,7 +79,9 @@ impl Seed {
|
||||
///
|
||||
/// Mirrors: `warzone-protocol::mnemonic::mnemonic_to_seed`
|
||||
pub fn from_mnemonic(words: &str) -> Result<Self, String> {
|
||||
let mnemonic: bip39::Mnemonic = words.parse().map_err(|e| format!("invalid mnemonic: {e}"))?;
|
||||
let mnemonic: bip39::Mnemonic = words
|
||||
.parse()
|
||||
.map_err(|e| format!("invalid mnemonic: {e}"))?;
|
||||
let entropy = mnemonic.to_entropy();
|
||||
if entropy.len() != 32 {
|
||||
return Err(format!("expected 32 bytes entropy, got {}", entropy.len()));
|
||||
|
||||
@@ -16,8 +16,8 @@ pub mod session;
|
||||
|
||||
pub use anti_replay::AntiReplayWindow;
|
||||
pub use handshake::WarzoneKeyExchange;
|
||||
pub use identity::{hash_room_name, Fingerprint, IdentityKeyPair, PublicIdentity, Seed};
|
||||
pub use nonce::{build_nonce, Direction};
|
||||
pub use identity::{Fingerprint, IdentityKeyPair, PublicIdentity, Seed, hash_room_name};
|
||||
pub use nonce::{Direction, build_nonce};
|
||||
pub use rekey::RekeyManager;
|
||||
pub use session::ChaChaSession;
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
use chacha20poly1305::aead::Aead;
|
||||
use chacha20poly1305::{ChaCha20Poly1305, KeyInit, Nonce};
|
||||
use x25519_dalek::{PublicKey, StaticSecret};
|
||||
use rand::rngs::OsRng;
|
||||
use wzp_proto::{CryptoError, CryptoSession};
|
||||
use x25519_dalek::{PublicKey, StaticSecret};
|
||||
|
||||
use crate::nonce::{self, Direction};
|
||||
use crate::rekey::RekeyManager;
|
||||
@@ -135,7 +135,9 @@ impl CryptoSession for ChaChaSession {
|
||||
.ok_or_else(|| CryptoError::RekeyFailed("no pending rekey".into()))?;
|
||||
|
||||
let total_packets = self.send_seq as u64 + self.recv_seq as u64;
|
||||
let new_key = self.rekey_mgr.perform_rekey(peer_ephemeral_pub, secret, total_packets);
|
||||
let new_key = self
|
||||
.rekey_mgr
|
||||
.perform_rekey(peer_ephemeral_pub, secret, total_packets);
|
||||
self.install_key(new_key);
|
||||
|
||||
// Reset sequence counters after rekey for nonce uniqueness
|
||||
|
||||
@@ -52,7 +52,10 @@ fn wzp_identity_module_matches_featherchat() {
|
||||
assert_eq!(wzp_pub.signing.as_bytes(), fc_pub.signing.as_bytes());
|
||||
assert_eq!(wzp_pub.encryption.as_bytes(), fc_pub.encryption.as_bytes());
|
||||
assert_eq!(wzp_pub.fingerprint.0, fc_pub.fingerprint.0);
|
||||
assert_eq!(wzp_pub.fingerprint.to_string(), fc_pub.fingerprint.to_string());
|
||||
assert_eq!(
|
||||
wzp_pub.fingerprint.to_string(),
|
||||
fc_pub.fingerprint.to_string()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -148,16 +151,25 @@ fn wzp_signal_serializes_into_fc_callsignal_payload() {
|
||||
// And deserializes back
|
||||
let decoded: warzone_protocol::message::WireMessage = bincode::deserialize(&encoded).unwrap();
|
||||
if let warzone_protocol::message::WireMessage::CallSignal {
|
||||
id, payload: p, signal_type, ..
|
||||
id,
|
||||
payload: p,
|
||||
signal_type,
|
||||
..
|
||||
} = decoded
|
||||
{
|
||||
assert_eq!(id, "call-123");
|
||||
assert!(matches!(signal_type, warzone_protocol::message::CallSignalType::Offer));
|
||||
assert!(matches!(
|
||||
signal_type,
|
||||
warzone_protocol::message::CallSignalType::Offer
|
||||
));
|
||||
|
||||
// Decode the WZP payload back
|
||||
let wzp_payload = wzp_client::featherchat::decode_call_payload(&p).unwrap();
|
||||
assert_eq!(wzp_payload.relay_addr.unwrap(), "relay.example.com:4433");
|
||||
assert!(matches!(wzp_payload.signal, wzp_proto::SignalMessage::CallOffer { .. }));
|
||||
assert!(matches!(
|
||||
wzp_payload.signal,
|
||||
wzp_proto::SignalMessage::CallOffer { .. }
|
||||
));
|
||||
} else {
|
||||
panic!("expected CallSignal");
|
||||
}
|
||||
@@ -204,7 +216,10 @@ fn wzp_hangup_round_trips_through_fc_callsignal() {
|
||||
|
||||
let payload = wzp_client::featherchat::encode_call_payload(&hangup, None, None);
|
||||
let signal_type = wzp_client::featherchat::signal_to_call_type(&hangup);
|
||||
assert!(matches!(signal_type, wzp_client::featherchat::CallSignalType::Hangup));
|
||||
assert!(matches!(
|
||||
signal_type,
|
||||
wzp_client::featherchat::CallSignalType::Hangup
|
||||
));
|
||||
|
||||
let fc_msg = warzone_protocol::message::WireMessage::CallSignal {
|
||||
id: "call-789".to_string(),
|
||||
@@ -219,7 +234,10 @@ fn wzp_hangup_round_trips_through_fc_callsignal() {
|
||||
|
||||
if let warzone_protocol::message::WireMessage::CallSignal { payload, .. } = decoded {
|
||||
let wzp = wzp_client::featherchat::decode_call_payload(&payload).unwrap();
|
||||
assert!(matches!(wzp.signal, wzp_proto::SignalMessage::Hangup { .. }));
|
||||
assert!(matches!(
|
||||
wzp.signal,
|
||||
wzp_proto::SignalMessage::Hangup { .. }
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,8 +270,7 @@ fn auth_validate_response_matches_wzp_expectations() {
|
||||
"eth_address": null
|
||||
});
|
||||
|
||||
let wzp_resp: wzp_relay::auth::ValidateResponse =
|
||||
serde_json::from_value(fc_response).unwrap();
|
||||
let wzp_resp: wzp_relay::auth::ValidateResponse = serde_json::from_value(fc_response).unwrap();
|
||||
assert!(wzp_resp.valid);
|
||||
assert_eq!(
|
||||
wzp_resp.fingerprint.unwrap(),
|
||||
@@ -265,8 +282,7 @@ fn auth_validate_response_matches_wzp_expectations() {
|
||||
#[test]
|
||||
fn auth_invalid_response_matches() {
|
||||
let fc_response = serde_json::json!({ "valid": false });
|
||||
let wzp_resp: wzp_relay::auth::ValidateResponse =
|
||||
serde_json::from_value(fc_response).unwrap();
|
||||
let wzp_resp: wzp_relay::auth::ValidateResponse = serde_json::from_value(fc_response).unwrap();
|
||||
assert!(!wzp_resp.valid);
|
||||
assert!(wzp_resp.fingerprint.is_none());
|
||||
}
|
||||
@@ -280,15 +296,18 @@ fn all_signal_types_map_correctly() {
|
||||
let cases: Vec<(wzp_proto::SignalMessage, &str)> = vec![
|
||||
(
|
||||
wzp_proto::SignalMessage::CallOffer {
|
||||
identity_pub: [0; 32], ephemeral_pub: [0; 32],
|
||||
signature: vec![], supported_profiles: vec![],
|
||||
identity_pub: [0; 32],
|
||||
ephemeral_pub: [0; 32],
|
||||
signature: vec![],
|
||||
supported_profiles: vec![],
|
||||
alias: None,
|
||||
},
|
||||
"Offer",
|
||||
),
|
||||
(
|
||||
wzp_proto::SignalMessage::CallAnswer {
|
||||
identity_pub: [0; 32], ephemeral_pub: [0; 32],
|
||||
identity_pub: [0; 32],
|
||||
ephemeral_pub: [0; 32],
|
||||
signature: vec![],
|
||||
chosen_profile: wzp_proto::QualityProfile::GOOD,
|
||||
},
|
||||
@@ -312,7 +331,10 @@ fn all_signal_types_map_correctly() {
|
||||
for (signal, expected_name) in cases {
|
||||
let ct = signal_to_call_type(&signal);
|
||||
let name = format!("{ct:?}");
|
||||
assert_eq!(name, expected_name, "signal type mapping for {expected_name}");
|
||||
assert_eq!(
|
||||
name, expected_name,
|
||||
"signal type mapping for {expected_name}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,8 +448,7 @@ fn auth_response_with_eth_address() {
|
||||
"alias": "vitalik",
|
||||
"eth_address": "0x1234567890abcdef1234567890abcdef12345678"
|
||||
});
|
||||
let resp: wzp_relay::auth::ValidateResponse =
|
||||
serde_json::from_value(with_eth).unwrap();
|
||||
let resp: wzp_relay::auth::ValidateResponse = serde_json::from_value(with_eth).unwrap();
|
||||
assert!(resp.valid);
|
||||
assert_eq!(
|
||||
resp.fingerprint.unwrap(),
|
||||
@@ -442,8 +463,7 @@ fn auth_response_with_eth_address() {
|
||||
"alias": "anon",
|
||||
"eth_address": null
|
||||
});
|
||||
let resp2: wzp_relay::auth::ValidateResponse =
|
||||
serde_json::from_value(with_null_eth).unwrap();
|
||||
let resp2: wzp_relay::auth::ValidateResponse = serde_json::from_value(with_null_eth).unwrap();
|
||||
assert!(resp2.valid);
|
||||
assert_eq!(
|
||||
resp2.fingerprint.unwrap(),
|
||||
@@ -454,8 +474,7 @@ fn auth_response_with_eth_address() {
|
||||
let without_eth = serde_json::json!({
|
||||
"valid": false
|
||||
});
|
||||
let resp3: wzp_relay::auth::ValidateResponse =
|
||||
serde_json::from_value(without_eth).unwrap();
|
||||
let resp3: wzp_relay::auth::ValidateResponse = serde_json::from_value(without_eth).unwrap();
|
||||
assert!(!resp3.valid);
|
||||
}
|
||||
|
||||
@@ -496,7 +515,11 @@ fn all_fc_call_signal_types_representable() {
|
||||
(CallSignalType::Busy, "Busy"),
|
||||
];
|
||||
|
||||
assert_eq!(variants.len(), 7, "featherChat defines exactly 7 call signal types");
|
||||
assert_eq!(
|
||||
variants.len(),
|
||||
7,
|
||||
"featherChat defines exactly 7 call signal types"
|
||||
);
|
||||
|
||||
for (variant, expected_name) in &variants {
|
||||
let name = format!("{variant:?}");
|
||||
@@ -550,10 +573,7 @@ fn hash_room_name_used_as_sni_is_valid() {
|
||||
#[test]
|
||||
fn wzp_proto_cargo_toml_is_standalone() {
|
||||
// Try both paths (run from workspace root or from crate directory)
|
||||
let candidates = [
|
||||
"crates/wzp-proto/Cargo.toml",
|
||||
"../wzp-proto/Cargo.toml",
|
||||
];
|
||||
let candidates = ["crates/wzp-proto/Cargo.toml", "../wzp-proto/Cargo.toml"];
|
||||
|
||||
let contents = candidates
|
||||
.iter()
|
||||
|
||||
Reference in New Issue
Block a user