Documentazione/documentazione.md

4.4 KiB

Protocollo TCN

Descrizione del protocollo

Chiavi di autenticazione e verifica

Chiave temporanea di contatto

Numeri temporanei di contatto

Report

Implementazione del protocollo per la JMV

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.

Come illustrato nella @sec:tck, a partire dalla chiave di autorizzazione è possibile ricavare la TemporaryContactKey iniziale1. 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.

fun baseTemporaryContactKey(): TemporaryContactKey {
  val hmac = MessageDigest.getInstance("SHA-256").apply {
    update(Const.H_TCK_DOMAIN_SEPARATOR)
    update(key.toByteArray())
}

  return TemporaryContactKey.createFromByteArray(
    hmac.digest(),
    0
  )
}
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.

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.

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

Bluetooth

Trasmissione

Scansione

Stima della distanza

UI

Memorizzazione

Rete


  1. La chiave temporanea iniziale viene ricavata a partire dalla sola rak e da essa non è generato nessun numero temporaneo di contatto. ↩︎