Add tck and report description

This commit is contained in:
Raffaele Mignone 2020-07-08 15:55:32 +02:00
parent ba7bd73b73
commit f7e726ac7a
Signed by: norangebit
GPG Key ID: F5255658CB220573
1 changed files with 74 additions and 8 deletions

View File

@ -9,7 +9,7 @@
### Chiavi di autenticazione e verifica
### Chiave temporanea di contatto
### Chiave temporanea di contatto {#sec:tck}
@ -23,15 +23,18 @@
## Implementazione del protocollo per la JMV
Per poter utilizzare il protocollo all'interno dell'applicazione Android è stato sviluppato un'implementazione di quest'ultimo per la *Java Virtual Machine*.
Come visto nella @sec:rak-rvk il protocollo genera le chiavi di autorizzazione e verifica a partire dalla curva ellittica *Ed25519*.
La nostra implementazione del protocollo per la gestione di questa curva utilizza la libreria NOME_LIBRERIA.
Al fine di utilizzare il protocollo precedentemente descritto all'interno dell'applicazione Android, ne è stato sviluppato un'implementazione per la *Java Virtual Machine*.
La gestione della coppia di chiavi derivate dalla curva ellittica *Ed25519* è stata affidata alla libreria NOME_LIBRERIA.
La chiave privata e pubblica prodotte sono state *wrappate* rispettivamente nelle classi `ReportAuthorizationKey` e `ReportVerificationKey`.
Questa scelta non solo ha permesso di utilizzare nomi dal maggiore significato rispetto al dominio applicativo, ma anche nascondere l'implementazione della curva *Ed25519* in modo da disaccoppiare l'interfaccia della libreria crittografica da quella utilizzata per il protocollo TCN.
La chiave privata e pubblica prodotte da quest'ultima sono state *wrappate* all'interno delle classi `ReportAuthorizationKey` e `ReportVerificationKey` in questo modo le classi hanno un nome più esplicativo rispetto al contesto di utilizzo e un futuro cambiamento della libreria utilizzata per la crittografia non impatterà l'API della libreria.
Come illustrato nella @sec:tck, a partire dalla chiave di autorizzazione è possibile ricavare la `TemporaryContactKey` iniziale[^tck-0].
Ciò può essere fatto traverso la funzione `baseTemporaryContactKey()`, la cui implementazione è riportata nel @lst:tck-0.
Invece, partendo da una chiave di contatto generica, è possibile ricavare la successiva chiave di contatto attraverso il metodo `nextTemporaryContactKey()` riportato nel listato @lst:next-tck.
A partire dalla `ReportAuthorizationKey` è possibile ricavare la `TemporaryContactKey` iniziale[^tck-0] attraverso la funzione `baseTemporaryContactKey()` riportata nel @lst:tck-0.
[^tck-0]: La chiave temporanea iniziale viene ricavata a partire dalla sola *rak* e da essa non è generato nessun numero temporaneo di contatto.
``` {.kotlin #lst:tck-0 caption="Derivazione della prima tck"}
``` {.kotlin #lst:tck-0 caption="Derivazione della prima tck."}
fun baseTemporaryContactKey(): TemporaryContactKey {
val hmac = MessageDigest.getInstance("SHA-256").apply {
update(Const.H_TCK_DOMAIN_SEPARATOR)
@ -45,7 +48,70 @@ fun baseTemporaryContactKey(): TemporaryContactKey {
}
```
[^tck-0]: La chiave temporanea iniziale viene ricavata a partire dalla sola *rak* e da essa non è generato nessun numero temporaneo di contatto.
``` {.kotlin #lst:next-tck caption="Generazione della prossima tck."}
fun nextTemporaryContactKey(
rvk: ReportVerificationKey
): TemporaryContactKey {
val hmac = MessageDigest.getInstance("SHA-256").apply {
update(Const.H_TCK_DOMAIN_SEPARATOR)
update(rvk.toByteArray())
update(key)
}
return TemporaryContactKey(
hmac.digest(),
index.inc()
)
}
```
Sempre a partire dalla tck è possibile ricavare il numero di contatto temporaneo (tcn) e da esso l'UUID utilizzato all'interno dei beacon bluetooth.
Questa operazione può essere eseguita mediante la funzione `deriveTemporaryContactNumber()` la cui implementazione è stata riportata nel @lst:derive-tcn.
``` {.kotlin #lst:derive-tcn caption="Derivazione del numero di contatto temporaneo."}
fun deriveTemporaryContactNumber(): TemporaryContactNumber {
val hmac = MessageDigest.getInstance("SHA-256").apply {
update(Const.H_TCN_DOMAIN_SEPARATOR)
update(index.toLeByteArray())
update(key)
}
return TemporaryContactNumber(
hmac.digest().sliceArray(0 until 16),
index
)
}
```
Una altra componente fondamentale dell'implementazione del protocollo TCN è la classe `Report`, infatti tramite essa è possibile generare il report firmato che poi sarà inviato al server.
Inoltre questa classe mette a disposizione una serie di funzioni di utilità come `generateContactNumbers()` e `toReportData()` che facilitano l'estrazione delle informazioni contenute all'interno del report.
Infine la classe report fornisce anche un metodo statico, `readReportDataFromByteArray()`, attraverso il quale altre componenti applicative sono in grado di recuperare le informazioni di un report contenute all'interno di un array di bytes.
L'implementazione di questo metodo è riportata nel listato @lst:read-report.
``` {.kotlin #lst:read-report caption="Lettura dei dati di un report da un ByteArray."}
fun readReportDataFromByteArray(bytes: ByteArray): ReportData {
val buffer = ByteBuffer.wrap(bytes).apply {
order(ByteOrder.LITTLE_ENDIAN)
}
val rvk = ReportVerificationKey
.createFromByteArray(buffer.read(32))
val tckBytes = buffer.read(32)
val from = buffer.short
val until = buffer.short
val memoType = buffer.get()
val memoData = String(buffer.read(buffer.get().toInt()))
return ReportData(
rvk,
TemporaryContactKey
.createFromByteArray(tckBytes, from.dec()),
from,
until,
memoData
)
}
```
# Applicazione