Android11 Wifi 加密类型详解

您所在的位置:网站首页 wifiwpa加密 Android11 Wifi 加密类型详解

Android11 Wifi 加密类型详解

2024-03-05 08:42| 来源: 网络整理| 查看: 265

Android Wifi 加密类型详解

文章目录 Android Wifi 加密类型详解一、早期的WiFi认证标准二、Android 中Wifi加密类型1、代码中的声明2、Wifi加密协议简介3、代码中配置加密类型4、系统源码应用中设置加密类型(1)原生Settings应用(2)原生TvSettings应用 5、获取加密类型 三、wifi连接 共勉: 逆水行舟不进则退。其实很多时候,某一方面的知识就那么多,你多学一点,就多会一点。

有些项目中是不用原生Settings,是自己开发的设置,连接WPA/WPA2是没有问题的, 但是连接EAP和WPA3居然连接不上,发现自己的代码中并没有对这两种加密类型的wifi就行判断,导致连接不上。

如果你是类似的问题或者自己开发的wifi连接,并且设计到多种加密形式,可以看看本文内容。

一、早期的WiFi认证标准 WEP: Wired Equivalent Privacy(有线等效加密) , 保护无线网络信息安全的体制,无线网络通过无线电传播,为了保证数据机密性而设计。 但是存在一些漏洞,比如针对EAP的密钥截取攻击,和针对数据完整性的Replay Attack(回放攻击),已经不推荐使用。 WPA: WiFi Protected Access (Wi-Fi访问保护), 是一种保护无线网络访问安全的技术标准,WPA是为了解决EAP的几个严重的弱点而产生的, 通过128位密钥加上48位初向量和可以在使用中动态改变密钥的“临时密钥完整性协议”(TKIP), 使用RC4加密、使用Michael消息验证码,避免针对EAP的密钥截取攻击和Replay Attack。 WPA2:WPA的升级版, 采用CCMP计数器模式密码块链消息完整码协议,使用CBC-MAC替代Michael消息验证码, 使用AES取代RC4加密算法。在身份认证和保证数据完整性上更安全。

Android 10之后有了WPA3 后面有介绍。

二、Android 中Wifi加密类型 1、代码中的声明

WifiConfiguration.java (Android 11)

/** Security type for an open network. */ public static final int SECURITY_TYPE_OPEN = 0; /** Security type for a WEP network. */ public static final int SECURITY_TYPE_WEP = 1; /** Security type for a PSK network. */ public static final int SECURITY_TYPE_PSK = 2; /** Security type for an EAP network. */ public static final int SECURITY_TYPE_EAP = 3; /** Security type for an SAE network. */ public static final int SECURITY_TYPE_SAE = 4; /** Security type for an EAP Suite B network. */ public static final int SECURITY_TYPE_EAP_SUITE_B = 5; /** Security type for an OWE network. */ public static final int SECURITY_TYPE_OWE = 6; /** Security type for a WAPI PSK network. */ public static final int SECURITY_TYPE_WAPI_PSK = 7; /** Security type for a WAPI Certificate network. */ public static final int SECURITY_TYPE_WAPI_CERT = 8;

在文件 WifiConfiguration.java搜索"Security types we support.",也能看到当前api支持的类型。

0表示不加密。Android11 存在的wifi加密方式8种。 对比查看了Android9.0只有1-6,后面新增的两种也没用过。 Android11 WiFi相关代码改动记录 https://blog.csdn.net/qq_43804080/article/details/112602931

正常手机和路由器发出热点都是0/1/2;

2、Wifi加密协议简介

下面是wifi加密介绍,东拼西凑搞过来的:

