18、安全机制:WPA2/WPA3 支持、证书管理、企业级认证(EAP)

Wi-Fi 安全,说白了就是解决两个问题:你是谁数据有没有被偷看

我在做 Android Wi-Fi 开发的早期,总觉得安全这块是协议栈的事,应用层不用太操心。直到有一次,客户反馈说他们的企业路由器连不上,日志里全是 EAP 认证失败的报错……嗯,从那以后,我再也不敢轻视安全机制了。

18.1 WPA2 与 WPA3:从兼容到演进

WPA2 是过去十年的主流,WPA3 是新一代标准。Android 从 10 开始原生支持 WPA3,但实际落地时,你会发现很多设备还在用 WPA2。

核心区别:

  • WPA2:使用 4 次握手(4-Way Handshake),预共享密钥(PSK)容易受到字典攻击。
  • WPA3:引入 SAE(Simultaneous Authentication of Equals),也就是 Dragonfly 握手,抵抗离线字典攻击。

我个人习惯在代码里这样判断当前网络的安全类型:

// 获取当前连接的网络安全能力
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int securityType = wifiInfo.getSecurityType();

switch (securityType) {
    case WifiInfo.SECURITY_TYPE_PSK:
        // WPA2-Personal
        break;
    case WifiInfo.SECURITY_TYPE_SAE:
        // WPA3-Personal
        break;
    case WifiInfo.SECURITY_TYPE_EAP:
        // 企业级认证
        break;
}

你想想看,如果设备不支持 WPA3,你硬要配置 SAE 参数,连接就会失败。所以,先查询能力,再配置网络,这是基本素养。

避坑指南:我曾经在 Android 11 上遇到一个 bug——某些旧款路由器虽然广播了 WPA3 能力,但实际握手时只支持 WPA2。解决方案是:在连接失败后,降级尝试 WPA2 配置。

18.2 证书管理:信任链的基石

企业级认证离不开证书。Android 使用 KeyStore 系统来管理证书和私钥。说白了,这就是一个安全容器,应用不能直接读取私钥内容,只能通过 API 使用它。

我建议你把证书管理分为三个层次:

  1. 系统证书:预装在 /system/etc/security/cacerts/ 下,用于验证服务器身份。
  2. 用户证书:用户通过设置安装的证书,存储在 KeyStore 中。
  3. 应用证书:应用自己生成的客户端证书,用于 EAP-TLS 认证。

安装一个 CA 证书的典型代码:

// 通过 Intent 安装证书
Intent installIntent = KeyChain.createInstallIntent();
byte[] certBytes = ...; // 从文件或网络读取
installIntent.putExtra(KeyChain.EXTRA_CERTIFICATE, certBytes);
startActivityForResult(installIntent, REQUEST_INSTALL_CERT);

嗯,这里要注意:安装证书需要用户交互,你不能静默安装。这是 Android 的安全设计,防止恶意应用偷偷植入根证书。

警告:千万不要把私钥硬编码在代码里。我曾经见过一个项目,把客户端证书的私钥写在 strings.xml 中……结果被反编译后,整个企业网络都暴露了。

18.3 企业级认证(EAP):不止是输入用户名密码

EAP(Extensible Authentication Protocol)是一个框架,不是单一协议。Android 支持多种 EAP 方法,我挑几个常用的说说:

EAP 方法 认证方式 安全性 典型场景
EAP-TLS 客户端证书 + 服务器证书 最高 金融、政府内网
EAP-TTLS 服务器证书 + 用户名/密码(隧道内) 中型企业
PEAP 服务器证书 + MSCHAPv2 中高 大多数企业 Wi-Fi
EAP-SIM/AKA SIM 卡认证 运营商热点

配置一个 PEAP 企业网络的代码示例:

WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP);
enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2);
enterpriseConfig.setIdentity("user@domain.com");
enterpriseConfig.setPassword("your-password");

// 设置 CA 证书
enterpriseConfig.setCaCertificate(caCert);

WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"corp-wifi\"";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
config.enterpriseConfig = enterpriseConfig;

wifiManager.addNetwork(config);

为什么需要设置 CA 证书?因为如果不验证服务器身份,攻击者可以伪造一个假的 RADIUS 服务器,截获你的用户名和密码。这就是所谓的 中间人攻击

我的经验:在配置 EAP-TLS 时,客户端证书的私钥必须标记为 KeyProperties.PURPOSE_SIGN,否则握手时会报错。我曾经在这个坑里卡了两天,最后发现是 KeyGenParameterSpec 的用途没设对。

18.4 安全机制的整体流程

为了让你更直观地理解,我画了一张图,展示从扫描到连接的安全决策路径:

Wi-Fi 安全认证决策流程 扫描到网络 获取安全类型字段 判断安全类型 Open / WPA2 / WPA3 / EAP WPA2 / WPA3 PSK / SAE 握手 企业级 EAP TLS / TTLS / PEAP 开放网络 无加密,风险高 密钥验证 PMK 派生 无验证 直接连接 证书 + 身份验证 CA / 客户端证书 连接成功 / 失败回调

从图中你可以看到,安全决策不是一条直线。WPA2/WPA3 走的是密钥派生路径,EAP 走的是证书验证路径,而开放网络……嗯,我建议你直接屏蔽掉。

18.5 实战中的几个关键点

  • 证书过期处理:企业证书通常有有效期。我建议在连接前检查证书的有效期,如果即将过期,提前提示用户更新。
  • EAP 方法协商:有些 RADIUS 服务器会要求特定的 EAP 方法。如果配置不对,连接会一直卡在 "正在获取 IP 地址" 阶段。
  • 隐私保护:WPA3 支持 Opportunistic Wireless Encryption(OWE),即使没有密码也能加密传输。这在公共热点场景下很有用。

小技巧:调试企业级认证时,可以开启 Wi-Fi 的详细日志:adb shell dumpsys wifi 然后搜索 "EAP" 或 "supplicant"。我曾经靠这个命令定位到一个证书链不完整的问题。

安全机制这块,说白了就是「信任」两个字。你信任谁,用什么方式证明信任,数据怎么保护。Android 框架把这些都封装好了,但你要理解背后的原理,才能在遇到问题时快速定位。


公众号:蓝海资料掘金营,微信deep3321