wifit3 WPA PSK密钥派生实现:PBKDF2、PRF-512与EAPOL MIC纯Python解析
【免费下载链接】wifit3Wifite but USB-only & cross-platform.项目地址: https://gitcode.com/GitHub_Trending/wi/wifit3
wifit3 是一款跨平台的 USB Wi-Fi 安全审计工具(Wifite 的纯 Python 实现),其 src/wifit3/crack/wpa_psk.py 模块用不到 50 行代码完整实现了 WPA/WPA2-PSK 的密钥派生链:从口令(PSK)经PBKDF2派生 PMK,再用PRF-512扩展出 PTK,最后计算EAPOL MIC校验值——全程零第三方加密依赖,只用了标准库的hashlib与hmac。本文带你读懂这条链路的每一步,以及它在抓包破解流程中如何被验证与复用。
为什么值得读这段纯Python实现?
多数 Wi-Fi 工具(如 Aircrack-ng)把密钥派生封装在 C 库或内核里,新手很难看清"口令 → 握手校验"的全貌。wifit3 把整条链路摊开在 Python 源码中:
- 零运行时依赖:不引入任何加密库,
hashlib一把梭; - 可测试:用 IEEE 802.11i 附录 J 的官方测试向量逐字节比对;
- 可复用:同一份代码既用于离线验证握手是否可破解,也用于伪造 AP 应答 M2 消息。
密钥派生全链路:PSK → PMK → PTK → MIC
一条链共四步,对应 wpa_psk.py 中的四个函数:
| 步骤 | 算法 | 输出 | 源码函数 |
|---|---|---|---|
| 1. PSK 扩展 | PBKDF2-HMAC-SHA1,4096 轮 | 32 字节 PMK | pmk() |
| 2. PTK 派生 | PRF-512(HMAC-SHA1 迭代) | 48 字节 PTK | ptk() |
| 3. 取 MIC 密钥 | 截取 PTK 前 16 字节 | 16 字节 KCK | kck() |
| 4. 计算校验 | HMAC-SHA1 取前 16 字节 | EAPOL MIC | eapol_mic() |
第一步:PBKDF2 把口令变成 PMK
PMK(Pairwise Master Key)由口令 + SSID 通过 PBKDF2-HMAC-SHA1 迭代 4096 轮得到:
def pmk(psk: str, ssid: str) -> bytes: return hashlib.pbkdf2_hmac("sha1", psk.encode(), ssid.encode(), 4096, 32)两个要点:
- SSID 充当加盐因子(salt)——同一个口令在不同 SSID 下派生出不同的 PMK,所以 hashcat 破解时必须提供 SSID;
- 4096 轮迭代刻意很慢——这正是 WPA 口令离线爆破单卡速度远低于 MD5/SHA1 的原因。
第二步:PRF-512 扩展出 PTK
PRF-512 是 802.11i 定义的伪随机函数:以 PMK 为密钥,反复对"标签 + 数据 + 计数器"做 HMAC-SHA1,拼够所需长度为止。wifit3 的实现见 _prf():
def _prf(key: bytes, label: bytes, data: bytes, nbytes: int) -> bytes: out = b"" i = 0 while len(out) < nbytes: out += hmac.new(key, label + b"\x00" + data + bytes([i]), hashlib.sha1).digest() i += 1 return out[:nbytes]真正的精髓在 ptk() 的排序约定:
data = min(aa, spa) + max(aa, spa) + min(anonce, snonce) + max(anonce, snonce) return _prf(pmk_bytes, b"Pairwise key expansion", data, nbytes)AP 的 MAC 与客户 MAC、AP 随机数(ANonce)与客户随机数(SNonce)都先排序再拼接。这样无论哪一方先发起、谁做地址方,双方算出的 PTK 都完全一致——这是 4 次握手能成功的数学基础,也是很多"魔改"实现出 bug 的地方。
第三步与第四步:KCK 与 EAPOL MIC
PTK 共 48 字节,切分为 TK(32B 加密数据)、KCK(16B 签 MIC)、KIK(余量)。M2 消息的 MIC 计算规则:
- 取 EAPOL 802.1X 负载,将偏移 81 处的 16 字节 MIC 字段清零;
- 以 KCK 为密钥对清零后的负载做 HMAC-SHA1,取前 16 字节。
def eapol_mic(kck_bytes: bytes, eapol_payload_mic_zeroed: bytes) -> bytes: return hmac.new(kck_bytes, eapol_payload_mic_zeroed, hashlib.sha1).digest()[:16]MIC 偏移常量 81 定义在 src/wifit3/dot11/eapol.py,与 hashcat-m 22000读取的字段位置严格一致。
如何验证实现正确:官方测试向量
wifit3 的单元测试 tests/crack/test_wpa_psk.py 做了三件事:
- PMK 向量比对:
pmk("password", "IEEE")必须等于 IEEE 802.11i 附录 J 给出的f42c6fc52df0...10a12e——业界公认的黄金标准; - PTK 对称性:交换 AP/客户 两侧参数,PTK 不变(验证排序逻辑);
- M2 MIC 往返:伪造一条 M2 帧,用
mic_for()签名→清零→重签,结果一致;换一个错误口令则 MIC 必然不同。
这套"签名-还原"往返测试是判断 MIC 实现正确与否最直接的判据。
同一份代码的两条业务线
wifit3 把wpa_psk复用在完全相反的两个方向上,这是它架构上最优雅的地方:
① 离线破解验证—— 独立脚本 scripts/ap/crack.py 演示了完整爆破闭环:从 hc22000 行中取出 ANonce、EAPOL 与 MIC 目标值,遍历候选口令,对每个候选调用wpa_psk.mic_for(psk, ssid, aa, spa, anonce, snonce, eapol),与捕获的 MIC 比对:
for psk in words: if wpa_psk.mic_for(psk, ssid, aa, spa, anonce, snonce, eapol).hex() == mic_target.lower(): return ssid, psk这也解释了 WPA 破解的本质:攻击者只需重算 MIC,无需解密任何数据。
② 伪造 AP 应答(EvilTwin)—— src/wifit3/campaigns/eviltwin/fake_ap.py 中克隆出的 WPA2 "分身"向诱饵客户端发 M1 后,在 scripts/ap/fake_auth.py 里用同一份mic_for()为 M2 计算合法签名:
mic = wpa_psk.mic_for(self.psk, self.ssid, self.bssid, self.our_mac, anonce, snonce, zeroed) payload = set_mic(zeroed, mic)签名正确,真实客户端的 4 次握手才会走完,wifit3 才能抓到可破解的 M2。
与 hashcat 的衔接:hc22000 输出
抓到握手后,src/wifit3/crack/handshake.py 的crackable_pairs()是唯一事实来源(single source of truth):它按 hashcatmodule_22000.c的 MESSAGEPAIR 语义(0x00/0x01/0x02/0x05)配对 M1/M2/M3/M4,再经 hc22000_format.py 生成WPA*02*…哈希行。因为"捕获成功"的判定与哈希行生成走同一条代码路径,UI 横幅永远不会声称抓到了握手、而保存时又拒绝写入。哈希行中 MIC 字段被清零、EAPOL 负载原样嵌入——hashcat 拿到后做的正是wpa_psk.mic_for()的同一套重算,只是它用 GPU 暴力遍历口令。
小结
wifit3 用约 50 行纯 Python 串起了 WPA-PSK 的完整数学链路:
PBKDF2-HMAC-SHA1(psk, ssid, 4096, 32)→PMK(慢迭代防爆破)PRF-512(PMK, "Pairwise key expansion", 排序的MAC对+随机数对)→PTK(排序保证双方一致)HMAC-SHA1(KCK, MIC清零的EAPOL)[:16]→EAPOL MIC(破解验证的核心)
想动手实验的话,建议按这个顺序阅读:先跑 tests/crack/test_wpa_psk.py 看黄金向量,再读 scripts/ap/crack.py 理解离线爆破,最后对照 src/wifit3/crack/wpa_psk.py 的模块 docstring 理清每一步的字节语义。
【免费下载链接】wifit3Wifite but USB-only & cross-platform.项目地址: https://gitcode.com/GitHub_Trending/wi/wifit3
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考