2016-04-21 17 views
14

A partire da Android 5.0.0 è possibile toccare a lungo una connessione WiFi e scrivere quella connessione a un tag ("Scrivi sul tag NFC"). È possibile trovare la fonte per tale operazione qui: WriteWifiConfigToNfcDialog.java. La riga relativa che richiede una connessione WiFi e crea un payload NDEF appare qui:Creazione di un record WiFi NDEF mediante l'applicazione/vnd.wfa.wsc in Android

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

mWifiManager è un'istanza di WifiManager, tuttavia getWpsNfcConfigurationToken non fa parte del API. Tracciando questo metodo, possiamo trovare il suo commit qui: Add calls for NFC WSC token creation che purtroppo non aiuta. Qui è dove sono finite le mie indagini. Edit: ho scoperto il seguente stack di chiamate:

WifiServiceImpl.java chiamate mWifiStateMachine.syncGetWpsNfcConfigurationToken(netId);

WifiStateMachine.java chiamate mWifiNative.getNfcWpsConfigurationToken(netId);

WifiNative.java ha finalmente il metodo

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

che poi chiama

String result = doStringCommandNative(mInterfacePrefix + command);

dove doStringCommandNative fa una chiamata di sistema (non riesce a trovare il codice per questo ovunque).

Quale ora è dove finisce l'indagine.

Sperando che qualcuno possa intervenire e mostrarmi un metodo che crea un NdefRecord che è del tipo application/vnd.wfa.wsc dato un SSID, una password, un tipo di crittografia/Auth.

Ho ovviamente ispezionato i byte di un record effettivo application/vnd.wfa.wsc creato da Android ma ricreando manualmente questo processo con i byte sembra potenzialmente molto inaffidabile ed è incredibilmente noioso.

risposta

10

La risposta si trova in Wi-Fi Alliance "Specifiche tecniche di configurazione semplice Wi-Fi v2.0.5" (disponibile per il download here).Android utilizza questo formato standard per la configurazione delle reti WiFi, ho assunto erroneamente che fosse proprietario.

In primo luogo, ho creato una classe di supporto NFC (giustamente chiamata NFCHelper.java) che ha tutte le costanti di byte necessarie per costruire il record. Quindi, ho creato un metodo hacky per creare uno dei due record richiesti. La specifica è in realtà abbastanza inutile qui, quello che ho fatto è stato esaminato un numero di payload di tag che erano stati correttamente configurati tramite il sistema operativo Android. Infine, è necessario disporre di un meccanismo per anteporre un "Handover Select Record (NFC WKT Hs)" (vedere pagina 90 delle specifiche WiFi). Credo che questo disco "dica" ad Android di registrare la rete nel seguente token.

Come creare il record passaggio di consegne:

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. 

Metodo di creazione del token di configurazione:

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); 
} 

licenza e sintesi here. Puoi trovare un'implementazione del metodo concat in qualsiasi punto della rete, o semplicemente scrivere la tua.

Nota: questa è un'implementazione abbastanza hacky (come si può notare). Sto includendo i byte AES e AES/TKIP come ho trovato nel test ha funzionato per una varietà di reti utilizzando diversi metodi di crittografia/autenticazione in Android 5. * Non esitate a cambiare il prototipo della funzione, l'array String ha funzionato bene con cosa stavo facendo

Utilizzando i due record creati nel primo frammento di cui sopra, è necessario trasferirlo in un NdefMessage e scriverlo sul tag.

Un giorno presto avrò intenzione di fare una sceneggiatura e un soln molto migliore/robusto con grafica e materiale, quindi aggiornerò questa risposta.

+1

Grazie per la risposta e il tuo codice. Non è altrettanto hacky come mi sarei aspettato. : D – noone

7

La chiamata di doStringCommand("WPS_NFC_CONFIG_TOKEN WPS " + netId) alla fine viene gestita dal modulo wpa_supplicant. Questa funzione è descritta here. Penso che l'effettiva implementazione di questo possa essere trovata in wps_supplicant.c.

Quello che stai effettivamente cercando di fare non è qualcosa di specifico per Android. È definito nella "Specifiche tecniche di configurazione semplice WiFi", che è possibile scaricare compilando this form. La parte pertinente deve essere 10.1.2 Token di configurazione.

NfcUtils.java ha un'implementazione funzionante per questo! Ci sono alcuni FIXME e TODO, ma in totale funziona e dovrebbe darti un'idea abbastanza chiara di cosa devi fare.

Se si desidera analizzare personalmente tali NdefRecords e fare qualcosa con SSID e chiave, NfcWifiProtectedSetup.java mostra come farlo.

+0

Prima di tutto, grazie per aver rintracciato 'wps_supplicant.c'. Secondo, mentre non ho aggiornato la domanda originale tra qualche tempo, sono riuscito a creare il record Wifi! Non ero molto contento della soluzione (e non eccessivamente orgogliosa perché è abbastanza hacky). Ho infatti acquisito una copia della "WiFi Technical Configuration Technical Specification" (versione 2.0.0) ed ero in grado di seguire le specifiche - la parte più importante era il Handover Record che non avevo nemmeno pensato. Pubblicherò il mio codice come risposta. – henrycjc

+0

@ Henry Ho avuto qualche problema a leggere e capire le specifiche fino ad ora. Dal momento che sto cercando di fare anche questo, non vedo l'ora di vedere come l'hai fatto! – noone

Problemi correlati