La decrittografia PHP non funziona su alcune stringhe con trim ()

Ho difficoltà a decodificare i valori che terminano con% 3D% 3D. Al momento della decodifica, ottengo un valore di return completamente illeggibile. Il valore crittografato viene passato tramite la querystring, ma ho eseguito un test che esegue il looping dei valori da 0 a 200 per escludere problemi con la codifica dell'URL.

Funzioni di crittografia e decrittografia:

function encryptValue($encrypt) { $key = variable_get_local("privateKey", $default = ""); $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND); $passcrypt = trim(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, trim($encrypt), MCRYPT_MODE_ECB, $iv)); $encode = urlencode(base64_encode($passcrypt)); return $encode; } function decryptValue($decrypt) { $key = variable_get_local("privateKey", $default = ""); $decoded = base64_decode(urldecode($decrypt)); $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND); $decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, trim($decoded), MCRYPT_MODE_ECB, $iv)); return $decrypted; } 

Ho provato a mantenere identico il valore iv attraverso la crittografia e la decrittografia, ma questo non modifica l'output. Ho anche provato a rimuovere il trim() attorno al trim($decoded) ma questo non ha cambiato nulla.

Di seguito è quello che ho usato per identificare il problema. Tra 0 e 200 la crittografia produrrà un valore che termina su% 3D% 3D 9 volte e determinerà il fallimento della decrittografia.

 for($i=0;$i<200;$i++) { echo encryptValue($i) . "<br/>"; echo decryptValue(encryptValue($i)) . "<br/><hr/>"; } 

Grazie per aver letto.

Il tuo problema è con tutte le funzioni di trim , che non dovrebbero essere usate. Non ritaglierai i dati codificati in quanto i dati saranno rimossi, potrebbe essere fondamentale per la chiave, come hai notato.

Funziona così:

 function encryptValue($encrypt) { $key = variable_get_local("privateKey", $default = ""); $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND); $passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, trim($encrypt), MCRYPT_MODE_ECB, $iv); $encode = urlencode(base64_encode($passcrypt)); return $encode; } function decryptValue($decrypt) { $key = variable_get_local("privateKey", $default = ""); $decoded = base64_decode(urldecode($decrypt)); $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND); $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $decoded, MCRYPT_MODE_ECB, $iv); return $decrypted; } 

Ecco alcune osservazioni nello script corrente:

  • La modalità ECB non è sicura usa invece CBC
  • MCRYPT_RAND è lo stesso di rand vedi str_shuffle e randomness usano invece MCRYPT_DEV_URANDOM
  • Per una maggiore sicurezza, utilizzare la crittografia + l'authentication mediante HMAC per impedire l'attacco del pad di oracle
  • Utilizza una libreria testata correttamente e Zend\Crypt piuttosto che creare il tuo seno non sei un esperto di sicurezza

Esempio :

 // Encription Key $encryptionKey = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM); // Stored securely // Signature Key $signatureKey = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM); // Stored securely // Start DataEncryption Object $obj = new DataEncryption($encryptionKey, $signatureKey); $obj->setEncoding(DataEncryption::ENCODE_BASE64); // Test for($i = 0; $i < 200; $i ++) { printf("%s = %s\n", $encode = $obj->encrypt($i), $obj->decrypt($encode)); } 

Produzione

 eSCknmsoMHY2oo5lpW3NpQhDigs4+Fw8aObeIhK+wPyUImQbvlh/aUrW = 0 qFswb3VO5+Foi4kjVn6s5lpZbiWgdKmfObh37/xjPyqB4ZFfAXNUeYYX = 1 WKG0BCKUxOXWU6S3YJ/dNL46Lcn7lt+ihG4tEoZuORDoJXSjz6Vrcepn = 2 K24QqkGYC86btzGQ5HKKMewVhiEIdKOajpgLx8SMKVKfCwlOJlbRwpaz = 3 0DbJycPZ24FOAhQrhQJmgMsP0p2nFzYUlFVOFlbQ8zhLTXkcdnNOhVfi = 4 l7saQG2BTPAZR2EnYjxfNmTxEBBaAh+n9+8eOCITDGzEVShw9wOxP7Pt = 5 eUhvvHJOFsy6ZaBu40XgU+N5VtuFBesRVx0ryfManIXva5y7J0ShiKcE = 6 TaX+172N60X1UTVmMWYcdcn7YzN7xoAOVEPpaD7r1pE3OtX5Erg4nja8 = 7 0LM3W0pkQ73IsmqAgRiQvqL0/rdkk7YvuwcVwoe1NI+qZo7Jq8gyFIvn = 8 .... 38m8fEoUhoTyPPBukg3KVhrmwVDyVCcnWx/5erAslUDzEP7Bddzj5y8Y = 196 Dwi6t7sX30bxjbVXMKCWEZs0FxTUZM4IPHKR3VD6kygi7op0Q6ARCZJW = 197 TJ/faDaIuE0mDPHmGar1BeIyAnfVD0Z47ZtCcHjz5AZzaQ1YWH8kF1bU = 198 FYh+8Kts4ubVvTT5o0vZYfKC+8ExhpD5pWgHK3EhvGWkcPwKerSIvkK0 = 199 

