Mysql
 sql >> Database >  >> RDS >> Mysql

Crittografia Laravel AES-256 e MySQL

Aggiorna

PR 31721 è stato fuso in Laravel 7.0.8, che corregge le barre di escape nella codifica json. Prima di ciò, la crittografia degli stessi dati ti darebbe risultati di dimensioni variabili. Ora, a partire dalla 7.0.8, la crittografia degli stessi dati ti darà ogni volta lo stesso risultato di dimensioni.

TL;DR:

Il metodo di crittografia di Laravel restituirà una stringa, quindi il tipo di dati dovrebbe essere un varchar o una variazione di testo, a seconda della dimensione dei dati da crittografare.

Per determinare la dimensione approssimativa, puoi utilizzare la seguente serie di calcoli:

Laravel>=7.0.8

Sia a =la dimensione dei dati serializzati non crittografati (strlen(serialize($data)) )
Lasciate b =a + 16 - (a MOD 16) (calcola la dimensione dei dati crittografati)
Let c =(b + 2 - ((b + 2) MOD 3)) / 3 * 4 (calcola la dimensione dei dati codificati in base64)
Let d =c + 117 (aggiungi la dimensione della codifica MAC, IV e json)
Let e =(d + 2 - ((d + 2) MOD 3)) / 3 * 4 (calcola la dimensione dei dati codificati in base64)

Anche se il valore non è deterministico, la dimensione del risultato lo è. Ad esempio, se dovessi crittografare un numero di previdenza sociale a 9 cifre, il risultato sarà sempre di 216 caratteri.

Laravel <7.0.8

Sia a =la dimensione dei dati serializzati non crittografati (strlen(serialize($data)) )
Lasciate b =a + 16 - (a MOD 16) (calcola la dimensione dei dati crittografati)
Let c =(b + 2 - ((b + 2) MOD 3)) / 3 * 4 (calcola la dimensione dei dati codificati in base64)
Let d =c + 117 + 8 + ((c + 2 - ((c + 2) MOD 3)) / 3) (aggiungi la dimensione della codifica MAC, IV e json, oltre a un buffer aggiuntivo per le barre potenzialmente sfuggite)
Let e =(d + 2 - ((d + 2) MOD 3)) / 3 * 4 (calcola la dimensione dei dati codificati in base64)

