Quel est le problème avec cette classe de PHP4 à chiffrement AES?
-
19-09-2019 - |
Question
Quand je décrypter quelque chose crypté avec cette fonction, la version déchiffrée ne correspond pas à l'original.
class AES256encryption {
var $secret = '';
var $cipher_key = '';
function AES256encryption($secret='') {
if (empty($secret)) {
global $secret;
if (empty($secret)) {
$secret = "some random secret string";
}
}
$this->secret = $secret;
}
function gen_cipher() {
if (empty($this->cipher_key)) {
$this->cipher_key = substr(sha1($this->secret),0,20);
}
}
function mciv() {
return mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
}
function encrypt($text) {
$this->gen_cipher();
return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->cipher_key, $text, MCRYPT_MODE_CBC, $this->mciv())));
}
function decrypt($text) {
$this->gen_cipher();
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->cipher_key, base64_decode($text), MCRYPT_MODE_CBC, $this->mciv()));
}
}
La solution
Ne pas créer une nouvelle IV chaque fois que vous voulez crypter / décrypter quelque chose. Vous avez besoin de la même IV aux heures de chiffrement et de déchiffrement. En mode CBC, il n'y a pas besoin d'obtenir secret IV aussi longtemps qu'il est aléatoire à sa création. Donc, votre code devrait être quelque chose comme:
class AES256encryption {
var $secret = '';
var $cipher_key = '';
var $mciv = NULL;
function AES256encryption($secret='') {
if (empty($secret)) {
global $secret;⋅⋅⋅⋅⋅⋅⋅⋅⋅
if (empty($secret)) {
$secret = "some random secret string";
}
}
$this->secret = $secret;
$this->gen_mciv();
}
function gen_cipher() {
if (empty($this->cipher_key)) {
$this->cipher_key = substr(sha1($this->secret),0,20);
}
}
function gen_mciv() {
if(NULL === $this->mciv)
{
$this->mciv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
}
}
function encrypt($text) {
$this->gen_cipher();
return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->cipher_key, $text, MCRYPT_MODE_CBC, $this->mciv)));
}
function decrypt($text) {
$this->gen_cipher();
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->cipher_key, base64_decode($text), MCRYPT_MODE_CBC, $this->mciv));
}
}
$ac = new AES256encryption('my secret pass');
$z = $ac->encrypt('test');
var_dump($z);
$u = $ac->decrypt($z);
var_dump($u);
Et cela semble fonctionner:
mycroft:~ $ php test_aes.php
string(44) "+KRlfrPp37FfwB4gJXQ67X+8bjbjxEFHjOn55YOgU5o="
string(4) "test"
modes de chiffrement par bloc de opération qui reprend la façon dont ce travail.
Autres conseils
Le IV doit être envoyé au destinataire, ainsi que les données cryptées. Cela signifie que votre fonction encrypt
devra base64 encoder et envoyer, et votre fonction decrypt
devront attendre à recevoir dans le cadre de l'entrée.
Sur la base de l'aide de Patrick et café, j'ai révisé ma classe. J'ai découvert que le secret à la fois et IV doit être le même dans le décryptage comme cela a été utilisé dans le cryptage sinon le décryptage ne fonctionnera pas. IV doit être de 32 caractères. Voici ma classe révisée dans le cas où il est d'usage à tout le monde.
class AES256 {
var $secret = 'some string of any length'; // some random string of any length
var $iv = '0v6bJhPYe2TElCUrT{TD-drLH(5y4pQj'; // must be 32 chars
var $cipher_key = '';
function AES256($secret='', $iv='') {
if (!empty($secret)) {
$this->secret = $secret;
}
$this->cipher_key = substr(sha1($this->secret),0,20);
if (!empty($iv) && (strlen($iv) == 32)) {
$this->iv = $iv;
}
}
function encrypt($plaintext) {
return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->cipher_key, $plaintext, MCRYPT_MODE_CBC, $this->iv)));
}
function decrypt($ciphertext) {
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->cipher_key, base64_decode($ciphertext), MCRYPT_MODE_CBC, $this->iv));
}
}
$r = array();
$ac = new AES256('some string of any length');
$r['ciphertext'] = $ac->encrypt(',23ln1gQ6-3ZY[JI');
$r['plaintext'] = $ac->decrypt("wdkUJRR1qxXLkeseVfiLhKnXsAiVzx4H2ytj+2BFRlo=");
print_r($r);