Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Mon, Jan 6, 12:47 AM

in-portal

Index: branches/5.2.x/core/kernel/security/SecurityEncrypter.php
===================================================================
--- branches/5.2.x/core/kernel/security/SecurityEncrypter.php (revision 16770)
+++ branches/5.2.x/core/kernel/security/SecurityEncrypter.php (revision 16771)
@@ -1,228 +1,238 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2018 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class SecurityEncrypter extends kBase
{
const HASHING_ALGORITHM = 'sha256';
const HASHING_KEY_LENGTH = 32;
const ENCRYPTION_METHOD = 'aes-128-cbc'; // Or 'aes-256-cbc'.
const ENCRYPTION_KEY_LENGTH = 16; // Or 32.
/**
* The HMAC key.
*
* @var string
*/
protected $hmacKey;
/**
* The encryption key.
*
* @var string
*/
protected $encryptionKey;
/**
* SecurityEncrypter constructor.
*/
public function __construct()
{
parent::__construct();
$vars = kUtil::getSystemConfig()->getData();
// In the config data is encoded stored to avoid corruption.
$this->hmacKey = base64_decode($vars['SecurityHmacKey']);
// Equivalent of "hex2bin" for PHP < 5.4.
$this->encryptionKey = pack('H*', $vars['SecurityEncryptionKey']);
}
/**
+ * Remove security-related info from serialized object version.
+ *
+ * @return array
+ */
+ public function __sleep()
+ {
+ return array('Prefix', 'Special', 'prefixSpecial');
+ }
+
+ /**
* Creates signature.
*
* @param string $string String.
* @param boolean $raw_output Return raw signature version.
* @param string|null $key_override Override key.
*
* @return string
*/
public function createSignature($string, $raw_output = false, $key_override = null)
{
return hash_hmac(self::HASHING_ALGORITHM, $string, $this->_getHmacKey($key_override), $raw_output);
}
/**
* Returns HMAC key.
*
* @param string|null $key_override Key override.
*
* @return string
* @throws InvalidArgumentException When HMAC key is empty.
*/
private function _getHmacKey($key_override = null)
{
$key = $this->doGetHmacKey($key_override);
if ( empty($key) ) {
throw new InvalidArgumentException('The HMAC key is empty.');
}
if ( mb_strlen($key, '8bit') === self::HASHING_KEY_LENGTH ) {
return $key;
}
return $this->deriveKey($key, self::HASHING_KEY_LENGTH);
}
/**
* Returns HMAC key.
*
* @param string|null $key_override Key override.
*
* @return string
*/
protected function doGetHmacKey($key_override = null)
{
return isset($key_override) ? $key_override : $this->hmacKey;
}
/**
* Returns encryption key.
*
* @param string|null $key_override Key override.
*
* @return string
* @throws InvalidArgumentException When encryption key is empty.
*/
private function _getEncryptionKey($key_override = null)
{
$key = $this->doGetEncryptionKey($key_override);
if ( empty($key) ) {
throw new InvalidArgumentException('The encryption key is empty.');
}
if ( mb_strlen($key, '8bit') === self::ENCRYPTION_KEY_LENGTH ) {
return $key;
}
return $this->deriveKey($key, self::ENCRYPTION_KEY_LENGTH);
}
/**
* Returns encryption key.
*
* @param string|null $key_override Key override.
*
* @return string
*/
protected function doGetEncryptionKey($key_override = null)
{
return isset($key_override) ? $key_override : $this->encryptionKey;
}
/**
* Derives given key.
*
* @param string $key Key.
* @param integer $length Length.
*
* @return string
*/
final public function deriveKey($key, $length)
{
$salt = SecurityGenerator::generateBytes(16, true);
return hash_pbkdf2(self::HASHING_ALGORITHM, $key, $salt, 80000, $length, true);
}
/**
* Encrypts a plain text.
*
* @param string $plaintext Plain text.
* @param string|null $key_override Key override.
*
* @return string
*/
final public function encrypt($plaintext, $key_override = null)
{
$iv_size = openssl_cipher_iv_length(self::ENCRYPTION_METHOD);
$iv = openssl_random_pseudo_bytes($iv_size);
$ciphertext = openssl_encrypt(
$plaintext,
self::ENCRYPTION_METHOD,
$this->_getEncryptionKey($key_override),
OPENSSL_RAW_DATA,
$iv
);
// Note: We cover the IV in our HMAC.
$hmac = $this->createSignature($iv . $ciphertext, true);
return base64_encode($hmac . $iv . $ciphertext);
}
/**
* Decrypts a cipher text.
*
* @param string $ciphertext Cipher text.
* @param string|null $key_override Key override.
*
* @return string|false
* @throws LogicException When signature verification has failed.
*/
final public function decrypt($ciphertext, $key_override = null)
{
$iv_size = openssl_cipher_iv_length(self::ENCRYPTION_METHOD);
$decoded = base64_decode($ciphertext);
$hmac = mb_substr($decoded, 0, self::HASHING_KEY_LENGTH, '8bit');
$iv = mb_substr($decoded, self::HASHING_KEY_LENGTH, $iv_size, '8bit');
$ciphertext = mb_substr($decoded, self::HASHING_KEY_LENGTH + $iv_size, null, '8bit');
$calculated = $this->createSignature($iv . $ciphertext, true);
if ( !hash_equals($hmac, $calculated) ) {
throw new LogicException('Signature verification of ciphertext failed.');
}
return openssl_decrypt(
$ciphertext,
self::ENCRYPTION_METHOD,
$this->_getEncryptionKey($key_override),
OPENSSL_RAW_DATA,
$iv
);
}
/**
* Determines if used cipher is available.
*
* @return boolean
*/
final public function cipherAvailable()
{
return in_array(self::ENCRYPTION_METHOD, openssl_get_cipher_methods(), true);
}
}

Event Timeline