SECURITY_TYPE_WEP = 1; //比较旧的加密方式,基本很少用,不太安全 更多文字介绍:https://blog.csdn.net/u013403237/article/details/50663790 SECURITY_TYPE_PSK = 2; //目前常用 包含WPA/WPA2 更多文字介绍:https://www.jianshu.com/p/9316c433ec5f/ SECURITY_TYPE_EAP = 3; //非常安全 EAP 的类型,是一种企业验证的安全类型,EAP 全称叫 802.1X/EAP 他常常给误解成 802.11x。 EAP 的意思就是可扩展认证协议的缩写。 最常部署的 EAP 验证类型包括 EAP-MD-5、EAP-TLS、EAP-LEAP、EAP-TTLS、EAP-Fast、EAP-PEAP; 所以EAP网络也是连接wifi参数最多的网络,还需要添加客户端和服务器端的证书安装。 更多文字介绍:https://blog.csdn.net/hl1293348082/article/details/123888636 SECURITY_TYPE_SAE = 4; SAE最早是802.11s中为mesh网络提出的基于password的认证和key生成协议[1]。在WPA2-PSK中,PMK就是PSK,直接来源于密钥; 而SAE则保证任何STA pair(AP-STA,nonAP-STA)在不同的session都有不同的PMK,使用SAE认证的个人无线网络通常称为WPA3-PSK/WPA3-Personal。 简单的说SAE,就是WPA2的升级,简称WPA3 更多文字介绍:https://blog.csdn.net/qq_23087099/article/details/113921261 SECURITY_TYPE_EAP_SUITE_B = 5; EAP网络的另一种加密形式,具体介绍查不出 SECURITY_TYPE_OWE = 6; 未查出相关介绍,在当前类中发现,入下介绍,Opportunististic (共产主义),大概是共享网络的一种加密格式吧。 /** * Opportunististic Wireless Encryption */ public static final int OWE = 9; 最后两种:SECURITY_TYPE_WAPI_X WAPI(无线网络WLANAuthenticationandPrivacyInfrastructure)是我国自主研发并大力推行的无线网络WLAN安全标准, 它通过了IEEE(注意,不是Wi-Fi)认证和授权,是一种认证和私密性保护协议,其作用类似于802.11b中的WEP,但是能提供更加完善的安全保护。 3、代码中配置加密类型

连接对应类型的wifi需要配置里面的config对象, 可以使用 WifiConfiguration 的 setSecurityParams 进行设置。

WifiConfiguration.java

