1
0
Fork 0
MySQLDumper/library/Zend/Filter/Encrypt/Openssl.php
2011-06-10 21:55:32 +00:00

492 Zeilen
13 KiB
PHP

<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Filter
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Filter_Encrypt_Interface
*/
require_once 'Zend/Filter/Encrypt/Interface.php';
/**
* Encryption adapter for openssl
*
* @category Zend
* @package Zend_Filter
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Filter_Encrypt_Openssl implements Zend_Filter_Encrypt_Interface
{
/**
* Definitions for encryption
* array(
* 'public' => public keys
* 'private' => private keys
* 'envelope' => resulting envelope keys
* )
*/
protected $_keys = array(
'public' => array(),
'private' => array(),
'envelope' => array()
);
/**
* Internal passphrase
*
* @var string
*/
protected $_passphrase;
/**
* Internal compression
*
* @var array
*/
protected $_compression;
/**
* Internal create package
*
* @var boolean
*/
protected $_package = false;
/**
* Class constructor
* Available options
* 'public' => public key
* 'private' => private key
* 'envelope' => envelope key
* 'passphrase' => passphrase
* 'compression' => compress value with this compression adapter
* 'package' => pack envelope keys into encrypted string, simplifies decryption
*
* @param string|array $options Options for this adapter
*/
public function __construct($options = array())
{
if (!extension_loaded('openssl')) {
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception('This filter needs the openssl extension');
}
if ($options instanceof Zend_Config) {
$options = $options->toArray();
}
if (!is_array($options)) {
$options = array('public' => $options);
}
if (array_key_exists('passphrase', $options)) {
$this->setPassphrase($options['passphrase']);
unset($options['passphrase']);
}
if (array_key_exists('compression', $options)) {
$this->setCompression($options['compression']);
unset($options['compress']);
}
if (array_key_exists('package', $options)) {
$this->setPackage($options['package']);
unset($options['package']);
}
$this->_setKeys($options);
}
/**
* Sets the encryption keys
*
* @param string|array $keys Key with type association
* @return Zend_Filter_Encrypt_Openssl
*/
protected function _setKeys($keys)
{
if (!is_array($keys)) {
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception('Invalid options argument provided to filter');
}
foreach ($keys as $type => $key) {
if (is_file($key) and is_readable($key)) {
$file = fopen($key, 'r');
$cert = fread($file, 8192);
fclose($file);
} else {
$cert = $key;
$key = count($this->_keys[$type]);
}
switch ($type) {
case 'public':
$test = openssl_pkey_get_public($cert);
if ($test === false) {
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception("Public key '{$cert}' not valid");
}
openssl_free_key($test);
$this->_keys['public'][$key] = $cert;
break;
case 'private':
$test = openssl_pkey_get_private($cert, $this->_passphrase);
if ($test === false) {
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception("Private key '{$cert}' not valid");
}
openssl_free_key($test);
$this->_keys['private'][$key] = $cert;
break;
case 'envelope':
$this->_keys['envelope'][$key] = $cert;
break;
default:
break;
}
}
return $this;
}
/**
* Returns all public keys
*
* @return array
*/
public function getPublicKey()
{
$key = $this->_keys['public'];
return $key;
}
/**
* Sets public keys
*
* @param string|array $key Public keys
* @return Zend_Filter_Encrypt_Openssl
*/
public function setPublicKey($key)
{
if (is_array($key)) {
foreach($key as $type => $option) {
if ($type !== 'public') {
$key['public'] = $option;
unset($key[$type]);
}
}
} else {
$key = array('public' => $key);
}
return $this->_setKeys($key);
}
/**
* Returns all private keys
*
* @return array
*/
public function getPrivateKey()
{
$key = $this->_keys['private'];
return $key;
}
/**
* Sets private keys
*
* @param string $key Private key
* @param string $passphrase
* @return Zend_Filter_Encrypt_Openssl
*/
public function setPrivateKey($key, $passphrase = null)
{
if (is_array($key)) {
foreach($key as $type => $option) {
if ($type !== 'private') {
$key['private'] = $option;
unset($key[$type]);
}
}
} else {
$key = array('private' => $key);
}
if ($passphrase !== null) {
$this->setPassphrase($passphrase);
}
return $this->_setKeys($key);
}
/**
* Returns all envelope keys
*
* @return array
*/
public function getEnvelopeKey()
{
$key = $this->_keys['envelope'];
return $key;
}
/**
* Sets envelope keys
*
* @param string|array $options Envelope keys
* @return Zend_Filter_Encrypt_Openssl
*/
public function setEnvelopeKey($key)
{
if (is_array($key)) {
foreach($key as $type => $option) {
if ($type !== 'envelope') {
$key['envelope'] = $option;
unset($key[$type]);
}
}
} else {
$key = array('envelope' => $key);
}
return $this->_setKeys($key);
}
/**
* Returns the passphrase
*
* @return string
*/
public function getPassphrase()
{
return $this->_passphrase;
}
/**
* Sets a new passphrase
*
* @param string $passphrase
* @return Zend_Filter_Encrypt_Openssl
*/
public function setPassphrase($passphrase)
{
$this->_passphrase = $passphrase;
return $this;
}
/**
* Returns the compression
*
* @return array
*/
public function getCompression()
{
return $this->_compression;
}
/**
* Sets a internal compression for values to encrypt
*
* @param string|array $compression
* @return Zend_Filter_Encrypt_Openssl
*/
public function setCompression($compression)
{
if (is_string($this->_compression)) {
$compression = array('adapter' => $compression);
}
$this->_compression = $compression;
return $this;
}
/**
* Returns if header should be packaged
*
* @return boolean
*/
public function getPackage()
{
return $this->_package;
}
/**
* Sets if the envelope keys should be included in the encrypted value
*
* @param boolean $package
* @return Zend_Filter_Encrypt_Openssl
*/
public function setPackage($package)
{
$this->_package = (boolean) $package;
return $this;
}
/**
* Encrypts $value with the defined settings
* Note that you also need the "encrypted" keys to be able to decrypt
*
* @param string $value Content to encrypt
* @return string The encrypted content
* @throws Zend_Filter_Exception
*/
public function encrypt($value)
{
$encrypted = array();
$encryptedkeys = array();
if (count($this->_keys['public']) == 0) {
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception('Openssl can not encrypt without public keys');
}
$keys = array();
$fingerprints = array();
$count = -1;
foreach($this->_keys['public'] as $key => $cert) {
$keys[$key] = openssl_pkey_get_public($cert);
if ($this->_package) {
$details = openssl_pkey_get_details($keys[$key]);
if ($details === false) {
$details = array('key' => 'ZendFramework');
}
++$count;
$fingerprints[$count] = md5($details['key']);
}
}
// compress prior to encryption
if (!empty($this->_compression)) {
require_once 'Zend/Filter/Compress.php';
$compress = new Zend_Filter_Compress($this->_compression);
$value = $compress->filter($value);
}
$crypt = openssl_seal($value, $encrypted, $encryptedkeys, $keys);
foreach ($keys as $key) {
openssl_free_key($key);
}
if ($crypt === false) {
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception('Openssl was not able to encrypt your content with the given options');
}
$this->_keys['envelope'] = $encryptedkeys;
// Pack data and envelope keys into single string
if ($this->_package) {
$header = pack('n', count($this->_keys['envelope']));
foreach($this->_keys['envelope'] as $key => $envKey) {
$header .= pack('H32n', $fingerprints[$key], strlen($envKey)) . $envKey;
}
$encrypted = $header . $encrypted;
}
return $encrypted;
}
/**
* Defined by Zend_Filter_Interface
*
* Decrypts $value with the defined settings
*
* @param string $value Content to decrypt
* @return string The decrypted content
* @throws Zend_Filter_Exception
*/
public function decrypt($value)
{
$decrypted = "";
$envelope = current($this->getEnvelopeKey());
if (count($this->_keys['private']) !== 1) {
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception('Please give a private key for decryption with Openssl');
}
if (!$this->_package && empty($envelope)) {
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception('Please give a envelope key for decryption with Openssl');
}
foreach($this->_keys['private'] as $key => $cert) {
$keys = openssl_pkey_get_private($cert, $this->getPassphrase());
}
if ($this->_package) {
$details = openssl_pkey_get_details($keys);
if ($details !== false) {
$fingerprint = md5($details['key']);
} else {
$fingerprint = md5("ZendFramework");
}
$count = unpack('ncount', $value);
$count = $count['count'];
$length = 2;
for($i = $count; $i > 0; --$i) {
$header = unpack('H32print/nsize', substr($value, $length, 18));
$length += 18;
if ($header['print'] == $fingerprint) {
$envelope = substr($value, $length, $header['size']);
}
$length += $header['size'];
}
// remainder of string is the value to decrypt
$value = substr($value, $length);
}
$crypt = openssl_open($value, $decrypted, $envelope, $keys);
openssl_free_key($keys);
if ($crypt === false) {
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception('Openssl was not able to decrypt you content with the given options');
}
// decompress after decryption
if (!empty($this->_compression)) {
require_once 'Zend/Filter/Decompress.php';
$decompress = new Zend_Filter_Decompress($this->_compression);
$decrypted = $decompress->filter($decrypted);
}
return $decrypted;
}
/**
* Returns the adapter name
*
* @return string
*/
public function toString()
{
return 'Openssl';
}
}