Вход Регистрация
Файл: concrete5.7.5.6/concrete/vendor/zendframework/zend-crypt/src/BlockCipher.php
Строк: 407
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace ZendCrypt;

use 
ZendCryptKeyDerivationPbkdf2;
use 
ZendCryptSymmetricSymmetricInterface;
use 
ZendMathRand;

/**
 * Encrypt using a symmetric cipher then authenticate using HMAC (SHA-256)
 */
class BlockCipher
{
    const 
KEY_DERIV_HMAC 'sha256';

    
/**
     * Symmetric cipher
     *
     * @var SymmetricInterface
     */
    
protected $cipher;

    
/**
     * Symmetric cipher plugin manager
     *
     * @var SymmetricPluginManager
     */
    
protected static $symmetricPlugins null;

    
/**
     * Hash algorithm fot HMAC
     *
     * @var string
     */
    
protected $hash 'sha256';

    
/**
     * Check if the salt has been set
     *
     * @var bool
     */
    
protected $saltSetted false;

    
/**
     * The output is binary?
     *
     * @var bool
     */
    
protected $binaryOutput false;

    
/**
     * Number of iterations for Pbkdf2
     *
     * @var string
     */
    
protected $keyIteration 5000;

    
/**
     * Key
     *
     * @var string
     */
    
protected $key;

    
/**
     * Constructor
     *
     * @param SymmetricInterface $cipher
     */
    
public function __construct(SymmetricInterface $cipher)
    {
        
$this->cipher $cipher;
    }

    
/**
     * Factory.
     *
     * @param  string      $adapter
     * @param  array       $options
     * @return BlockCipher
     */
    
public static function factory($adapter$options = array())
    {
        
$plugins = static::getSymmetricPluginManager();
        
$adapter $plugins->get($adapter, (array) $options);

        return new static(
$adapter);
    }

    
/**
     * Returns the symmetric cipher plugin manager.  If it doesn't exist it's created.
     *
     * @return SymmetricPluginManager
     */
    
public static function getSymmetricPluginManager()
    {
        if (static::
$symmetricPlugins === null) {
            static::
setSymmetricPluginManager(new SymmetricPluginManager());
        }

        return static::
$symmetricPlugins;
    }

    
/**
     * Set the symmetric cipher plugin manager
     *
     * @param  string|SymmetricPluginManager      $plugins
     * @throws ExceptionInvalidArgumentException
     */
    
public static function setSymmetricPluginManager($plugins)
    {
        if (
is_string($plugins)) {
            if (!
class_exists($plugins)) {
                throw new 
ExceptionInvalidArgumentException(sprintf(
                    
'Unable to locate symmetric cipher plugins using class "%s"; class does not exist',
                    
$plugins
                
));
            }
            
$plugins = new $plugins();
        }
        if (!
$plugins instanceof SymmetricPluginManager) {
            throw new 
ExceptionInvalidArgumentException(sprintf(
                
'Expected an instance or extension of %sSymmetricPluginManager; received "%s"',
                
__NAMESPACE__,
                (
is_object($plugins) ? get_class($plugins) : gettype($plugins))
            ));
        }
        static::
$symmetricPlugins $plugins;
    }

    
/**
     * Set the symmetric cipher
     *
     * @param  SymmetricInterface $cipher
     * @return BlockCipher
     */
    
public function setCipher(SymmetricInterface $cipher)
    {
        
$this->cipher $cipher;
        return 
$this;
    }

    
/**
     * Get symmetric cipher
     *
     * @return SymmetricInterface
     */
    
public function getCipher()
    {
        return 
$this->cipher;
    }

    
/**
     * Set the number of iterations for Pbkdf2
     *
     * @param  int     $num
     * @return BlockCipher
     */
    
public function setKeyIteration($num)
    {
        
$this->keyIteration = (int) $num;

        return 
$this;
    }

    
/**
     * Get the number of iterations for Pbkdf2
     *
     * @return int
     */
    
public function getKeyIteration()
    {
        return 
$this->keyIteration;
    }

    
/**
     * Set the salt (IV)
     *
     * @param  string                             $salt
     * @return BlockCipher
     * @throws ExceptionInvalidArgumentException
     */
    
public function setSalt($salt)
    {
        try {
            
$this->cipher->setSalt($salt);
        } catch (
SymmetricExceptionInvalidArgumentException $e) {
            throw new 
ExceptionInvalidArgumentException("The salt is not valid: " $e->getMessage());
        }
        
$this->saltSetted true;

        return 
$this;
    }

    
/**
     * Get the salt (IV) according to the size requested by the algorithm
     *
     * @return string
     */
    
public function getSalt()
    {
        return 
$this->cipher->getSalt();
    }

    
/**
     * Get the original salt value
     *
     * @return string
     */
    
public function getOriginalSalt()
    {
        return 
$this->cipher->getOriginalSalt();
    }

    
/**
     * Enable/disable the binary output
     *
     * @param  bool        $value
     * @return BlockCipher
     */
    
public function setBinaryOutput($value)
    {
        
$this->binaryOutput = (bool) $value;

        return 
$this;
    }

    
/**
     * Get the value of binary output
     *
     * @return bool
     */
    
public function getBinaryOutput()
    {
        return 
$this->binaryOutput;
    }

    
/**
     * Set the encryption/decryption key
     *
     * @param  string                             $key
     * @return BlockCipher
     * @throws ExceptionInvalidArgumentException
     */
    
public function setKey($key)
    {
        if (empty(
$key)) {
            throw new 
ExceptionInvalidArgumentException('The key cannot be empty');
        }
        
$this->key $key;

        return 
$this;
    }

    
/**
     * Get the key
     *
     * @return string
     */
    
public function getKey()
    {
        return 
$this->key;
    }

    
/**
     * Set algorithm of the symmetric cipher
     *
     * @param  string                             $algo
     * @return BlockCipher
     * @throws ExceptionInvalidArgumentException
     */
    
public function setCipherAlgorithm($algo)
    {
        if (empty(
$this->cipher)) {
            throw new 
ExceptionInvalidArgumentException('No symmetric cipher specified');
        }
        try {
            
$this->cipher->setAlgorithm($algo);
        } catch (
SymmetricExceptionInvalidArgumentException $e) {
            throw new 
ExceptionInvalidArgumentException($e->getMessage());
        }

        return 
$this;
    }

    
/**
     * Get the cipher algorithm
     *
     * @return string|bool
     */
    
public function getCipherAlgorithm()
    {
        if (!empty(
$this->cipher)) {
            return 
$this->cipher->getAlgorithm();
        }

        return 
false;
    }

    
/**
     * Get the supported algorithms of the symmetric cipher
     *
     * @return array
     */
    
public function getCipherSupportedAlgorithms()
    {
        if (!empty(
$this->cipher)) {
            return 
$this->cipher->getSupportedAlgorithms();
        }

        return array();
    }

    
/**
     * Set the hash algorithm for HMAC authentication
     *
     * @param  string                             $hash
     * @return BlockCipher
     * @throws ExceptionInvalidArgumentException
     */
    
public function setHashAlgorithm($hash)
    {
        if (!
Hash::isSupported($hash)) {
            throw new 
ExceptionInvalidArgumentException(
                
"The specified hash algorithm '{$hash}' is not supported by ZendCryptHash"
            
);
        }
        
$this->hash $hash;

        return 
$this;
    }

    
/**
     * Get the hash algorithm for HMAC authentication
     *
     * @return string
     */
    
public function getHashAlgorithm()
    {
        return 
$this->hash;
    }

    
/**
     * Encrypt then authenticate using HMAC
     *
     * @param  string                             $data
     * @return string
     * @throws ExceptionInvalidArgumentException
     */
    
public function encrypt($data)
    {
        
// 0 (as integer), 0.0 (as float) & '0' (as string) will return false, though these should be allowed
        
if (!is_string($data) || $data === '') {
            throw new 
ExceptionInvalidArgumentException('The data to encrypt cannot be empty');
        }
        if (empty(
$this->cipher)) {
            throw new 
ExceptionInvalidArgumentException('No symmetric cipher specified');
        }
        if (empty(
$this->key)) {
            throw new 
ExceptionInvalidArgumentException('No key specified for the encryption');
        }
        
$keySize $this->cipher->getKeySize();
        
// generate a random salt (IV) if the salt has not been set
        
if (!$this->saltSetted) {
            
$this->cipher->setSalt(Rand::getBytes($this->cipher->getSaltSize(), true));
        }
        
// generate the encryption key and the HMAC key for the authentication
        
$hash Pbkdf2::calc(self::KEY_DERIV_HMAC,
                             
$this->getKey(),
                             
$this->getSalt(),
                             
$this->keyIteration,
                             
$keySize 2);
        
// set the encryption key
        
$this->cipher->setKey(substr($hash0$keySize));
        
// set the key for HMAC
        
$keyHmac substr($hash$keySize);
        
// encryption
        
$ciphertext $this->cipher->encrypt($data);
        
// HMAC
        
$hmac Hmac::compute($keyHmac,
                              
$this->hash,
                              
$this->cipher->getAlgorithm() . $ciphertext);
        if (!
$this->binaryOutput) {
            
$ciphertext base64_encode($ciphertext);
        }

        return 
$hmac $ciphertext;
    }

    
/**
     * Decrypt
     *
     * @param  string                             $data
     * @return string|bool
     * @throws ExceptionInvalidArgumentException
     */
    
public function decrypt($data)
    {
        if (!
is_string($data)) {
            throw new 
ExceptionInvalidArgumentException('The data to decrypt must be a string');
        }
        if (
'' === $data) {
            throw new 
ExceptionInvalidArgumentException('The data to decrypt cannot be empty');
        }
        if (empty(
$this->key)) {
            throw new 
ExceptionInvalidArgumentException('No key specified for the decryption');
        }
        if (empty(
$this->cipher)) {
            throw new 
ExceptionInvalidArgumentException('No symmetric cipher specified');
        }
        
$hmacSize   Hmac::getOutputSize($this->hash);
        
$hmac       substr($data0$hmacSize);
        
$ciphertext substr($data$hmacSize);
        if (!
$this->binaryOutput) {
            
$ciphertext base64_decode($ciphertext);
        }
        
$iv      substr($ciphertext0$this->cipher->getSaltSize());
        
$keySize $this->cipher->getKeySize();
        
// generate the encryption key and the HMAC key for the authentication
        
$hash Pbkdf2::calc(self::KEY_DERIV_HMAC,
                             
$this->getKey(),
                             
$iv,
                             
$this->keyIteration,
                             
$keySize 2);
        
// set the decryption key
        
$this->cipher->setKey(substr($hash0$keySize));
        
// set the key for HMAC
        
$keyHmac substr($hash$keySize);
        
$hmacNew Hmac::compute($keyHmac,
                                 
$this->hash,
                                 
$this->cipher->getAlgorithm() . $ciphertext);
        if (!
Utils::compareStrings($hmacNew$hmac)) {
            return 
false;
        }

        return 
$this->cipher->decrypt($ciphertext);
    }
}
Онлайн: 2
Реклама