Ad esempio, se dovessi crittografare un numero di previdenza sociale a 9 cifre, il risultato sarebbe minimo 216 caratteri e massimo 308 caratteri (sebbene questa sia probabilmente un'impossibilità statistica). Se esegui un ciclo di oltre 100000 crittografie, vedrai che la dimensione è generalmente nell'intervallo 216 - 224. La formula fornita sopra ti direbbe di impostare il tuo campo su 248 caratteri, che è un buffer sano al di sopra dell'intervallo previsto, ma non statisticamente impossibile da raggiungere.

Dettagli:

Il valore restituito dal metodo encrypt non è solo il testo crittografato, ma è una rappresentazione con codifica base64 di un array di payload codificato in json che contiene (1) il valore crittografato con codifica base64 dei dati serializzati, (2) il vettore di inizializzazione codificato in base64 ( IV) e (3) il codice di autenticazione del messaggio (MAC). Quindi, per determinare la dimensione del campo necessaria, dovrai conoscere la dimensione massima dei dati che verranno codificati e quindi aggiungere spazio extra per queste informazioni extra che vengono inserite nella stringa restituita.

Innanzitutto, calcoliamo la dimensione massima del tuo valore crittografato. Poiché il tuo algoritmo di crittografia (AES-256-CBC) è un cifrario a blocchi, questo è abbastanza facile da fare con una formula. AES utilizza blocchi di 16 byte e richiede almeno un byte di riempimento, quindi la dimensione del valore crittografato sarà il multiplo successivo di 16. Quindi, se i tuoi dati originali sono 30 byte, i tuoi dati crittografati saranno 32 byte. Se i tuoi dati originali sono 32 byte, i tuoi dati crittografati saranno 48 byte (poiché AES richiede almeno un byte di riempimento, i tuoi 32 byte diventano 33 e quindi sale al multiplo successivo da 16 a 48). La formula per questo sarebbe x + 16 - (x MOD 16) . Quindi, per 30 byte ottieni 30 + 16 - (30 MOD 16) = 32 .

Quando si calcola la dimensione del valore crittografato, tenere presente che i dati crittografati vengono prima serializzati. Quindi, ad esempio, se stai crittografando un numero di previdenza sociale, il valore normale è di soli 9 caratteri, ma il valore serializzato è in realtà di 16 caratteri (s:9:"xxxxxxxxx"; ). Poiché il valore serializzato è ciò che è effettivamente crittografato ed è 16 byte, la dimensione del valore crittografato sarà 32 byte (16 + 16 - (16 MOD 16) = 32 ).

In aggiunta a questo, il openssl_encrypt la funzione restituisce i dati crittografati già codificati in base64. La codifica Base64 aumenta la dimensione del valore di circa 4/3. Per ogni 3 byte nei dati originali, la codifica base64 genererà una rappresentazione di 4 byte (carattere). Quindi, per l'esempio SSN, il risultato crittografato è 32 byte. Quando traduciamo in base64, 32 byte ci danno (32 / 3) = 10.6 segmenti da 3 byte. Dal momento che base64 riempie il byte successivo, prendi il soffitto e moltiplica per 4, che dà 11 * 4 = 44 byte. Quindi, il nostro valore crittografato originale di 32 byte diventa una stringa di 44 caratteri. Se hai bisogno di una formula per questo, puoi usare (x + 2 - ((x + 2) MOD 3)) / 3 * 4 . Quindi, (32 + 2 - ((32 + 2) MOD 3)) / 3 * 4 = 44 .

La prossima informazione è il MAC. Il MAC è un valore hash SHA256, quindi sappiamo che sarà di 64 caratteri.

L'ultima informazione è la IV. Il semplice IV è di 16 byte casuali. L'IV memorizzato nell'array di carico utile è il valore codificato in base64 dell'IV semplice. Quindi, possiamo usare la formula sopra per calcolare la dimensione del IV codificato in base64:(16 + 2 - ((16 + 2) MOD 3)) / 3 * 4 = 24 .

Queste tre informazioni vengono compattate in un array e quindi json_encoded. A causa della rappresentazione json e del nome dei valori nell'array, questo aggiunge altri 29 byte.

Inoltre, in Laravel <7.0.8, tutte le barre in avanti nei dati codificati in base64 vengono evitate con barre inverse nella stringa json, quindi questo aggiunge un numero variabile di byte a seconda di quante barre in avanti sono presenti. Per l'esempio SSN, ci sono 68 caratteri di dati codificati in base64 (44 per i dati crittografati, 24 per IV). Supponiamo che il numero massimo di barre in avanti sia probabilmente circa 1/3 dei risultati, o circa 23 byte extra. In Laravel>=7.0.8, queste barre in avanti non vengono salvate, quindi non ci sono byte extra.

Infine, questo valore json_encoded è base64_encoded, che aumenterà nuovamente la dimensione di un fattore di circa 4/3.

Quindi, per mettere tutto insieme, immaginiamo ancora una volta che stai crittografando un numero di previdenza sociale. Il openssl_encrypt il risultato sarà di 44 caratteri, il MAC è di 64 caratteri, l'IV è di 24 caratteri e la rappresentazione json aggiunge altri 29 caratteri.

In Laravel <7.0.8, c'è anche il buffer di 23 caratteri in più. Questo ci dà (44 + 64 + 24 + 29 + 23 = 184 ) caratteri. Questo risultato viene codificato in base64, che ci dà ((184 + 2 - ((184 + 2) MOD 3)) / 3 * 4 = 248 ) caratteri.

In Laravel>=7.0.8, non è presente alcun buffer aggiuntivo. Questo ci dà (44 + 64 + 24 + 29 = 161 ) caratteri. Questo risultato viene codificato in base64, che ci dà ((161 + 2 - ((161 + 2) MOD 3)) / 3 * 4 = 216 ) caratteri.