mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-15 03:18:26 +00:00
Merge pull request #11643 from chinpei215/2.x-make-mcrypt-optional
[2.x] Make mcrypt optional
This commit is contained in:
commit
e0e4a3b0d6
3 changed files with 111 additions and 15 deletions
|
@ -18,8 +18,11 @@
|
||||||
"source": "https://github.com/cakephp/cakephp"
|
"source": "https://github.com/cakephp/cakephp"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.0",
|
"php": ">=5.3.0"
|
||||||
"ext-mcrypt": "*"
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-openssl": "You need to install ext-openssl or ext-mcrypt to use AES-256 encryption",
|
||||||
|
"ext-mcrypt": "You need to install ext-openssl or ext-mcrypt to use AES-256 encryption"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^3.7",
|
"phpunit/phpunit": "^3.7",
|
||||||
|
|
|
@ -29,6 +29,26 @@ class SecurityTest extends CakeTestCase {
|
||||||
*/
|
*/
|
||||||
public $sut = null;
|
public $sut = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setUp method
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
Configure::delete('Security.useOpenSsl');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tearDown method
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function tearDown() {
|
||||||
|
parent::tearDown();
|
||||||
|
Configure::delete('Security.useOpenSsl');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* testInactiveMins method
|
* testInactiveMins method
|
||||||
*
|
*
|
||||||
|
@ -337,6 +357,54 @@ class SecurityTest extends CakeTestCase {
|
||||||
$this->assertEquals($txt, Security::decrypt($result, $key));
|
$this->assertEquals($txt, Security::decrypt($result, $key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that encrypted strings are comatible between the mcrypt and openssl engine.
|
||||||
|
*
|
||||||
|
* @dataProvider plainTextProvider
|
||||||
|
* @param string $txt Plain text to be encrypted.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testEncryptDecryptCompatibility($txt) {
|
||||||
|
$this->skipIf(!extension_loaded('mcrypt'), 'This test requires mcrypt to be installed');
|
||||||
|
$this->skipIf(!extension_loaded('openssl'), 'This test requires openssl to be installed');
|
||||||
|
$this->skipIf(version_compare(PHP_VERSION, '5.3.3', '<'), 'This test requires PHP 5.3.3 or greater');
|
||||||
|
|
||||||
|
$key = '12345678901234567890123456789012';
|
||||||
|
|
||||||
|
Configure::write('Security.useOpenSsl', false);
|
||||||
|
$mcrypt = Security::encrypt($txt, $key);
|
||||||
|
|
||||||
|
Configure::write('Security.useOpenSsl', true);
|
||||||
|
$openssl = Security::encrypt($txt, $key);
|
||||||
|
|
||||||
|
$this->assertEquals(strlen($mcrypt), strlen($openssl));
|
||||||
|
|
||||||
|
Configure::write('Security.useOpenSsl', false);
|
||||||
|
$this->assertEquals($txt, Security::decrypt($mcrypt, $key));
|
||||||
|
$this->assertEquals($txt, Security::decrypt($openssl, $key));
|
||||||
|
|
||||||
|
Configure::write('Security.useOpenSsl', true);
|
||||||
|
$this->assertEquals($txt, Security::decrypt($mcrypt, $key));
|
||||||
|
$this->assertEquals($txt, Security::decrypt($openssl, $key));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data provider for testEncryptDecryptCompatibility
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function plainTextProvider() {
|
||||||
|
return array(
|
||||||
|
array(''),
|
||||||
|
array('abcdefg'),
|
||||||
|
array('1234567890123456'),
|
||||||
|
array('The quick brown fox'),
|
||||||
|
array('12345678901234567890123456789012'),
|
||||||
|
array('The quick brown fox jumped over the lazy dog.'),
|
||||||
|
array('何らかのマルチバイト文字列'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that changing the key causes decryption to fail.
|
* Test that changing the key causes decryption to fail.
|
||||||
*
|
*
|
||||||
|
|
|
@ -184,9 +184,12 @@ class Security {
|
||||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||||
return openssl_random_pseudo_bytes($length);
|
return openssl_random_pseudo_bytes($length);
|
||||||
}
|
}
|
||||||
|
if (function_exists('mcrypt_create_iv')) {
|
||||||
|
return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
|
||||||
|
}
|
||||||
trigger_error(
|
trigger_error(
|
||||||
'You do not have a safe source of random data available. ' .
|
'You do not have a safe source of random data available. ' .
|
||||||
'Install either the openssl extension, or paragonie/random_compat. ' .
|
'Install either the openssl extension, the mcrypt extension, or paragonie/random_compat. ' .
|
||||||
'Falling back to an insecure random source.',
|
'Falling back to an insecure random source.',
|
||||||
E_USER_WARNING
|
E_USER_WARNING
|
||||||
);
|
);
|
||||||
|
@ -206,7 +209,7 @@ class Security {
|
||||||
* for sensitive data. Additionally this method does *not* work in environments
|
* for sensitive data. Additionally this method does *not* work in environments
|
||||||
* where suhosin is enabled.
|
* where suhosin is enabled.
|
||||||
*
|
*
|
||||||
* Instead you should use Security::rijndael() when you need strong
|
* Instead you should use Security::encrypt() when you need strong
|
||||||
* encryption.
|
* encryption.
|
||||||
*
|
*
|
||||||
* @param string $text Encrypted string to decrypt, normal string to encrypt
|
* @param string $text Encrypted string to decrypt, normal string to encrypt
|
||||||
|
@ -349,12 +352,24 @@ class Security {
|
||||||
// Generate the encryption and hmac key.
|
// Generate the encryption and hmac key.
|
||||||
$key = substr(hash('sha256', $key . $hmacSalt), 0, 32);
|
$key = substr(hash('sha256', $key . $hmacSalt), 0, 32);
|
||||||
|
|
||||||
$algorithm = MCRYPT_RIJNDAEL_128;
|
if (Configure::read('Security.useOpenSsl')) {
|
||||||
$mode = MCRYPT_MODE_CBC;
|
$method = 'AES-256-CBC';
|
||||||
|
$ivSize = openssl_cipher_iv_length($method);
|
||||||
|
$iv = openssl_random_pseudo_bytes($ivSize);
|
||||||
|
$padLength = (int)ceil((strlen($plain) ?: 1) / $ivSize) * $ivSize;
|
||||||
|
$ciphertext = openssl_encrypt(str_pad($plain, $padLength, "\0"), $method, $key, true, $iv);
|
||||||
|
// Remove the PKCS#7 padding block for compatibility with mcrypt.
|
||||||
|
// Since we have padded the provided data with \0, the final block contains only padded bytes.
|
||||||
|
// So it can be removed safely.
|
||||||
|
$ciphertext = $iv . substr($ciphertext, 0, -$ivSize);
|
||||||
|
} else {
|
||||||
|
$algorithm = MCRYPT_RIJNDAEL_128;
|
||||||
|
$mode = MCRYPT_MODE_CBC;
|
||||||
|
$ivSize = mcrypt_get_iv_size($algorithm, $mode);
|
||||||
|
$iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM);
|
||||||
|
$ciphertext = $iv . mcrypt_encrypt($algorithm, $key, $plain, $mode, $iv);
|
||||||
|
}
|
||||||
|
|
||||||
$ivSize = mcrypt_get_iv_size($algorithm, $mode);
|
|
||||||
$iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM);
|
|
||||||
$ciphertext = $iv . mcrypt_encrypt($algorithm, $key, $plain, $mode, $iv);
|
|
||||||
$hmac = hash_hmac('sha256', $ciphertext, $key);
|
$hmac = hash_hmac('sha256', $ciphertext, $key);
|
||||||
return $hmac . $ciphertext;
|
return $hmac . $ciphertext;
|
||||||
}
|
}
|
||||||
|
@ -404,13 +419,23 @@ class Security {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$algorithm = MCRYPT_RIJNDAEL_128;
|
if (Configure::read('Security.useOpenSsl')) {
|
||||||
$mode = MCRYPT_MODE_CBC;
|
$method = 'AES-256-CBC';
|
||||||
$ivSize = mcrypt_get_iv_size($algorithm, $mode);
|
$ivSize = openssl_cipher_iv_length($method);
|
||||||
|
$iv = substr($cipher, 0, $ivSize);
|
||||||
|
$cipher = substr($cipher, $ivSize);
|
||||||
|
// Regenerate PKCS#7 padding block
|
||||||
|
$padding = openssl_encrypt('', $method, $key, true, substr($cipher, -$ivSize));
|
||||||
|
$plain = openssl_decrypt($cipher . $padding, $method, $key, true, $iv);
|
||||||
|
} else {
|
||||||
|
$algorithm = MCRYPT_RIJNDAEL_128;
|
||||||
|
$mode = MCRYPT_MODE_CBC;
|
||||||
|
$ivSize = mcrypt_get_iv_size($algorithm, $mode);
|
||||||
|
$iv = substr($cipher, 0, $ivSize);
|
||||||
|
$cipher = substr($cipher, $ivSize);
|
||||||
|
$plain = mcrypt_decrypt($algorithm, $key, $cipher, $mode, $iv);
|
||||||
|
}
|
||||||
|
|
||||||
$iv = substr($cipher, 0, $ivSize);
|
|
||||||
$cipher = substr($cipher, $ivSize);
|
|
||||||
$plain = mcrypt_decrypt($algorithm, $key, $cipher, $mode, $iv);
|
|
||||||
return rtrim($plain, "\0");
|
return rtrim($plain, "\0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue