2010-02-10 3 views
1

Когда я расшифровываю что-то, зашифрованное этой функцией, расшифрованная версия не равна оригиналу.Что не так с этим классом PHP4 для шифрования AES?

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())); 
    } 
} 

ответ

4

Не создавайте новый IV каждый раз, когда вы хотите что-то зашифровать/расшифровать. Вам нужен тот же IV при шифровании и дешифровке. В режиме CBC нет необходимости получать секрет IV, если он является случайным при его создании. Так что ваш код должен быть что-то вроде:

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); 

И это, кажется, работает:

mycroft:~ $ php test_aes.php 
string(44) "+KRlfrPp37FfwB4gJXQ67X+8bjbjxEFHjOn55YOgU5o=" 
string(4) "test" 

Пожалуйста, проверьте block cipher modes of operation, который продолжается, как эта работа.

+0

Спасибо, Патрик, за помощь! –

2

IV необходимо отправить получателю вместе с зашифрованными данными. Это означает, что ваша функция encrypt должна будет закодировать ее base64 и отправить ее, и ваша функция decrypt должна будет ожидать получить ее как часть ввода.

+0

Спасибо, кафе, это было полезно! –

1

Основываясь на помощи Патрика и кафе, я пересмотрел свой класс. Я обнаружил, что и секрет, и IV должны быть одинаковыми при расшифровке, как это использовалось в шифровании, иначе дешифрование не будет работать. IV должно быть 32 символа. Вот мой пересмотренный класс, если он кому-то полезен.

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); 
+0

Вы не должны использовать фиксированный IV - вы должны использовать только что созданный IV для каждого сообщения и просто включать его вместе с зашифрованными данными. – caf

+0

О, хорошо, что нужно знать. Спасибо за помощь! –

Смежные вопросы