/** * Set the various security params to correspond to the provided security type. * This is accomplished by setting the various BitSets exposed in WifiConfiguration. * * @param securityType One of the following security types: * {@link #SECURITY_TYPE_OPEN}, * {@link #SECURITY_TYPE_WEP}, * {@link #SECURITY_TYPE_PSK}, * {@link #SECURITY_TYPE_EAP}, * {@link #SECURITY_TYPE_SAE}, * {@link #SECURITY_TYPE_EAP_SUITE_B}, * {@link #SECURITY_TYPE_OWE}, * {@link #SECURITY_TYPE_WAPI_PSK}, or * {@link #SECURITY_TYPE_WAPI_CERT} */ public void setSecurityParams(@SecurityType int securityType) { // Clear all the bitsets. allowedKeyManagement.clear(); allowedProtocols.clear(); allowedAuthAlgorithms.clear(); allowedPairwiseCiphers.clear(); allowedGroupCiphers.clear(); allowedGroupManagementCiphers.clear(); allowedSuiteBCiphers.clear(); switch (securityType) { case SECURITY_TYPE_OPEN: allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); break; case SECURITY_TYPE_WEP: allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); break; case SECURITY_TYPE_PSK: allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); break; case SECURITY_TYPE_EAP: allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); break; case SECURITY_TYPE_SAE: allowedProtocols.set(WifiConfiguration.Protocol.RSN); allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); requirePmf = true; break; case SECURITY_TYPE_EAP_SUITE_B: allowedProtocols.set(WifiConfiguration.Protocol.RSN); allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192); allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256); // Note: allowedSuiteBCiphers bitset will be set by the service once the // certificates are attached to this profile requirePmf = true; break; case SECURITY_TYPE_OWE: allowedProtocols.set(WifiConfiguration.Protocol.RSN); allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE); allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); requirePmf = true; break; case SECURITY_TYPE_WAPI_PSK: allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_PSK); allowedProtocols.set(WifiConfiguration.Protocol.WAPI); allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4); allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4); break; case SECURITY_TYPE_WAPI_CERT: allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_CERT); allowedProtocols.set(WifiConfiguration.Protocol.WAPI); allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4); allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4); break; default: throw new IllegalArgumentException("unknown security type " + securityType); } } 4、系统源码应用中设置加密类型

在TvSetting和原生Setting里面会调用自己SettingsLib中的AccessPoint的相关api,而里面的加密类型的数值又有点不一样。

AccessPoint 是对WifiConfiguration 的进一步封装对象。

frameworks\base\packages\SettingsLib\src\com\android\settingslib\wifi\AccessPoint.java

public static final int SECURITY_NONE = 0; public static final int SECURITY_WEP = 1; public static final int SECURITY_PSK = 2; public static final int SECURITY_EAP = 3; public static final int SECURITY_OWE = 4; public static final int SECURITY_SAE = 5; public static final int SECURITY_EAP_SUITE_B = 6; public static final int SECURITY_MAX_VAL = 7;

普通应用中使用api,扫描到的wifi 列表对象是WifiConfiguration对象; 所以你如果使用SettingsLib的api方式,扫描到的AccessPoint列表, 就需要逐个判断类型设置 WifiConfiguration 的setSecurityParams方法来设置加密类型的配置。

看了下原生Settings里面的代码,是自己判断加密类型,自己写一遍setSecurityParams方法。

(1)原生Settings应用

比如,Settings的WifiConfigController.java的代码

public WifiConfiguration getConfig() { if (mMode == WifiConfigUiBase.MODE_VIEW) { return null; } WifiConfiguration config = new WifiConfiguration(); switch (mAccessPointSecurity) { case AccessPoint.SECURITY_NONE: config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); break; case AccessPoint.SECURITY_WEP: // 加密类型配置 config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WEP); // 密码设置 if (mPasswordView.length() != 0) { int length = mPasswordView.length(); String password = mPasswordView.getText().toString(); // WEP-40, WEP-104, and 256-bit WEP (WEP-232?) if ((length == 10 || length == 26 || length == 58) && password.matches("[0-9A-Fa-f]*")) { config.wepKeys[0] = password; } else { config.wepKeys[0] = '"' + password + '"'; } } break; 。。。。。。 } }

大屏开发人员经常参考的是TvSetting的修改。

(2)原生TvSettings应用

也可以对config里面的allowedProtocols直接设置, 比如:TvSettings 的WifiSecurityHelper.java

public static WifiConfiguration getConfig(FragmentActivity context) { WifiConfiguration config = userChoiceInfo.getWifiConfiguration(); if (TextUtils.isEmpty(config.SSID)) { // If the user adds a network manually, assume that it is hidden. config.hiddenSSID = true; } if (userChoiceInfo.getPageSummary(UserChoiceInfo.SSID) != null) { config.SSID = AccessPoint.convertToQuotedString( userChoiceInfo.getPageSummary(UserChoiceInfo.SSID)); } int accessPointSecurity = getSecurity(context); String password = userChoiceInfo.getPageSummary(UserChoiceInfo.PASSWORD); int length = password != null ? password.length() : 0; switch (accessPointSecurity) { case AccessPoint.SECURITY_NONE: config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); break; case AccessPoint.SECURITY_WEP: // 加密类型配置 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); //设置密码 // WEP-40, WEP-104, and 256-bit WEP (WEP-232?) if ((length == 10 || length == 26 || length == 58) && password.matches("[0-9A-Fa-f]*")) { config.wepKeys[0] = password; } else { config.wepKeys[0] = '"' + password + '"'; } break; case AccessPoint.SECURITY_PSK: config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); if (length != 0) { if (password.matches("[0-9A-Fa-f]{64}")) { config.preSharedKey = password; } else { config.preSharedKey = '"' + password + '"'; } } break; case AccessPoint.SECURITY_SAE: config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); if (length != 0) {// DroidLogic modify SWPL-45229 config.preSharedKey = '"' + password + '"'; } break; case AccessPoint.SECURITY_OWE: config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE); break; default: //TVSettings只支持上面六种加密方式的wifi,其他的wifi就要参考原生Settings修改了 return null; } config.setIpConfiguration(advancedOptionsFlowInfo.getIpConfiguration()); //配置代理/静态ip return config; } }

所以看到下面不同的代码方式对加密类型的配置不要大惊效果

WifiConfiguration config = new WifiConfiguration(); //方式1 配置加密类型 config.setSecurityParams(XX); //方式2 配置界面类型 本质也是设置下面的加密类型配置(,下面只是示例),不同的加密类型配置的项不同,具体参考WifiConfiguration.java即可。 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);

简单的看,使用 WifiConfiguration 的 setSecurityParams 方法是比较简单和保险的,但是确认下类型对应哦。

值得注意的是不同的加密类型,有的设置密码会有一定的差异。 WEP某些情况,PSK(WAP1/2)、SAE(WPA3)的密码如果有特殊符合是要加双引号""包裹的。 具体的代码可以看Settings的WifiConfigController.java的具体获取config对象的代码,不同的Android版本里面支持的加密协议有一定的变化,一般来说是会变多。

5、获取加密类型

WifiConfiguration 对象居然没有get方法获取到它的加密类型!

系统封装的 AccessPoint 对象是有的方法getSecurity 和getSecurityString 获取加密类型和类型字符串;

那么如何从WifiConfiguration对象中获取加密类型呢?

查看里面的代码发现有个隐藏的方法:

/** @hide * return the SSID + security type in String format. */ public String getSsidAndSecurityTypeString() { String key; if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK]; } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) || allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP]; } else if (wepTxKeyIndex >= 0 && wepTxKeyIndex < wepKeys.length && wepKeys[wepTxKeyIndex] != null) { key = SSID + "WEP"; } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { key = SSID + KeyMgmt.strings[KeyMgmt.OWE]; } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { key = SSID + KeyMgmt.strings[KeyMgmt.SAE]; } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) { key = SSID + KeyMgmt.strings[KeyMgmt.SUITE_B_192]; } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) { key = SSID + KeyMgmt.strings[KeyMgmt.WAPI_PSK]; } else if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) { key = SSID + KeyMgmt.strings[KeyMgmt.WAPI_CERT]; } else if (allowedKeyManagement.get(KeyMgmt.OSEN)) { key = SSID + KeyMgmt.strings[KeyMgmt.OSEN]; } else { key = SSID + KeyMgmt.strings[KeyMgmt.NONE]; } return key; }

