web-dev-qa-db-fra.com

Qu'est-ce qu'un IV OpenSL et pourquoi ai-je besoin d'une clé et d'un IV?

Je suis sur le point d'utiliser le script suivant pour crypter et décrypter certaines données. Je l'utilise car mon cryptage actuel ne fonctionne pas sur notre nouveau serveur. Nous utilisons actuellement mcrypt, je veux donc passer à openssl.

Dans notre base de données, nous utilisons le cryptage aes qui utilise une clé 128 bits, donc je sais ce qu'est une clé, mais je ne sais pas ce qu'est un openssl iv? Et pourquoi aurais-je besoin d'une clé et d'un iv.

Le code que je vais utiliser est celui-ci, que j'ai trouvé sur un site Web parce que je ne comprends pas très bien le cryptage.

Évidemment, je vais le modifier pour que la clé soit conservée ailleurs.

function encrypt_decrypt($action, $string) {
    $output = false;

    $encrypt_method = "AES-256-CBC";
    $secret_key = 'This is my secret key';
    $secret_iv = 'This is my secret iv';

    // hash
    $key = hash('sha256', $secret_key);

    // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
    $iv = substr(hash('sha256', $secret_iv), 0, 16);

    if( $action == 'encrypt' ) {
        $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
        $output = base64_encode($output);
    }
    else if( $action == 'decrypt' ){
        $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
    }

    return $output;
}

$plain_txt = "This is my plain text";
echo "Plain Text = $plain_txt\n";

$encrypted_txt = encrypt_decrypt('encrypt', $plain_txt);
echo "Encrypted Text = $encrypted_txt\n";

$decrypted_txt = encrypt_decrypt('decrypt', $encrypted_txt);
echo "Decrypted Text = $decrypted_txt\n";

if( $plain_txt === $decrypted_txt ) echo "SUCCESS";
else echo "FAILED";

echo "\n";
13
Thomas Williams

Le vecteur d'initialisation fait partie de ce qui fait fonctionner AES en mode CBC (Cipher Block Chaining) - les IV ne sont pas uniques à OpenSSL. CBC fonctionne en XORant le bloc précédent avec le bloc actuel. Le tout premier bloc n'a pas de bloc précédent, donc l'IV sert à cet effet.

La raison pour laquelle cela est nécessaire nécessite un peu de compréhension du fonctionnement des chiffrements par blocs. Sans ce chaînage et IV, nous nous retrouvons avec un mode AES appelé ECB, ou Electronic Code Book. La BCE a des faiblesses qui permettent une attaque en texte clair choisie, parmi de nombreux autres problèmes.

Je recommanderais de passer un peu de temps avec les meilleures pratiques pour les vecteurs d'initialisation CBC. Leur mauvaise utilisation peut affaiblir la sécurité globale d'AES. La courte explication est:

  • Les IV doivent être aléatoires et générés par un CSPRNG.
  • Les IV ne doivent pas être réutilisés. Autrement dit, ne cryptez pas le texte en clair "A" et le texte en clair "B" avec le même IV. Chaque enregistrement doit avoir son propre IV.
  • L'IV n'est pas un secret comme la clé. Il peut être stocké en texte clair avec le texte chiffré.

Gardez également à l'esprit que ces conseils ne s'appliquent qu'à AES-CBC. Si vous étudiez d'autres modes d'AES, tels que GCM, cela ne s'applique pas.

16
vcsjones

Je pense que vous avez peut-être mélangé "clé hachée" et "iv" (Dieu sait que je l'ai fait lors du démarrage de la crypto). la clé hachée est exactement ce que vous avez fait. Pour iv, vous devez utiliser des données aléatoires différentes chaque fois que le cryptage est effectué avec la même clé. (mon expérience: j'ai dû créer un gestionnaire de session sécurisé pdo qui crypte/décrypte les données de la session, j'ai donc fini par implémenter AES-256-CBC en utilisant l'extension openssl)

juste un petit conseil si quelqu'un arrive ici.

// iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
$iv = substr(hash('sha256', $secret_iv), 0, 16);

n'est pas la bonne façon de générer iv + pas besoin de secret_iv car iv doit être aussi aléatoire que possible. Ne le traitez pas (ou ne le comprenez pas) de la même manière que le hachage.

Comme vous avez accès à l'extension openssl, il existe un moyen meilleur/plus sûr de générer iv pour le chiffrement choisi, openssl peut également vous indiquer la bonne longueur de l'iv pour le chiffrement:

$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('AES-256-CBC'));

Il sera au format binaire, donc si vous en avez besoin en hex, utilisez bin2hex ($ iv). Si vous avez besoin de stocker l'iv généré dans mysql, je le stocke au format brut (le type de champ varbinary, binary fonctionne également).

Encore une chose. La balise $ options est définie sur 0 dans openssl_encrypt et _decrypt, ce qui signifie "si la valeur true est renvoyée en tant que données de sortie brutes, sinon la valeur de retour est codée en base64".

4
ConfusedAmish