2010-09-15 18 views
13

Dopo aver iniziato a utilizzare la crittografia nella mia applicazione, mi trovo perplesso dalla relazione tra la lunghezza del testo di input e il testo cifrato in cui si traduce. Prima di applicare Crypto, era facile determinare il database dimensione della colonna. Ora, tuttavia, le dimensioni della colonna variano leggermente.Relazione tra input e lunghezza del testo cifrato in AES

due domande:

  1. Ho ragione nel ritenere questo è dovuto l'imbottitura del mio ingresso, in modo che si adatti requirments della cifratura?
  2. C'è un modo per prevedere con precisione la lunghezza massima del testo cifrato in base alla lunghezza massima dell'input?

E per i punti bonus: dovrei memorizzare il testo cifrato base64-codificato in un varchar, o tenerlo come byte non elaborati e memorizzarli in un varbinary? Ci sono rischi nell'archiviazione dei byte nel mio database (sto usando query parametrizzate, quindi in teoria la rottura accidentale dell'escaping non dovrebbe essere un problema)?

TIA!

Supplementare: il codice che sto utilizzando è AES/Rijndael-256 - questa relazione varia tra gli algoritmi disponibili?

+0

Perché è necessario specificare la lunghezza massima a tutti? Non sono gli anni '80 - i database hanno supportato campi con limiti di lunghezza grandi o inesistenti per qualche tempo. –

+0

Prestazioni e meno spazio di archiviazione necessari. I campi TEXT e BLOB sono fantastici - ma per piccoli bit di dati (voglio dire, stiamo parlando di password crittografate ... non di grandi quantità di dati o romanzi XML) il sovraccarico sembra estraneo. TEXT e BLOB vengono archiviati in un'area separata del database dai record di cui fanno parte, rendendo quindi il motore del database due letture anziché uno. – kander

risposta

25

Il rapporto dipende dalla imbottitura e concatenamento modalità in uso, e la dimensione del blocco algoritmo (se è un codice a blocchi).

Alcuni algoritmi di crittografia sono codici di flusso che crittografano i dati "bit per bit" (o "byte per byte"). La maggior parte di essi produce un flusso dipendente dalla chiave di byte pseudo-casuali e la crittografia viene eseguita da XORing che trasmette i dati (la decrittografia è identica). Con un codice di flusso, la lunghezza crittografata è uguale alla lunghezza dei dati semplice.

Altri algoritmi di crittografia sono codici a blocchi. Un codice a blocchi, nominalmente, codifica un singolo blocco di dati di una lunghezza fissa. AES è un codice a blocchi con blocchi a 128 bit (16 byte). Nota che AES-256 usa anche blocchi a 128 bit; il "256" riguarda la lunghezza della chiave, non la lunghezza del blocco. La modalità di concatenamento riguarda la suddivisione dei dati in diversi blocchi di questo tipo (non è facile eseguirlo in sicurezza, ma la modalità CBC va bene). A seconda della modalità di concatenazione, i dati potrebbero richiedere alcuni padding, ad esempio alcuni byte aggiuntivi aggiunti alla fine in modo che la lunghezza sia appropriata per la modalità concatenamento. Il padding deve essere tale da poter essere rimosso in modo univoco da durante la decodifica.

Con modalità CBC, i dati di ingresso devono avere un multiplo lunghezza della lunghezza del blocco, così è consuetudine aggiungere riempimento PKCS # 5: se la lunghezza del blocco è n, quindi viene aggiunto almeno 1 byte, in più n, tale che la dimensione totale è un multiplo di n, e gli ultimi byte aggiunto (possibilmente tutti) hanno un valore numerico k dove k è il numero di byte aggiunto. Dopo la decifratura, è sufficiente esaminare l'ultimo byte decrittografato per recuperare k e quindi sapere quanti byte di padding devono essere rimossi.

Quindi, con modalità CBC e AES, assumendo riempimento PKCS # 5, se i dati di input ha lunghezza d allora la lunghezza cifrato è (d + 16) & ~15. Sto usando la notazione C-like qui; in parole povere, la lunghezza è compresa tra d + 1 e d + 16 e multiplo di 16.

C'è una modalità chiamata CTR (come "contatore") in cui il codice a blocchi crittografa valori successivi di un contatore, che produce un flusso di byte pseudo-casuali. Ciò trasforma efficacemente il cifrario a blocchi in un codice di flusso, e quindi un messaggio di lunghezza d è codificato in d byte.

Attenzione: su tutti i sistemi di crittografia (compresi cifrari a flusso) e modalità richiedono un valore aggiunto chiamato IV (valore iniziale). Ogni messaggio deve avere il suo IV, e nessun messaggio criptato con la stessa chiave deve utilizzare lo stesso IV. Alcune modalità hanno requisiti aggiuntivi; in particolare, per CBC e CTR, l'IV deve essere scelto in modo casuale e uniforme con un generatore di numeri pseudo-casuali crittograficamente forte. Il IV non è segreto, ma deve essere conosciuto dal decrypter. Poiché ogni messaggio riceve la propria IV, è spesso necessario codificare la IV insieme al messaggio crittografato. Con CBC o CTR, IV ha lunghezza n, quindi, per AES, sono 16 byte in più. Non so che cosa mcrypt faccia con la IV, ma, crittograficamente parlando, la IV deve essere gestita ad un certo punto.

Come per Base64, è utile per trasferire dati binari su supporti di solo testo, ma questo non dovrebbe essere necessario per un database corretto. Inoltre, Base64 ingrandisce i dati di circa il 33%, quindi non dovrebbe essere applicato alla cieca. Penso che tu stia meglio evitando Base64 qui.

+0

+1 @Thomas, buona spiegazione. Non è possibile utilizzare/non utilizzare un IV per la modalità CBC AES, se si genera una nuova chiave di sessione per ogni file che si desidera crittografare? Grazie – Raj

+1

Se si genera una nuova chiave per ogni file, è possibile utilizzare un IV convenzionale (ad esempio un IV tutto-zero) che non ha bisogno di essere codificato.Ma generare una nuova chiave segreta casuale per ogni file è difficile almeno quanto generare una nuova IV casuale per ogni file. Qualunque cosa sia la migliore dipende dalla situazione. –

+0

Grazie per la tua risposta molto dettagliata - Sto memorizzando l'IV in una colonna separata dai dati crittografati, nello stesso record, perché la IV è una lunghezza fissa. Starò lontano da Bas64 per il testo cifrato. – kander

1

Dalla mia comprensione, in modalità blocco (cbc, ecb) la lunghezza di output verrà arrotondata alla dimensione del blocco, come restituito da mcrypt_enc_get_block_size. Inoltre, è necessario memorizzare IV insieme ai dati, quindi le dimensioni verranno arrotondate strlen (dati) + mcrypt_enc_get_iv_size().

Per quanto riguarda la codifica di base64, non mi preoccuperei (ma assicurati di utilizzare la codifica esadecimale quando esegui il db).

1

Per AES CBC cifrario a blocchi con riempimento PKCS # 5,

#define BLOCKSIZE 16 

size_t CipherTextLen = (PlainTxtLen/BLOCKSIZE + 1) * BLOCKSIZE; 

Ciò non tiene conto del vettore di inizializzazione

Problemi correlati