From f7e726ac7a84d9a9be4fc698dec59b7eeffca689 Mon Sep 17 00:00:00 2001 From: norangebit Date: Wed, 8 Jul 2020 15:55:32 +0200 Subject: [PATCH] Add tck and report description --- documentazione.md | 82 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 8 deletions(-) diff --git a/documentazione.md b/documentazione.md index b39700a..3a40b4f 100644 --- a/documentazione.md +++ b/documentazione.md @@ -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