Mysql
 sql >> Base de données >  >> RDS >> Mysql

Chiffrement Laravel AES-256 et MySQL

Mettre à jour

PR 31721 a été fusionné dans Laravel 7.0.8, qui corrige les barres obliques échappées dans l'encodage json. Avant cela, chiffrer les mêmes données vous donnerait des résultats de taille variable. Désormais, à partir de la version 7.0.8, le chiffrement des mêmes données vous donnera à chaque fois le même résultat de taille.

TL; DR :

La méthode de chiffrement de Laravel renverra une chaîne, de sorte que le type de données doit être un varchar ou une variation de texte, selon la taille des données chiffrées.

Pour déterminer la taille approximative, vous pouvez utiliser la série de calculs suivante :

Laravel>=7.0.8

Soit a =la taille des données non chiffrées sérialisées (strlen(serialize($data)) )
Soit b =a + 16 - (a MOD 16) (calculer la taille des données chiffrées)
Soit c =(b + 2 - ((b + 2) MOD 3)) / 3 * 4 (calculer la taille des données encodées en base64)
Soit d =c + 117 (ajoutez la taille de l'encodage MAC, IV et json)
Laissez e =(d + 2 - ((d + 2) MOD 3)) / 3 * 4 (calculer la taille des données encodées en base64)

Même si la valeur n'est pas déterministe, la taille du résultat l'est. Par exemple, si vous deviez crypter un numéro de sécurité sociale à 9 chiffres, le résultat sera toujours de 216 caractères.

Laravel <7.0.8

Soit a =la taille des données non chiffrées sérialisées (strlen(serialize($data)) )
Soit b =a + 16 - (a MOD 16) (calculer la taille des données chiffrées)
Soit c =(b + 2 - ((b + 2) MOD 3)) / 3 * 4 (calculer la taille des données encodées en base64)
Soit d =c + 117 + 8 + ((c + 2 - ((c + 2) MOD 3)) / 3) (ajoutez la taille de l'encodage MAC, IV et json, plus un tampon supplémentaire pour les barres obliques potentiellement échappées)
Laissez e =(d + 2 - ((d + 2) MOD 3)) / 3 * 4 (calculer la taille des données encodées en base64)

Par exemple, si vous deviez crypter un numéro de sécurité sociale à 9 chiffres, le résultat serait au minimum de 216 caractères et au maximum de 308 caractères (bien que ce soit probablement une impossibilité statistique). Si vous exécutez une boucle de plus de 100 000 cryptages, vous verrez que la taille est généralement comprise entre 216 et 224. La formule fournie ci-dessus vous indiquerait de définir votre champ sur 248 caractères, ce qui est un tampon sain au-dessus de la plage attendue, mais pas statistiquement impossible à atteindre.

Détails :

La valeur renvoyée par la méthode de cryptage n'est pas seulement le texte crypté, mais est une représentation codée en base64 d'un tableau de charge utile encodé en json qui contient (1) la valeur cryptée encodée en base64 des données sérialisées, (2) le vecteur d'initialisation encodé en base64 ( IV), et (3) le code d'authentification de message (MAC). Ainsi, pour déterminer la taille du champ nécessaire, vous devrez connaître la taille maximale des données qui seront encodées, puis ajouter de l'espace supplémentaire pour ces informations supplémentaires qui sont insérées dans la chaîne renvoyée.

Tout d'abord, calculons la taille maximale de votre valeur cryptée. Étant donné que votre algorithme de chiffrement (AES-256-CBC) est un chiffrement par blocs, cela se fait assez facilement avec une formule. AES utilise des blocs de 16 octets et nécessite au moins un octet de remplissage, de sorte que la taille de la valeur cryptée sera le prochain multiple de 16. Ainsi, si vos données d'origine sont de 30 octets, vos données cryptées seront de 32 octets. Si vos données d'origine sont de 32 octets, vos données cryptées seront de 48 octets (puisque AES nécessite au moins un octet de remplissage, vos 32 octets deviennent 33, puis cela passe au multiple suivant de 16 à 48). La formule pour cela serait x + 16 - (x MOD 16) . Donc, pour 30 octets, vous obtenez 30 + 16 - (30 MOD 16) = 32 .

Lors du calcul de la taille de la valeur chiffrée, gardez à l'esprit que les données chiffrées sont d'abord sérialisées. Ainsi, par exemple, si vous cryptez un numéro de sécurité sociale, la valeur en clair n'est que de 9 caractères, mais la valeur sérialisée est en fait de 16 caractères (s:9:"xxxxxxxxx"; ). Étant donné que la valeur sérialisée est ce qui est réellement crypté et qu'elle fait 16 octets, la taille de la valeur cryptée sera de 32 octets (16 + 16 - (16 MOD 16) = 32 ).

En plus de cela, le openssl_encrypt La fonction renvoie les données chiffrées déjà encodées en base64. L'encodage Base64 augmente la taille de la valeur d'environ 4/3. Pour chaque 3 octets dans les données d'origine, l'encodage base64 générera une représentation de 4 octets (caractères). Ainsi, pour l'exemple SSN, le résultat crypté est de 32 octets. Lors de la traduction en base64, 32 octets nous donnent (32 / 3) = 10.6 segments de 3 octets. Puisque base64 remplit l'octet suivant, prenez le plafond et multipliez par 4, ce qui donne 11 * 4 = 44 octets. Ainsi, notre valeur cryptée originale de 32 octets devient une chaîne de 44 caractères. Si vous avez besoin d'une formule pour cela, vous pouvez utiliser (x + 2 - ((x + 2) MOD 3)) / 3 * 4 . Donc, (32 + 2 - ((32 + 2) MOD 3)) / 3 * 4 = 44 .

La prochaine information est le MAC. Le MAC est une valeur hachée SHA256, nous savons donc qu'il comportera 64 caractères.

La dernière information est le IV. Le IV simple est de 16 octets aléatoires. L'IV stocké dans le tableau de charge utile est la valeur encodée en base64 de l'IV simple. Ainsi, nous pouvons utiliser la formule ci-dessus pour calculer la taille du IV encodé en base64 :(16 + 2 - ((16 + 2) MOD 3)) / 3 * 4 = 24 .

Ces trois informations sont compactées dans un tableau, puis codées en json. En raison de la représentation json et du nom des valeurs dans le tableau, cela ajoute 29 octets supplémentaires.

De plus, dans Laravel <7.0.8, toutes les barres obliques dans les données encodées en base64 sont échappées avec des barres obliques inverses dans la chaîne json, ce qui ajoute un nombre variable d'octets en fonction du nombre de barres obliques présentes. Pour l'exemple SSN, il y a 68 caractères de données encodées en base64 (44 pour les données chiffrées, 24 pour l'IV). Supposons que le nombre maximum de barres obliques corresponde probablement à environ 1/3 des résultats, soit environ 23 octets supplémentaires. Dans Laravel>=7.0.8, ces barres obliques ne sont pas échappées, il n'y a donc pas d'octets supplémentaires.

Enfin, cette valeur json_encodée est base64_encodée, ce qui augmentera à nouveau la taille d'un facteur d'environ 4/3.

Donc, pour mettre tout cela ensemble, imaginons à nouveau que vous cryptez un numéro de sécurité sociale. Le openssl_encrypt le résultat sera de 44 caractères, le MAC de 64 caractères, le IV de 24 caractères et la représentation json ajoute 29 caractères supplémentaires.

Dans Laravel <7.0.8, il y a aussi le tampon de 23 caractères supplémentaires. Cela nous donne (44 + 64 + 24 + 29 + 23 = 184 ) personnages. Ce résultat est encodé en base64, ce qui nous donne ((184 + 2 - ((184 + 2) MOD 3)) / 3 * 4 = 248 ) caractères.

Dans Laravel>=7.0.8, il n'y a pas de tampon supplémentaire. Cela nous donne (44 + 64 + 24 + 29 = 161 ) personnages. Ce résultat est encodé en base64, ce qui nous donne ((161 + 2 - ((161 + 2) MOD 3)) / 3 * 4 = 216 ) caractères.