//! Integração: handshake sintético (gerado com senha conhecida) -> montagem //! de `CrackTarget` -> `verify()`, para os dois métodos (EAPOL 4-way e //! PMKID), cobrindo senha certa e errada. mod common; use sabia_core::crack::{compute_mic, compute_pmkid, compute_ptk, derive_pmk, CrackTarget}; const BSSID: &str = "00:11:22:33:44:55"; const STATION: &str = "66:77:88:99:aa:bb"; #[test] fn eapol_4way_roundtrip_verifies_password() { let (m1, m2) = common::handshake_frames("MinhaRede", "senha-correta", 2, false); let hs = common::synthetic_handshake("MinhaRede", BSSID, STATION, &m1, &m2); let target = CrackTarget::from_handshake(&hs).expect("alvo EAPOL válido"); assert_eq!(target.method(), "EAPOL/CCMP"); assert!(target.verify("senha-correta")); assert!(!target.verify("senha-errada")); } #[test] fn pmkid_roundtrip_verifies_password() { let (m1, _m2) = common::handshake_frames("MinhaRede", "senha-correta", 2, true); let hs = common::synthetic_handshake("MinhaRede", BSSID, STATION, &m1, &[]); let target = CrackTarget::from_handshake(&hs).expect("alvo PMKID válido"); assert_eq!(target.method(), "PMKID"); assert!(target.verify("senha-correta")); assert!(!target.verify("senha-errada")); } #[test] fn tkip_keyversion_roundtrip_verifies_password() { let (m1, m2) = common::handshake_frames("RedeAntiga", "outra-senha", 1, false); let hs = common::synthetic_handshake("RedeAntiga", BSSID, STATION, &m1, &m2); let target = CrackTarget::from_handshake(&hs).expect("alvo EAPOL/TKIP válido"); assert_eq!(target.method(), "EAPOL/TKIP"); assert!(target.verify("outra-senha")); assert!(!target.verify("senha-errada")); } #[test] fn incomplete_handshake_without_pmkid_or_msg2_has_no_target() { let (m1, _m2) = common::handshake_frames("MinhaRede", "senha-correta", 2, false); // Sem msg2 e sem PMKID: não há prova suficiente para quebrar. let hs = common::synthetic_handshake("MinhaRede", BSSID, STATION, &m1, &[]); assert!(CrackTarget::from_handshake(&hs).is_none()); } #[test] fn derive_pmk_compute_ptk_and_mic_are_consistent() { let ssid = "VetorDireto"; let password = "senha-direta"; let anonce = [0xaa; 32]; let snonce = [0xbb; 32]; let pmk = derive_pmk(password, ssid); let ptk = compute_ptk(&pmk, &common::ap(), &common::sta(), &anonce, &snonce); // MIC calculado sobre um quadro msg2 qualquer, zerando o campo MIC antes. let mut m2 = common::key_frame(2, 2, snonce, &[]); let mic = compute_mic(2, &ptk[..16], &m2, sabia_core::eapol::MIC_OFFSET).expect("mic"); m2[sabia_core::eapol::MIC_OFFSET..sabia_core::eapol::MIC_OFFSET + 16].copy_from_slice(&mic); // Recalculando o MIC sobre o quadro já preenchido deve bater de novo // (compute_mic zera o campo internamente antes de recalcular). let mic_again = compute_mic(2, &ptk[..16], &m2, sabia_core::eapol::MIC_OFFSET).expect("mic"); assert_eq!(mic, mic_again); // PMKID direto também deve ser determinístico e usável no verify(). let pmkid = compute_pmkid(&pmk, &common::ap(), &common::sta()); assert_eq!( pmkid, compute_pmkid(&pmk, &common::ap(), &common::sta()), "PMKID deve ser determinístico" ); }