Afferrando la chiave ChaCha20 dalla ram

0

Ci sono vari altri post che parlano di prendere una chiave da ram come

La mia domanda è un po 'diversa. Supponiamo di avere la chiave e per una breve finestra la useremo per inizializzare una cifra (in questo caso ChaCha20) e quindi cancellare la chiave dalla memoria (usando le migliori pratiche, memset_s ecc.) [* Edit2]

Una volta inizializzato il codice, equivale ad avere la chiave in memoria?

In particolare, guardando il codice di riferimento ChaCha20: link

void ECRYPT_keysetup(ECRYPT_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
{
  const char *constants;

  x->input[4] = U8TO32_LITTLE(k + 0);
  x->input[5] = U8TO32_LITTLE(k + 4);
  x->input[6] = U8TO32_LITTLE(k + 8);
  x->input[7] = U8TO32_LITTLE(k + 12);
  if (kbits == 256) { /* recommended */
    k += 16;
    constants = sigma;
  } else { /* kbits == 128 */
    constants = tau;
  }
  x->input[8] = U8TO32_LITTLE(k + 0);
  x->input[9] = U8TO32_LITTLE(k + 4);
  x->input[10] = U8TO32_LITTLE(k + 8);
  x->input[11] = U8TO32_LITTLE(k + 12);
  x->input[0] = U8TO32_LITTLE(constants + 0);
  x->input[1] = U8TO32_LITTLE(constants + 4);
  x->input[2] = U8TO32_LITTLE(constants + 8);
  x->input[3] = U8TO32_LITTLE(constants + 12);
}

Sembra che sia sufficiente richiamare la posizione di memoria puntata da x- > inserire, leggere come 48 byte di dati da quel punto, e ce l'hai.

  1. È corretto?
  2. Come può essere impedito nel software? (best practice)

EDIT: Vedo che almeno input [12] e input [13] sono regolati man mano che i byte vengono scricchiolati ... e che il codice può essere "cercato" regolando l'input [8] e input [9] (o almeno in salsa20, suppongo chacha20 sia simile) ... quindi probabilmente sarebbe sufficiente cercare semplicemente una "posizione" casuale e criptare alcuni byte di riempimento casuali, al momento dell'inizializzazione

  1. È corretto, migliorerebbe la difesa contro l'acquisizione della chiave (o dello stato di inizializzazione)?

EDIT 2:

Credo che la chiave possa essere cancellata dalla memoria una volta che la cifratura è stata inizializzata poiché l'implementazione di riferimento non la usa per la decifratura ... o mi manca qualcosa?

Esempio:

ECRYPT_init();
ECRYPT_keysetup(&ctx, MyKey, ECRYPT_MAXKEYSIZE, ECRYPT_MAXIVSIZE);
ECRYPT_ivsetup(&ctx, MyIv);

//notice neither MyKey nor MyIv are used here:
ECRYPT_decrypt_bytes(&ctx, ciphertext, plaintext, ciphertext_len);
    
posta davidkomer 16.06.2016 - 20:03
fonte

1 risposta

1

L'algoritmo ChaCha20 è abbastanza semplice che se sei curioso di sapere come funziona potresti semplicemente scrivere la tua implementazione (ma non usarla in produzione!). RFC 7539 è un riferimento semplice che viene fornito anche con esempi in modo da poter facilmente verificare la correttezza mentre si procede. Ma il modo in cui funziona è che XOR il messaggio con un keystream viene generato come un insieme di blocchi a 64 byte, in cui ogni blocco viene "denominato" da tre argomenti :

  1. La chiave (segreta);
  2. Il nonce (non segreto);
  3. Il contatore dei blocchi (non segreto).

Il blocco viene inizializzato con questi valori e alcune costanti nel modo in cui viene visualizzato lo snippet di codice. Quindi il blocco viene decifrato con l'operazione doubleround dieci volte (dieci round doppi = venti round, ecco perché c'è un "20" nel nome). E ora, in modo critico, lo stato iniziale del blocco viene aggiunto al risultato di questo, e questo passaggio richiede di nuovo il tasto, quindi se lo cancellassi non saresti in grado di eseguire questo passaggio finale.

Dopo quell'aggiunta finale la chiave non dovrebbe essere facilmente recuperabile dal blocco risultante (o altrimenti il codice è completamente infranto!). Tuttavia, il contenuto del blocco è un segreto sensibile, perché un utente malintenzionato che lo vede può decodificare il blocco di testo cifrato corrispondente.

Tutto quello che hai a questo punto, tuttavia, è un blocco da 64 byte, che è valido solo per crittografare o decifrare un blocco di 64 byte del messaggio. A meno che 64 byte non siano la lunghezza massima dei messaggi che crittograferai, avrai bisogno della chiave ancora e ancora per generare ulteriori blocchi. Quindi puoi cancellare la chiave e i blocchi solo dopo aver crittografato o decodificato l'intero messaggio.

Dal momento che sia i blocchi chiave che quelli keytream sono dati segreti, è consigliabile utilizzare le funzionalità del sistema operativo per impedire che la memoria venga trasferita su disco. E vorrai azzerare in sicurezza quel ricordo dopo aver finito.

Considerazioni simili si applicano ad altri cifrari, ma i dettagli sono diversi. Ad esempio, molti codici (ma non ChaCha20) hanno una pianificazione dei tasti , cioè una sequenza di "sottochiavi" derivate dalla chiave segreta. Spesso, dopo aver generato la pianificazione della chiave, non hai più bisogno della chiave, quindi puoi azzerare la chiave in quel punto, ma le sottochiavi devono essere protette e devi aggrapparti a perché li riutilizzi per ogni blocco che elabori.

    
risposta data 17.06.2016 - 10:11
fonte

Leggi altre domande sui tag