Создание записи NDEF WiFi с помощью приложения /vnd.wfa.wsc в Android

Начиная с Android 5.0.0, вы можете долгое время подключаться к WiFi-соединению и записывать это соединение с тегом ( "Write to NFC tag" ). Здесь вы можете найти источник этой операции: WriteWifiConfigToNfcDialog.java. Соответствующая строка, которая принимает соединение WiFi и создает полезную нагрузку NDEF, находится здесь:

String wpsNfcConfigurationToken = mWifiManager.getWpsNfcConfigurationToken(mAccessPoint.networkId);

mWifiManager является экземпляром WifiManager, однако getWpsNfcConfigurationToken не является частью API. Отслеживая этот метод, мы можем найти его фиксацию здесь: Добавить вызовы для создания токенов NFC WSC, к сожалению, никакой помощи. Вот где закончилось мое расследование. Редактировать: Я обнаружил следующий стек вызовов:

WifiServiceImpl.java вызывает mWifiStateMachine.syncGetWpsNfcConfigurationToken(netId);

WifiStateMachine.java вызывает mWifiNative.getNfcWpsConfigurationToken(netId);

WifiNative.java, наконец, имеет метод

public String getNfcWpsConfigurationToken(int netId) { return doStringCommand("WPS_NFC_CONFIG_TOKEN WPS " + netId); }

который затем вызывает

String result = doStringCommandNative(mInterfacePrefix + command);

где doStringCommandNative выполняет системный вызов (не может найти код для этого в любом месте).

Что сейчас заканчивается, когда расследование заканчивается.

Надеясь, что кто-то может вмешаться и показать мне метод, который создает NdefRecord, который относится к типу application/vnd.wfa.wsc, заданному идентификатором SSID, паролем, шифрованием /Auth.

Я, конечно, проверил байты фактической записи application/vnd.wfa.wsc, созданной Android, но ручное воссоздание этого процесса с байтами кажется потенциально очень ненадежным и невероятно утомительным.

Ответ 1

Ответ заключается в Wi-Fi Alliance "Техническая спецификация Wi-Fi Simple Configuration v2.0.5" (доступна для загрузки здесь). Android использует этот стандартный формат для настройки сетей Wi-Fi, я ошибочно предположил, что он является собственностью.

Во-первых, я создал класс-помощник NFC (метко названный NFCHelper.java), который содержит все байт-константы, необходимые для создания записи. Затем я создал хакерский метод для создания одной из двух требуемых записей. Спектр фактически бесполезен здесь, что я сделал, было проверено множество полезных тегов, которые были успешно настроены через ОС Android. Наконец, у вас должен быть механизм для добавления "Handover Select Record (NFC WKT Hs)" (см. Стр. 90 спецификации WiFi). Я считаю, что эта запись "говорит" Android зарегистрировать сеть в следующем токене.

Как создать запись передачи обслуживания:

ndefRecords = new NdefRecord[2];
byte[] version = new byte[] { (0x1 << 4) | (0x2)};
ndefRecords[0] = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_HANDOVER_REQUEST, new byte[0], version);
// and then obviously add the record you create with the method below.

Способ создания токена конфигурации:

private NdefRecord createWifiRecord(String[] data) {
    String ssid = data[0];
    String password = data[1];
    String auth = data[2];
    String crypt = data[3];
    byte[] authByte = getAuthBytes(auth);
    byte[] cryptByte = getCryptBytes(crypt);
    byte[] ssidByte = ssid.getBytes();
    byte[] passwordByte = password.getBytes();
    byte[] ssidLength = {(byte)((int)Math.floor(ssid.length()/256)), (byte)(ssid.length()%256)};
    byte[] passwordLength = {(byte)((int)Math.floor(password.length()/256)), (byte)(password.length()%256)};
    byte[] cred = {0x00, 0x36};
    byte[] idx = {0x00, 0x01, 0x01};
    byte[] mac = {0x00, 0x06};
    byte[] keypad = {0x00, 0x0B};

    byte[] payload = concat(NFCHelper.CREDENTIAL, cred,
            NFCHelper.NETWORK_IDX, idx,
            NFCHelper.NETWORK_NAME, ssidLength, ssidByte,
            NFCHelper.AUTH_TYPE, NFCHelper.AUTH_WPA_PERSONAL, authByte,
            NFCHelper.CRYPT_TYPE, NFCHelper.CRYPT_WEP, NFCHelper.CRYPT_AES_TKIP,
            NFCHelper.NETWORK_KEY, passwordLength, passwordByte);
           // NFCHelper.MAC_ADDRESS, mac);
    return NdefRecord.createMime(NFC_TOKEN_MIME_TYPE, payload);
} 

Лицензия и gist здесь. Вы можете найти реализацию метода concat в любом месте сети или просто написать свой собственный.

Примечание: это довольно хакерская реализация (как вы можете заметить). Я включаю байты AES и AES/TKIP, которые я обнаружил при тестировании, которые он работал для различных сетей с использованием различных методов шифрования/авторизации под Android 5. * Пожалуйста, не стесняйтесь менять прототип функции, массив String просто отлично работал с тем, что я делал.

Используя две записи, созданные в первом фрагменте выше, вы должны передать это в NdefMessage и записать в свой тег.

В один прекрасный день я собираюсь писать и намного лучше/насыщенно soln с графикой и т.д., поэтому я обновлю этот ответ.

Ответ 2

Вызов doStringCommand("WPS_NFC_CONFIG_TOKEN WPS " + netId) в конце обрабатывается модулем wpa_supplicant. Эта функция описана здесь. Я думаю, что реальную реализацию этого можно найти в wps_supplicant.c.

То, что вы на самом деле пытаетесь сделать, - это не что-то особенное на самом деле Android. Он определен в "Технической спецификации простой конфигурации WiFi", которую вы можете загрузить, заполнив эту форму. Соответствующая часть должна быть 10.1.2 Ток конфигурации.

NfcUtils.java имеет для этого рабочую реализацию! Есть несколько FIXME и TODO, но в целом это работает и должно дать вам довольно хорошее представление о том, что вам нужно делать.

Если вы хотите самостоятельно проанализировать такие NdefRecords и сделать что-то с SSID и ключом, NfcWifiProtectedSetup.java показывает, как это сделать.