電信商 Wi-Fi 是 Android 9 及更高版本中提供的自動連線功能(使用加密的 IMSI),可讓裝置自動連線至電信業者實施的 Wi-Fi 網路。在體育場、地鐵站等擁擠程度較高或小區覆蓋範圍較小的區域,可以使用營運商Wi-Fi來改善用戶的連線體驗並減輕流量。
具有運營商 Wi-Fi 功能的設備會自動連接到配置的運營商 Wi-Fi 網路(具有公鑰證書的網路)。當使用者手動中斷與電信商 Wi-Fi 網路的連線時,該網路將被列入黑名單 24 小時(不會自動連線)。用戶可以隨時手動連線到黑名單網路。
在運行 Android 9 或更高版本並實現運營商 Wi-Fi 的裝置上,預設關閉透過電信業者 Wi-Fi 的自動連線。當設備首次嘗試連接到運營商 Wi-Fi 網路時,系統會向用戶發送通知。
執行
設備製造商和運營商必須執行以下操作才能實施運營商 Wi-Fi。
製造商
對於運行 Android 11 及更高版本的設備,請使用Wi-Fi 建議 API為每個營運商新增 Wi-Fi 設定檔。
對於運行 10 或更低版本的設備,請透過在運營商配置管理器中為每個運營商配置carrier_wifi_string_array
參數來新增 Wi-Fi 設定檔。
carrier_wifi_string_array
:一個字串數組,其中每個字串條目是一個 Base64 編碼的 Wi-Fi SSID 和一個用逗號分隔的 EAP 類型,其中 EAP 類型是一個整數(請參閱可擴展身份驗證協定 (EAP) 註冊表)。例如,下列設定適用於使用EAP-AKA 的SOME_SSID_NAME和使用EAP-SIM的Some_Other_SSID :config { key: "carrier_wifi_string_array" text_array { item: "U09NRV9TU0lEX05BTUUK,23" item: "U29tZV9PdGhlcl9TU0lECg==,18" } }
在運營商配置管理器中,為每個運營商配置以下參數:
imsi_key_availability_int
:標識用於 IMSI 加密的金鑰是否可用於 WLAN(設定位元 1)、EPDG(設定位元 0)或兩者(設定位元 0 和位元 1)。例如,以下組態表示 IMSI 加密適用於 WLAN,但不適用於 EPDG:config { key: "imsi_key_availability_int" int_value: 2 }
imsi_key_download_url_string
:從中下載包含用於 IMSI 加密的運營商公鑰的原型的 URL。例如,以下配置提供了特定的 URL:config { key: "imsi_key_download_url_string" text_value: "https://www.some_company_name.com:5555/some_directory_name/some_filename.json" }
allow_metered_network_for_cert_download_bool
:指示是否允許透過計量(蜂窩)網路下載運營商公鑰的標誌。如果未設定此標誌,則沒有 Wi-Fi 連線的新裝置將無法連線到電信業者 Wi-Fi 網絡,因為不允許下載金鑰。config { key: "allow_metered_network_for_cert_download_bool" bool_value: true }
營運商
為了實現營運商Wi-Fi,營運商必須啟用IMSI隱私保護並提供公鑰。
IMSI隱私保護
Android 使用公鑰加密技術保護訂閱者永久身分 (IMSI) 的機密性。 Android 實作了無線寬頻聯盟 (WBA)的 Wi-Fi IMSI 隱私權保護規範。當連線啟用 IMSI 隱私權保護時,永久使用者身分不會以明文形式透過空中傳輸。
永久身分加密
加密永久身分的格式如下:
- 永久身分的格式為
<EAP-Method><IMSI>@<NAI realm>
。 - EAP-Method 前綴是一個八位元字節,定義用於驗證的 EAP 方法:
-
0
: EAP-又名 1
:EAP-SIM卡6
: EAP-又名'
-
- NAI 領域格式為
wlan.mnc XXX .mcc YYY .3gppnetwork.org
,其中XXX
替換為 SIM 卡的行動網路代碼 (MNC),YYY
替換為行動國家/地區代碼 (MCC)。 - 永久身分使用電信業者提供的 RSA 公鑰進行加密。公鑰包含在X.509憑證中。
- 加密方案是RSAES-OAEP,使用 SHA-256 作為加密雜湊函數。此加密方案保證每次使用該方案時都有唯一的密文,從而避免了另一個可追蹤的持久身份。
- RSA 金鑰長度為 2048 位元。
- 加密緩衝區為 256 位元組。
- 密文採用Base64編碼。
- 輸出加密永久身分長度為344位元組。
Encrypted Permanent Identity = Base64(RSAES-OAEP-SHA-256(<EAP-Method><IMSI>@<NAI Realm>))
密鑰標識符
密鑰標識符是運營商附加到證書的可選屬性值對,以允許伺服器在身份驗證期間找到正確的私鑰。密鑰標識符的範例是CertificateSerialNumber=123456
。如果提供了密鑰標識符,則會作為身份驗證過程的一部分以明文形式發送。
基於 SIM 卡的 EAP 驗證方法的修改
當在連線上啟用 IMSI 隱私保護時,系統在收到EAP-Request/Identity
時不會發送永久身份,而是以匿名登入回應:
SERVER: EAP-Request/Identity
UE: EAP-Response/Identity AT_IDENTITY=<prefix>|anonymous@<NAI Realm>
<prefix>
是可選的。如果enable_eap_method_prefix_bool
運營商設定為true
,則身分的第一個字元(在anonymous
之前)會在 EAP 交換開始之前通知伺服器有關所使用的 EAP 方法的類型。
-
0
: EAP-又名 1
:EAP-SIM卡6
: EAP-又名'
如果運營商配置設定為false
,則訊息中不包含此前綴。
作為回應,伺服器發送EAP-Request/AKA-Identity
訊息,系統以下列格式回應:
SERVER: EAP-Request/AKA-Identity AT_ANY_ID_REQ
UE: EAP-Response/AKA-Identity AT_IDENTITY=<prefix>|<Encrypted Permanent Identity>|","|"<attribute>=<value>"
身份的第一個字元通知伺服器使用加密身份,或配置的 EAP 方法的類型:
-
\0
: 加密的永久身份 0
: EAP-又名1
:EAP-SIM卡6
: EAP-又名'
密鑰標識符屬性值對是可選的,如果不使用,則不會附加到加密永久身份的末尾。
此時,伺服器從密鑰標識符(如果提供)中找到私鑰,使用運營商私鑰解密加密的身份,然後繼續正常的 EAP 流程。
認證成功後,伺服器可以提供快速重認證身分或臨時身分(假名),用於後續連線。如果伺服器沒有提供臨時身份,系統將在後續連線中傳送加密身份。
運營商證書檢索、到期和撤銷
當系統中未安裝憑證時,系統將使用imsi_key_download_url_string
運營商設定中提供的URL,透過HTTP GET方法下載憑證。只有當allow_metered_network_for_cert_download_bool
運營商配置設定為true
時,系統才會使用蜂窩資料。否則,系統僅在 Wi-Fi 連線可用時下載憑證。
憑證過期由系統強制執行。系統在證書到期日期前 21 天開始嘗試續約證書,並使用相同的 URL 下載新證書。
如果伺服器無法解密加密的身份,伺服器會傳送帶有AT_NOTIFICATION
程式碼General Failure
(16384) 的EAP-Request/AKA-Notification
訊息來終止 EAP 交換。
如果憑證被撤銷或過期,伺服器會傳送一條EAP-Request/AKA-Notification
訊息,其中包含AT_NOTIFICATION
代碼Certificate Replacement Required
(16385),以終止 EAP 交換。作為回應,系統會應用內部啟發法來決定是否刪除憑證並嘗試從相同 URL 下載新憑證。
提供公鑰
向託管運營商憑證的伺服器提供公共 URL,最好使用基於 TLS 的 HTTP,其中:
- 可以從憑證中提取公鑰和過期時間。
來自伺服器的資訊是JSON格式,如下:
Property: key-identifier Type: String Encoding: UTF-8 Description: Specifies an identifier that the carrier would like to attach to the certificate. Optional: Yes Property: certificate Property alternative name: public-key Type: String Encoding: Base64 Description: The content of the carrier's X.509 certificate. Optional: No Property: key-type Type: String Encoding: UTF-8 Description: Specifies the module that will use the key. The value for type must be either WLAN or EPDG. Optional: Yes. If the key-type property isn't included, then its value defaults to WLAN.
以下是公鑰的範例。
{ "carrier-keys" : [ { "key-identifier" : "CertificateSerialNumber=5xxe06d4", "public-key" : "-----BEGIN CERTIFICATE-----\r\nTIIDRTCCAi2gAwIBAgIEVR4G1DANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzELMAkGA1UE\r\nCBMCTkExCzAJBgNVBAcTAk5BMQswCQYDVQQKEwJOQTELMAkGA1UECxMCTkExEDAOBgNVBAMTB1Rl\r\nc3RiT6N1/w==\r\n-----END CERTIFICATE-----" } ] }