Classe utilizzata

 class DataEncryption { private $keyEncryption; private $keySignature; private $ivSize; private $cipher = MCRYPT_RIJNDAEL_128; private $mode = MCRYPT_MODE_CBC; private $signatureLength = 10; private $encoding = 2; // I prefer hex const ENCODE_BASE64 = 1; const ENCODE_HEX = 2; function __construct($encryptionKey = null, $signatureKey = null) { // Set Keys $this->keyEncryption = empty($encryptionKey) ? mcrypt_create_iv(32, MCRYPT_DEV_URANDOM) : $encryptionKey; $this->keySignature = empty($signatureKey) ? mcrypt_create_iv(32, MCRYPT_DEV_URANDOM) : $signatureKey; // Get IV Size $this->ivSize = mcrypt_get_iv_size($this->cipher, $this->mode); } public function getKeys() { return arrays( "encryption" => $this->keyEncryption, "signature" => $this->keySignature ); } public function setMode($mode) { $this->mode = $mode; } public function setCipher($cipher) { $this->cipher = $cipher; } public function setEncoding($encode) { $this->encoding = $encode; } public function encrypt($data) { // add PKCS7 padding to data $block = mcrypt_get_block_size($this->cipher, $this->mode); $pad = $block - (strlen($data) % $block); $data .= str_repeat(chr($pad), $pad); $iv = $this->rand($this->ivSize); $cipherData = mcrypt_encrypt($this->cipher, $this->keyEncryption, $data, $this->mode, $iv); $finalData = $iv . $cipherData; // protected against padding oracle attacks $finalData = $this->sign($finalData) . $finalData; return $this->encode($finalData); } public function decrypt($data) { $data = $this->decode($data); // Check Integrity if (! $this->check($data)) { return false; } $data = substr($data, $this->signatureLength); // Break Data $iv = substr($data, 0, $this->ivSize); $cipherData = substr($data, $this->ivSize); $data = mcrypt_decrypt($this->cipher, $this->keyEncryption, $cipherData, $this->mode, $iv); // Remove PKCS7 padding $block = mcrypt_get_block_size($this->cipher, $this->mode); $pad = ord($data[($len = strlen($data)) - 1]); // $data = rtrim($data, "\0..\32"); return substr($data, 0, $len - $pad); } public function encode($data) { return $this->encoding === self::ENCODE_BASE64 ? base64_encode($data) : bin2hex($data); } public function decode($data) { return $this->encoding === self::ENCODE_BASE64 ? base64_decode($data) : pack("H*", $data); } public function sign($data) { $hash = hash_hmac('sha256', $data, $this->keySignature, true); return substr($hash, 0, $this->signatureLength); } public function check($data) { $signature = substr($data, 0, $this->signatureLength); $data = substr($data, $this->signatureLength); $hash = hash_hmac('sha256', $data, $this->keySignature, true); // return $signature === substr($hash, 0, $this->signatureLength); return $this->compare($signature, substr($hash, 0, $this->signatureLength)); } public function rand($no) { return mcrypt_create_iv($no, MCRYPT_DEV_URANDOM); } /** * Prevent Timing Attacks * @param string $a * @param string $b * @return boolean */ public function compare($a, $b) { if (strlen($a) !== strlen($b)) { return false; } $result = 0; for($i = 0; $i < strlen($a); $i ++) { $result |= ord($a[$i]) ^ ord($b[$i]); } return $result == 0; } }