Set di chiavi

Tink utilizza i set di chiavi per attivare la rotazione delle chiavi. Formalmente, un keyset è un elenco1 non vuoto di chiavi in cui una chiave è designata come primaria (la chiave utilizzata, ad esempio, per firmare e criptare i nuovi testi non criptati). Inoltre, le chiavi in un keyset ricevono un ID univoco2 e uno stato della chiave che consente di disabilitare le chiavi senza rimuoverle da un keyset.

I set di chiavi sono il modo principale in cui gli utenti possono accedere alle chiavi (tramite la classe KeysetHandle). In questo modo, ogni utente dispone di codice per gestire più chiavi contemporaneamente. Per la maggior parte degli utenti di crittografia, la gestione di più chiavi è una necessità: è necessario poter cambiare le chiavi (ad esempio, le chiavi precedenti possono essere compromesse) e non esiste quasi mai un "passaggio alla chiave successiva" atomico che possa essere applicato alle macchine su cui viene eseguito il codice e a tutti i testi criptati, a livello globale e in un istante. Pertanto, l'utente deve scrivere codice che funzioni quando si passa da una chiave a quella successiva.

Esempio: AEAD

Prendi in considerazione un keyset AEAD, che contiene più chiavi per la primitiva AEAD. Come spiegato in precedenza, ogni chiave specifica in modo univoco due funzioni: \(\mathrm{Enc}\) e \(\mathrm{Dec}\). Il keyset ora specifica anche due nuove funzioni: \(\mathrm{Enc}\) e \(\mathrm{Dec}\) - \(\mathrm{Enc}\) è semplicemente uguale alla funzione \(\mathrm{Enc}\) della chiave primaria del keyset, mentre la funzione \(\mathrm{Dec}\) tenta di decriptare con tutte le chiavi, esaminandole in un determinato ordine (vedi di seguito per scoprire in che modo Tink migliora le prestazioni di questa operazione).

È interessante notare che i set di tasti sono tasti completi: sono una descrizione completa delle funzioni \(\mathrm{Enc}\) e \(\mathrm{Dec}\) utilizzati. Ciò significa che gli utenti possono scrivere una classe che accetta come input un KeysetHandle, esprimendo l'idea che la classe necessita di una descrizione completa degli oggetti \(\mathrm{Enc}\) e \(\mathrm{Dec}\) per funzionare correttamente. Ciò consente all'utente di scrivere API che comunicano che per utilizzare questa classe è necessario fornire la descrizione di una primitiva crittografica.

Rotazione chiave

Considera un utente Tink che scrive un programma che prima ottiene un keyset da un KMS, poi crea un oggetto AEAD da questo keyset e infine utilizza questo oggetto per criptare e decriptare i testi criptati.

Un utente di questo tipo viene preparato automaticamente per la rotazione delle chiavi e per il cambio degli algoritmi nel caso in cui la sua scelta attuale non soddisfi più lo standard.

Tuttavia, è necessario prestare attenzione durante l'implementazione di questa rotazione delle chiavi: Innanzitutto, KMS deve aggiungere una nuova chiave al keyset (ma non impostarla ancora come primaria). Successivamente, il nuovo set di chiavi deve essere reso disponibile in tutti i file binari, in modo che ogni file binario che utilizza questo set di chiavi abbia la chiave più recente nel set di chiavi. Solo allora la nuova chiave deve essere impostata come principale e il keyset risultante viene nuovamente distribuito a tutti i binari che utilizzano il keyset.

Identificatori chiave nei testi criptati

Considera di nuovo l'esempio di un keyset AEAD. Se eseguita in modo ingenuo, la decriptazione di un testo criptato richiede a Tink di tentare la decriptazione con tutte le chiavi nel keyset, poiché non è possibile sapere quale chiave è stata utilizzata per criptare il keyset. Ciò può causare un overhead delle prestazioni elevato.

Per questo motivo, Tink consente di aggiungere un prefisso alle cifrature con una stringa di 5 byte derivata dall'ID. Seguendo la filosofia delle "chiavi complete" sopra descritta, questo prefisso fa parte della chiave e tutti i testi criptati derivati con questa chiave devono avere questo prefisso. Quando gli utenti creano le chiavi, possono scegliere se la chiave deve utilizzare un prefisso di questo tipo o se deve essere utilizzato un formato di testo cifrato senza prefisso.

Quando una chiave si trova in un keyset, Tink calcola questo tag dall'ID che la chiave ha nel keyset. Il fatto che gli ID siano univoci2 all'interno di un keyset implica che i tag siano univoci. Pertanto, se vengono utilizzate solo chiavi taggate, non si verifica alcuna perdita di prestazioni rispetto alla decrittografia con una singola chiave: Tink deve provare solo una delle chiavi durante la decrittografia.

Tuttavia, poiché il tag fa parte della chiave, ciò implica anche che la chiave può trovarsi in un keyset solo se ha un ID specifico. Ciò ha alcune implicazioni quando si descrive l'implementazione degli oggetti chiave in diverse lingue.

Chiavi con un requisito di ID, ma nessun prefisso di output

Alcune chiavi devono avere un ID specifico, ma non aggiungono alcun prefisso al loro output. Ad esempio, le chiavi di firma con la variante NO_PREFIX_WITH_PREHASH_ID (memorizzate con il tipo di prefisso di output WITH_ID_REQUIREMENT) producono firme senza prefisso. Quando utilizzi una chiave di questo tipo con la primitiva Prehash, Tink scrive l'ID chiave nel valore prehash, in modo che un firmatario remoto sappia con quale delle sue chiavi firmare.

Come per le chiavi che utilizzano un prefisso, una chiave di questo tipo può trovarsi solo in un keyset con quell'unico ID. L'ID chiave nel valore pre-hash sono metadati semplici, proprio come il prefisso dell'output: la firma non lo vincola e i verificatori non lo vedono mai. Per il layout a livello di byte, vedi Formato Tink.


  1. Alcune parti di Tink trattano ancora i keyset come un insieme. Tuttavia, questa impostazione deve essere modificata. Il motivo è che l'ordine è in generale importante: ad esempio, considera il ciclo di vita tipico di una rotazione delle chiavi con Aead. Innanzitutto, viene aggiunta una nuova chiave a un keyset. Questa chiave non è ancora stata impostata come primaria, ma è attiva. Questo nuovo set di chiavi viene implementato in tutti i binari. Una volta che tutti i binari conoscono la nuova chiave, questa diventa primaria (solo a questo punto l'utilizzo di questa chiave è sicuro). In questo secondo passaggio, la rotazione delle chiavi deve conoscere l'ultima chiave aggiunta. ↩

  2. Per la compatibilità con una libreria interna di Google, Tink consente di avere keyset in cui gli ID vengono ripetuti. Questo supporto verrà rimosso in futuro. ↩