178 lines
11 KiB
Markdown
178 lines
11 KiB
Markdown
# Protocollo TCN {#sec:tcn-protocol}
|
|
|
|
|
|
|
|
## Descrizione del protocollo
|
|
|
|
|
|
|
|
### Chiavi di autenticazione e verifica
|
|
|
|
|
|
### Chiave temporanea di contatto
|
|
|
|
|
|
|
|
### Numeri temporanei di contatto
|
|
|
|
|
|
|
|
### Report
|
|
|
|
|
|
|
|
## Implementazione del protocollo per la JMV
|
|
|
|
|
|
|
|
# Applicazione
|
|
|
|
L'applicazione permette di tracciare i contatti degli utenti attraverso l'impiego del Bluetooth Low Energy (BLE).
|
|
In particolare lo smartphone di ogni utente si comporta sia da trasmittente di beacon bluetooth che da ricevente.
|
|
In questo modo quando due utenti entrano nel raggio di azione del bluetooth il contatto verrà memorizzato sui rispettivi dispositivi.
|
|
|
|
L'applicazione prevede differenti modalità di funzionamento, ognuna delle quali garantisce un diverso livello di privacy.
|
|
Nella modalità di funzionamento ***A*** ogni qual volta si verifica un contatto l'applicazione si occupa di notificare immediatamente l'evento al server in modo tale che esso possa essere aggiunto al database remoto.
|
|
Questa modalità è quella meno *privacy friendly* in quanto la comunicazione avviene in *real-time* e all'interno del messaggio scambiato viene riportato sia l'UUID dell'utente sia quello della persona incontrata.
|
|
|
|
La modalità ***B*** prevede lo scambio delle stesse informazioni previste per la modalità precedente, ma solo se richiesto dalle autorità sanitarie.
|
|
In questo modo non solo si evita che i dati siano catturati dal server in *real-time*, ma si espongono le informazioni dell'utente solo quando queste sono strettamente necessarie.
|
|
Sia in questa modalità, che nella precedente si è scelto di non ruotare gli UUID identificativi degli utenti in modo da facilitare la generazione del grafo sul server.
|
|
Questa soluzione può mettere a repentaglio la privacy degli utenti ed essere sfruttata da *avversari* per ottenere informazioni sulle abitudini degli utilizzatori[^catena-negozi].
|
|
|
|
[^catena-negozi]: Per esempio una catena di negozi attraverso l'impiego di uno scanner bluetooth potrebbe ricostruire la *fedeltà* degli utenti, conoscere i settori del negozio preferiti ecc.
|
|
|
|
L'ultima modalità, la ***C***, è quella che tutela maggiormente la privacy degli utilizzatori attraverso due accorgimenti:
|
|
|
|
- Rotazione degli UUID
|
|
- Matching locale
|
|
|
|
La generazione degli UUID avviene attraverso una derivazione deterministica come visto nella @sec:tcn-protocol, in modo tale da avere lo stesso livello di privacy di una soluzione randomica, ma con una migliore scalabilità.
|
|
Mentre il matching locale permette di condividere il minor numero di informazioni possibili e solo quando questo è strettamente necessario.
|
|
Infatti in questa modalità l'applicazione carica le informazioni sul server solo in seguito alla richiesta delle autorità sanitarie.
|
|
Inoltre a differenza delle prime due modalità è previsto l'upload unicamente degli UUID che il dispositivo ha assunto nel tempo, in questo modo il server non è in grado di conoscere o ricavare i contatti avuti dall'utente.
|
|
|
|
## Bluetooth
|
|
|
|
L'interazione tra l'hardware bluetooth del dispositivo e l'applicazione è stata gestita attraverso l'impiego della libreria *Android Beacon Library* @AndroidBeaconLibrary che permette di gestire più facilmente le operazioni con beacon bluetooth.
|
|
Inoltre per rendere l'applicazione più funzionale, e quindi garantirne il funzionamento anche in background o a schermo spento è stato utilizzato un *foreground service* @ServicesOverview, che consente di mantenere in *primo piano* le operazioni di trasmissione e scansione anche quando l'applicazione non lo è.
|
|
Data la natura variegata di Android, le diverse implementazioni del sistema operativo adoperate dai vari produttori non si comportano sempre nello stesso modo, motivo per il quale alcuni dispositivi tenderanno a terminare, o mettere in pausa ugualmente l'applicazione[^dont-kill-my-app].
|
|
Potendo opera unicamente nello spazio utente non è stato possibile superare questi limiti.
|
|
|
|
[^dont-kill-my-app]: Molti produttori Android per aumentare la durata della batteria dei propri dispositivi tendono a stoppare e ridurre le funzionalità delle applicazioni. Maggiori dettagli possono essere trovati al seguente link \url{https://dontkillmyapp.com}.
|
|
|
|
Tutte le funzionalità legate al bluetooth sono state *incapsulate* all'interno della classe `BluetoothManager`.
|
|
L'interfaccia di questa classe espone due metodi, `startService()` e `stopService()` che consentono di avviare e stoppare sia la scansione che la trasmissione del beacon.
|
|
Poiché queste operazioni vanno ad interagire con le funzionalità del sistema operativo, l'istanza di questa classe deve essere collegata ad un oggetto di tipo `Context`.
|
|
Si è scelto di collegare l'oggetto `BluetoothManager` alla *application* e non ad una `Activity` in quanto i servizi devono essere utilizzati anche quando non sono presenti *activity* in *foreground*.
|
|
Per questo motivo è stata sviluppata anche una classe `BluetoothApplication` che va ad estendere le funzionalità di `Application` e fornisce a sua volta due metodi di start e stop che vanno a richiamare quelli esposti da `BluetoothManager` in modo tale che sia possibile controllare i servizi legati al bluetooth anche da altre componenti dell'applicazione.
|
|
|
|
### Trasmissione
|
|
|
|
Il dispositivo dell'utente deve eseguire il broadcast di un beacon bluetooth contenete l'UUID identificativo.
|
|
Questa operazione è stata svolta attraverso la classe `BeaconTransmitter` messa a disposizione dalla *Android Beacon Library*.
|
|
Inoltre per la modalità di funzionamento *C* è stato necessario prevedere un meccanismo di rotazione delle chiavi.
|
|
Questa rotazione viene settata attraverso la funzione `rotateTCN()` che sfrutta un `Handler` per programmare la rotazione dell'UUID.
|
|
|
|
``` {.kotlin #lst:rotate-tcn caption="Codice necessario alla rotazione del tcn."}
|
|
private fun rotateTCN() {
|
|
val advertiseHandler = Handler()
|
|
val changeTCN: Runnable = object : Runnable {
|
|
override fun run() {
|
|
tcnManager.nextTcn()
|
|
startAdvertising()
|
|
advertiseHandler.postDelayed(
|
|
this,
|
|
TCNManager.ELAPSE_BETWEEN_NEW_TCN
|
|
)
|
|
}
|
|
}
|
|
|
|
advertiseHandler.postDelayed(
|
|
changeTCN,
|
|
TCNManager.ELAPSE_BETWEEN_NEW_TCN
|
|
)
|
|
}
|
|
```
|
|
|
|
La scelta della frequenza di *advertising* è stata dettata dai vincoli tracciati dall'API di Android @AdvertiseSettings.
|
|
Infatti la libreria permette di trasmettere un beacon con una frequenza di 1 *Hz*, 3 *Hz* o 10 *Hz*.
|
|
Fortunatamente questi vincoli non si sono rilevati troppo limitanti infatti la frequenza di un Hertz, quindi un beacon trasmetto ogni secondo, permette di avere una buona trasmissione e di risparmiare batteria.
|
|
Inoltre in fase di scanning evita che siano registrate più interazioni nello stesso ciclo.
|
|
|
|
Sempre attraverso l'API di Android è stata settata la potenza di trasmissione del beacon.
|
|
Anche in questo caso la scelta era limitata a poche alternative:
|
|
|
|
- HIGH
|
|
- MEDIUM
|
|
- LOW
|
|
- ULTRA_LOW
|
|
|
|
Com'è possibile dedurre anche dai nomi dei vari livelli, l'API non fornisce nessuna stima quantitativa[^dispositivi-non-omogenei], ma solo delle indicazioni qualitative delle intensità del segnale trasmesso.
|
|
L'individuazione del livello più adatto è stata svolta per via sperimentale utilizzando cinque dispositivi differenti.
|
|
I due livelli più alti sono stati immediatamente scartati in quanto permettevano di rilevare i beacon a distanze elevate cosa che avrebbe minato la bontà dell'applicazione.
|
|
Con il livello ULTRA_LOW si è notato che venivano rilevate unicamente le interazioni inferiori al metro in contesti *free space*.
|
|
Poiché l'organizzazione mondiale della sanità raccomanda una distanza di almeno un metro @AdvicePublicCOVID19 questo livello di trasmissione non consente di rilevare contatti potenzialmente a rischio.
|
|
Per questo motivo si è scelto di utilizzare il livello LOW che permette di rilevare contatti fino a circa due metri.
|
|
|
|
[^dispositivi-non-omogenei]: D'altronde, data la natura non omogenea dei vari dispositivi Android, una stima quantitativa sarebbe stata impossibile da ottenere.
|
|
|
|
### Scansione
|
|
|
|
Le operazioni di scansione sono meno limitate dalle funzionalità dell'API di android e per questo motivo si ha avuto maggiore libertà di scelta.
|
|
In particolare è stato possibile settare sia l'intervallo temporale che deve intercorrere tra una scansione e la successiva, sia la durata della singola scansione.
|
|
Si è scelto di far trascorrere un minuto tra una scansione e la prossima e di avere una scansione della durata di un secondo.
|
|
Per quanto detto già in precedenza in base ai vari dispositivi e alle varie condizioni di funzionamento l'intervallo tra una scansione e la prossima potrebbe essere più ampio rispetto a quello stabilito.
|
|
Entrambi i parametri sono stati settati tramite una costante in modo tale da rendere la configurazione del comportamento facilmente cambiabile.
|
|
|
|
Quando l'applicazione rivela un beacon nelle vicinanze esso viene trasmesso ad un'ulteriore componete applicativa tramite l'impiego del `LocalBroadcastManager` @BroadcastsOverview.
|
|
Questa componente non consuma direttamente il beacon, ma ha il compito di smistarlo ad ulteriori componenti in base alla modalità di funzionamento dell'applicazione.
|
|
Il codice necessario a smistare i dati di contatto è stato riportato nel listato @lst:contact-receiver.
|
|
Come si può notare a linea 2, la prima operazione consiste nel recupero dei dati di contatto dall'`Intent`, mentre dala linea 7 si seleziona la funzione da invocare in base alla modalità di funzionamento.
|
|
|
|
``` {.kotlin .numberLines #lst:contact-receiver caption="Codice necessario allo smistamento dei dati di contatto."}
|
|
// ...
|
|
val contactData = intent?.getSerializableExtra(CONTACT_DATA_KEY)
|
|
as ContactData?
|
|
|
|
val mode = getMod(context)
|
|
|
|
val onMode = when (mode) {
|
|
Mode.MOD_A -> this::contactOnModeA
|
|
Mode.MOD_B -> this::contactOnModeB
|
|
Mode.MOD_C -> this::contactOnModeC
|
|
}
|
|
|
|
onMode(context, contactData)
|
|
```
|
|
|
|
Nel caso della modalità *A* il beacon viene trasmesso alla classe `NetworkReceiver` che si occupa di trasmettere il contatto al server remoto.
|
|
Mentre nel caso delle modalità *B* e *C* il beacon viene consumato dalla classe `StoreReceiver` la quale si occupa della memorizzazione permanete del contatto all'interno di un database locale.
|
|
|
|
|
|
### Stima della distanza
|
|
|
|
In base all'intensità dell segnale (***rssi***) misurato dal dispositivo ricevente è possibile ottenere una stima della distanza che intercorre tra chi invia il beacon e chi lo riceve attraverso l'@eq:distanza.
|
|
Per poter calcolare la distanza è necessario conoscere anche il valore di $n$ e $TxPower$.
|
|
$n$ è una costante che generalmente assume valori compresi tra uno e quattro e ci permette di modellare i diversi ambienti in cui si può operare.
|
|
Generalmente si utilizza $n$ pari a due quando si ipotizza di lavorare in ambienti *free space*.
|
|
|
|
$$
|
|
d = 10^{\frac{TxPower - rssi}{10 \cdot n}}
|
|
$$ {#eq:distanza}
|
|
|
|
$TxPower$ è la potenza di trasmissione nominale che si misurerebbe alla distanza di un metro dalla sorgente del segnale.
|
|
Il valore di $TxPower$ deve essere precedentemente ricavato per ogni emettitore e deve essere inviato all'interno del beacon bluetooth.
|
|
Lavorando con dispositivi eterogenei tra di loro non è stato possibile calcolare in modo esatto questo valore ma si è scelto di utilizzare un valore che mediamente si adattasse a tutti i dispositivi utilizzati in fase di test.
|
|
|
|
## UI
|
|
|
|
|
|
|
|
## Memorizzazione
|
|
|
|
|
|
|
|
## Rete
|
|
|