Quando si utilizza AES e CBC, l'IV può essere un hash del testo in chiaro?

15

[Originariamente su programmers.stackexchange.com con titolo: Puoi crittografare con AES + CBC e cercare i dati crittografati ]

Fondamentalmente, ho intenzione di andare con Advanced Encryption Standard con modalità Cipher-Block Chaining o Cipher Feedback o Output Feedback (non ho ancora deciso). Ogni modalità richiede un vettore di inizializzazione. Il fatto è che voglio rendere la stringa crittografata "ricercabile" in questo modo:

Supponiamo di avere un elenco di tabelle del database insieme a un "nome visualizzato" per ogni tabella. Concettualmente l'elenco sarebbe simile a questo (ho usato {xxx} per indicare la forma crittografata di xxx e [IVx] per indicare un vettore di inizializzazione):

ENC_DISPLAY_NAME         | ENC_TABLE_NAME
------------------------ | -----------------
[IV1]{John's table}      | [IV2]{TABLE_3574}
[IV3]{Eric's list}       | [IV4]{TABLE_3100}
                         |
[IV5]{Darren's projects} | [IV6]{TABLE_2823}
[IV7]{Paul's contacts}   | [IV8]{TABLE_5843}

Ora supponiamo che voglio consentire una ricerca su ENC_DISPLAY_NAME. (Le ricerche di uguaglianza sono tutto ciò che è necessario). Devo avere un modo per sapere quale vettore di inizializzazione è usato sul nome visualizzato che voglio trovare.

Penso che dovrei calcolare un hash a 128 bit (forse un CRC) del nome visualizzato, e usarlo come IV per calcolare la stringa crittografata. Cioè, se voglio memorizzare "i progetti di Darren", dovrei fare qualcosa del genere:

AESKey key = ...;
String str = "Darren's projects";
CRCType crc = ComputeCRC(str);

BinaryString enc = crc.ToBinaryString ( ).Concat
    (EncryptWithAESandCBC(str, key, (IVType)crc));

INSERT INTO MY_TABLE(ENC_DISPLAY_NAME,ENC_TABLE_NAME) VALUES(enc, ...);

Se invece desidero cercare la stringa, esegui gli stessi passaggi tranne l'ultimo e poi SELECT * FROM MY_TABLE WHERE ENC_DISPLAY_NAME=enc .

Questo è già stato provato? Ci sono dei rischi (di sicurezza)?

[Domande correlate: Calcola la chiave di crittografia AES con il testo in chiaro e il testo cifrato? ]

    
posta Null Pointers etc. 16.06.2011 - 16:56
fonte

3 risposte

18

Un hash calcolato sul testo in chiaro avrebbe le giuste caratteristiche per un IV, per quanto riguarda la "casualità uniforme". Si tratta di una funzione di hash crittograficamente protetta , non di un CRC. Piuttosto, qualcosa come SHA-256. Un CRC non è in alcun modo sufficientemente sicuro per la crittografia.

Tuttavia , l'IV deve essere noto a chiunque decifri, quindi deve essere memorizzato lungo il messaggio crittografato. Se l'IV è calcolato con una funzione di hash dal testo in chiaro, allora questo consente di eseguire un attacco di dizionario sul testo in chiaro (cercando un testo in chiaro possibile finché non viene trovato quello che corrisponde all'hash). Sconfiggere gli attacchi del dizionario è già abbastanza difficile per le password, che devono essere sicure e casuali; quindi, per qualcosa di completamente non casuale come nome visualizzato, dovresti davvero usare un IV generato da un generatore di numeri casuali crittografici correttamente protetto, non un hash calcolato dal testo in chiaro. Non cambierà i costi di archiviazione, dal momento che l'IV deve essere comunque memorizzato, indipendentemente da come lo si genera.

    
risposta data 16.06.2011 - 18:00
fonte
5

Risposta breve: IV deve essere casuale e inviato in chiaro.

Devi stare attento a non perdere informazioni sul testo in chiaro nel tuo hash. non devi essere possibile ottenere il testo normale con una tabella arcobaleno del tuo hash. Quindi un valore salt, memorizzato in un file di configurazione, non nel database, è in ordre.

Detto ciò, suggerisco questo:

  • Usa un IV casuale, memorizzato come fai adesso
  • memorizza un hash salato dei dati in testo semplice in un'altra colonna
  • cerca l'hash salato per recuperare l'IV casuale e il testo cifrato

Quindi nel tuo esempio, avresti questo:

NC_DISPLAY_NAME                                            | ENC_TABLE_NAME
-----------------------------------------------------------+------------------
hash(salt+"Darren's projects"), [IV5]{Darren's projects}   | [IV6]{TABLE_2823}

Naturalmente, l'hash salato non è privo di rischi. È inferiore a quello che cercavi di evitare per primo, ma ancora presente. Se il rischio è troppo elevato, è possibile crittografare l'hash del testo normale (con un altro tasto AES) in modalità ECB e cercarlo. Quindi la tua tabella sarà simile a questa:

NC_DISPLAY_NAME                                               | ENC_TABLE_NAME
--------------------------------------------------------------+------------------
{k1 hash("Darren's projects")}, [IV5]{k2 Darren's projects}   | [IV6]{TABLE_2823}

Fare l'hash ti dà l'entropia (sbiancamento dell'input) equivalente all'utilizzo di una IV (ma non ho il potere matematico di confermarla). La crittografia ti offre protezione contro le tabelle arcobaleno e i dizionari.

Sai che avrai un compromesso sulla sicurezza quando il brutto forzamento dell'indice di ricerca richiederà più tempo della forza bruta del testo cifrato casuale codificato IV.

    
risposta data 16.06.2011 - 17:21
fonte
0

Se hai intenzione di mettere l'hash dei contenuti proprio lì, allora rendi conto che la tua crittografia ti darà solo un'altra copia dei dati. Se tutto quello che stai usando è una ricerca, allora tutto ciò di cui hai bisogno è l'hash (escludendo le collisioni, comunque). Quindi qualsiasi attaccante che sta cercando una riga specifica in base al suo nome può trovarlo senza conoscere la chiave semplicemente ignorando la parte crittografata dei dati e cercando l'hash di ciò che sta cercando.

Ora se il digest che stai utilizzando è un HMAC e non solo CRC o un hash, potresti essere OK. Ma ti rendi conto che devi stare attento a non divulgare ulteriori informazioni con esso.

    
risposta data 21.06.2011 - 23:28
fonte

Leggi altre domande sui tag