web-dev-qa-db-fra.com

Utilisation du vecteur d'initialisation dans openssl_encrypt

J'ai jeté un œil à la question this , et je voulais le faire pour moi-même. Quand j'ai exécuté ce code (tiré directement de cette réponse ):

$textToEncrypt = "My super secret information.";
$encryptionMethod = "AES-256-CBC";  // AES is used by the U.S. gov't to encrypt top secret documents.
$secretHash = "25c6c7ff35b9979b151f2136cd13b0ff";

//To encrypt
$encryptedMessage = openssl_encrypt($textToEncrypt, $encryptionMethod, $secretHash, '1234567812345678');

//To Decrypt
$decryptedMessage = openssl_decrypt($encryptedMessage, $encryptionMethod, $secretHash);

//Result
echo "Encrypted: $encryptedMessage <br>Decrypted: $decryptedMessage";

Mais je reçois l'avertissement

openssl_encrypt(): Using an empty Initialization Vector (iv) is potentially insecure and not recommended

Je suis donc allé voir les docs , mais il n'y a pas de documentation. J'ai trouvé cela commentaire , mais toujours aucune mention de ce que le vecteur d'initialisation devrait être et comment je devrais l'utiliser. Quelqu'un peut-il m'éclairer?

Je sais que j'aurais pu faire un peu plus de recherche sur Google, mais Stackoverflow apparaît en premier dans de nombreux résultats de recherche, j'ai pensé que cette question pourrait être utile à toute autre personne qui rencontrait ce problème.

68
Alfo

Un IV est généralement un nombre aléatoire qui garantit que le texte chiffré est unique.

Pour expliquer pourquoi cela est nécessaire, supposons que nous ayons une base de données des noms de personnes chiffrés avec la clé "secret" et sans IV.

1 John dsfa9p8y098hasdf
2 Paul po43pokdfgpo3k4y
3 John dsfa9p8y098hasdf

Si Jean 1 connaît son texte chiffré (dsfa9p8y098hasdf) et a accès aux autres textes chiffrés, il peut facilement trouver d'autres personnes nommées Jean.

Maintenant, en réalité, un mode de cryptage qui nécessite un IV en utilisera toujours un. Si vous ne spécifiez pas un IV, il est automatiquement défini sur un tas d'octets nuls. Imaginez le premier exemple mais avec une IV constante (00000000).

1 John dsfa9p8y098hasdf 00000000
2 Paul po43pokdfgpo3k4y 00000000
3 John dsfa9p8y098hasdf 00000000

Pour éviter des textes chiffrés répétés, nous pouvons chiffrer les noms en utilisant la même clé "secrète" et des IV aléatoires:

1 John sdf875n90mh28458 45gh3546
2 Paul fg9087n5b60987nf 56897ngq
3 John gjhn0m89456vnler 8907345f

Comme vous pouvez le voir, les deux textes chiffrés "John" sont désormais différents. Chaque IV est unique et a influencé le processus de cryptage, ce qui rend également le résultat final unique. Jean 1 n'a désormais aucune idée du nom de l'utilisateur 3.

Le déchiffrement nécessite l'utilisation du même IV avec lequel le texte a été chiffré, c'est pourquoi il doit être stocké dans la base de données. L'IV n'est d'aucune utilité sans la clé, donc la transmettre ou la stocker avec le texte crypté n'est pas un problème.

Ceci est un exemple trop simpliste, mais la vérité est que le fait de ne pas utiliser de IV a de graves ramifications de sécurité.


Maintenant, votre code semble définir le IV (1234567812345678) mais ne pas l'utiliser sur le déchiffrement. C'est sûr d'échouer.

Vous pouvez également utiliser certaines des fonctions de génération IV de PHP. Je pense que cela devrait fonctionner pour vous:

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_Rand);
$encryptedMessage = openssl_encrypt($textToEncrypt, $encryptionMethod, $secretHash, 0, $iv);
$decryptedMessage = openssl_decrypt($encryptedMessage, $encryptionMethod, $secretHash, 0, $iv);

Pour le stockage/la transmission, vous pouvez simplement concaténer le texte IV et chiffré comme ceci:

$data = $iv.$encryptedMessage;

Ensuite, lors de la récupération, retirez l'IV pour le déchiffrement:

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = substr($data, 0, $iv_size);
$decryptedMessage = openssl_decrypt(substr($data, $iv_size), $encryptionMethod, $secretHash, 0, $iv);

Pour plus d'informations, consultez la bibliothèque Mcrypt de PHP. Il est assez complet et contient des tonnes d'exemples, dont beaucoup peuvent vous aider avec les implémentations de chiffrement openssh. http://php.net/manual/en/function.mcrypt-encrypt.php

119
Joel Mellon