use qssh::{QsshConfig, PqAlgorithm};
use qssh::crypto::PqKeyExchange;
use qssh::handshake::{ClientHandshake, ServerHandshake};
use qssh::transport::protocol::*;
use tokio::net::{TcpListener, TcpStream};
use tokio::time::{timeout, Duration};
use pqcrypto_traits::sign::PublicKey as SignPublicKey;
#[cfg(test)]
mod message_exchange_tests {
use super::*;
use bincode;
#[test]
fn test_client_hello_serialization() {
let msg = ClientHelloMessage {
version: PROTOCOL_VERSION,
random: [0x42; 32],
kex_algorithms: vec![PqAlgorithm::Falcon512, PqAlgorithm::SphincsPlus],
sig_algorithms: vec![PqAlgorithm::SphincsPlus, PqAlgorithm::Falcon512],
ciphers: vec!["aes256-gcm".to_string()],
qkd_capable: true,
extensions: vec![Extension::MaxPacketSize(65536)],
};
let serialized = bincode::serialize(&msg).unwrap();
let deserialized: ClientHelloMessage = bincode::deserialize(&serialized).unwrap();
assert_eq!(msg.version, deserialized.version);
assert_eq!(msg.random, deserialized.random);
assert_eq!(msg.kex_algorithms, deserialized.kex_algorithms);
assert_eq!(msg.qkd_capable, deserialized.qkd_capable);
}
#[test]
fn test_server_hello_with_falcon() {
let kex = PqKeyExchange::new().unwrap();
let (key_share, signature) = kex.create_key_share().unwrap();
let msg = ServerHelloMessage {
version: PROTOCOL_VERSION,
random: [0x33; 32],
selected_kex: PqAlgorithm::Falcon512,
selected_sig: PqAlgorithm::SphincsPlus,
selected_cipher: "aes256-gcm".to_string(),
falcon_public_key: kex.falcon_pk.as_bytes().to_vec(),
key_share,
key_share_signature: signature,
qkd_endpoint: Some("https://qkd.local:8443".to_string()),
extensions: vec![],
};
let serialized = bincode::serialize(&msg).unwrap();
let deserialized: ServerHelloMessage = bincode::deserialize(&serialized).unwrap();
assert_eq!(msg.selected_kex, deserialized.selected_kex);
assert_eq!(msg.falcon_public_key, deserialized.falcon_public_key);
assert_eq!(msg.key_share, deserialized.key_share);
assert_eq!(msg.key_share_signature, deserialized.key_share_signature);
}
#[test]
fn test_key_exchange_message() {
let kex = PqKeyExchange::new().unwrap();
let (key_share, signature) = kex.create_key_share().unwrap();
let msg = KeyExchangeMessage {
falcon_public_key: kex.falcon_pk.as_bytes().to_vec(),
key_share,
key_share_signature: signature,
sphincs_public_key: kex.sphincs_pk.as_bytes().to_vec(),
qkd_proof: Some(vec![0x00; 256]), };
let serialized = bincode::serialize(&msg).unwrap();
let deserialized: KeyExchangeMessage = bincode::deserialize(&serialized).unwrap();
assert_eq!(msg.falcon_public_key, deserialized.falcon_public_key);
assert_eq!(msg.sphincs_public_key, deserialized.sphincs_public_key);
assert_eq!(msg.qkd_proof, deserialized.qkd_proof);
}
}
#[cfg(test)]
mod protocol_flow_tests {
use super::*;
use std::sync::Arc;
use tokio::sync::Mutex;
#[tokio::test]
async fn test_message_ordering() {
let messages = Arc::new(Mutex::new(Vec::new()));
let msgs = messages.clone();
msgs.lock().await.push("ClientHello");
msgs.lock().await.push("ServerHello");
msgs.lock().await.push("KeyExchange");
msgs.lock().await.push("Auth");
let order = messages.lock().await;
assert_eq!(order[0], "ClientHello");
assert_eq!(order[1], "ServerHello");
assert_eq!(order[2], "KeyExchange");
assert_eq!(order[3], "Auth");
}
}
#[cfg(test)]
mod error_scenarios {
use super::*;
#[test]
fn test_version_mismatch() {
let wrong_version = (99, 99);
let msg = ClientHelloMessage {
version: wrong_version,
random: [0x00; 32],
kex_algorithms: vec![PqAlgorithm::Falcon512],
sig_algorithms: vec![PqAlgorithm::SphincsPlus],
ciphers: vec!["aes256-gcm".to_string()],
qkd_capable: false,
extensions: vec![],
};
assert_ne!(msg.version, PROTOCOL_VERSION);
}
#[test]
fn test_unsupported_algorithms() {
let msg = ClientHelloMessage {
version: PROTOCOL_VERSION,
random: [0x00; 32],
kex_algorithms: vec![], sig_algorithms: vec![],
ciphers: vec![],
qkd_capable: false,
extensions: vec![],
};
assert!(msg.kex_algorithms.is_empty());
assert!(msg.sig_algorithms.is_empty());
assert!(msg.ciphers.is_empty());
}
#[test]
fn test_disconnect_message() {
let disconnect = DisconnectMessage {
reason_code: disconnect_reasons::KEY_EXCHANGE_FAILED,
description: "Falcon signature verification failed".to_string(),
};
assert_eq!(disconnect.reason_code, disconnect_reasons::KEY_EXCHANGE_FAILED);
assert!(disconnect.description.contains("Falcon"));
}
}