隐藏的方法没法用啊!

但是发现 allowedKeyManagement 对象是public 的,是可以在外部普通使用的,所以你懂的!

/** * The set of key management protocols supported by this configuration. * See {@link KeyMgmt} for descriptions of the values. * Defaults to WPA-PSK WPA-EAP. */ @NonNull public BitSet allowedKeyManagement;

你可以自己封装getSecurity 和getSecurityString方法使用。

三、wifi连接

Wifi 连接的主要代码:

protected void connect(WifiConfiguration config) { WifiManager wifiManager = (WifiManager) getActivity().getSystemService(Context.WIFI_SERVICE); wifiManager.connect(config, connectListener); //所有的数据都在config对象里面;connectListener 没啥作用,一般传null参数,不管密码是否正确都是回调success。 }

其中WifiConfiguration就是我们要配置的数据,其中包括加密类型数据,密码,代理和静态ip。

系统应用的连接可以参考我之前写的这个: https://blog.csdn.net/wenzhi20102321/article/details/123675077

本文的wifi加密协议就介绍到这里,如果自己的wiif不能连接某个加密的网络,还是要用原始的Settings连接试试,确认是系统环境原因还是自己的apk代码问题。

共勉: 逆水行舟不进则退。其实很多时候,某一方面的知识就那么多,你多学一点,就多会一点。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3