Вход Регистрация
Файл: concrete5.7.5.6/concrete/vendor/zendframework/zend-crypt/src/PublicKey/DiffieHellman.php
Строк: 539
<?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 ZendCryptPublicKey;

use 
ZendCryptException;
use 
ZendMath;

/**
 * PHP implementation of the Diffie-Hellman public key encryption algorithm.
 * Allows two unassociated parties to establish a joint shared secret key
 * to be used in encrypting subsequent communications.
 */
class DiffieHellman
{
    const 
DEFAULT_KEY_SIZE 2048;

    
/**
     * Key formats
     */
    
const FORMAT_BINARY 'binary';
    const 
FORMAT_NUMBER 'number';
    const 
FORMAT_BTWOC  'btwoc';

    
/**
     * Static flag to select whether to use PHP5.3's openssl extension
     * if available.
     *
     * @var bool
     */
    
public static $useOpenssl true;

    
/**
     * Default large prime number; required by the algorithm.
     *
     * @var string
     */
    
private $prime null;

    
/**
     * The default generator number. This number must be greater than 0 but
     * less than the prime number set.
     *
     * @var string
     */
    
private $generator null;

    
/**
     * A private number set by the local user. It's optional and will
     * be generated if not set.
     *
     * @var string
     */
    
private $privateKey null;

    
/**
     * BigInteger support object courtesy of ZendMath
     *
     * @var ZendMathBigIntegerAdapterAdapterInterface
     */
    
private $math null;

    
/**
     * The public key generated by this instance after calling generateKeys().
     *
     * @var string
     */
    
private $publicKey null;

    
/**
     * The shared secret key resulting from a completed Diffie Hellman
     * exchange
     *
     * @var string
     */
    
private $secretKey null;

    
/**
     * @var resource
     */
    
protected $opensslKeyResource null;

    
/**
     * Constructor; if set construct the object using the parameter array to
     * set values for Prime, Generator and Private.
     * If a Private Key is not set, one will be generated at random.
     *
     * @param string $prime
     * @param string $generator
     * @param string $privateKey
     * @param string $privateKeyFormat
     */
    
public function __construct($prime$generator$privateKey null$privateKeyFormat self::FORMAT_NUMBER)
    {
        
$this->setPrime($prime);
        
$this->setGenerator($generator);
        if (
$privateKey !== null) {
            
$this->setPrivateKey($privateKey$privateKeyFormat);
        }

        
// set up BigInteger adapter
        
$this->math MathBigIntegerBigInteger::factory();
    }

    
/**
     * Set whether to use openssl extension
     *
     * @static
     * @param bool $flag
     */
    
public static function useOpensslExtension($flag true)
    {
        static::
$useOpenssl = (bool) $flag;
    }

    
/**
     * Generate own public key. If a private number has not already been set,
     * one will be generated at this stage.
     *
     * @return DiffieHellman
     * @throws ZendCryptExceptionRuntimeException
     */
    
public function generateKeys()
    {
        if (
function_exists('openssl_dh_compute_key') && static::$useOpenssl !== false) {
            
$details = array(
                
'p' => $this->convert($this->getPrime(), self::FORMAT_NUMBERself::FORMAT_BINARY),
                
'g' => $this->convert($this->getGenerator(), self::FORMAT_NUMBERself::FORMAT_BINARY)
            );
            if (
$this->hasPrivateKey()) {
                
$details['priv_key'] = $this->convert(
                    
$this->privateKeyself::FORMAT_NUMBERself::FORMAT_BINARY
                
);
                
$opensslKeyResource openssl_pkey_new(array('dh' => $details));
            } else {
                
$opensslKeyResource openssl_pkey_new(array(
                    
'dh'               => $details,
                    
'private_key_bits' => self::DEFAULT_KEY_SIZE,
                    
'private_key_type' => OPENSSL_KEYTYPE_DH
                
));
            }

            if (
false === $opensslKeyResource) {
                throw new 
ExceptionRuntimeException(
                    
'Can not generate new key; openssl ' openssl_error_string()
                );
            }

            
$data openssl_pkey_get_details($opensslKeyResource);

            
$this->setPrivateKey($data['dh']['priv_key'], self::FORMAT_BINARY);
            
$this->setPublicKey($data['dh']['pub_key'], self::FORMAT_BINARY);

            
$this->opensslKeyResource $opensslKeyResource;
        } else {
            
// Private key is lazy generated in the absence of ext/openssl
            
$publicKey $this->math->powmod($this->getGenerator(), $this->getPrivateKey(), $this->getPrime());
            
$this->setPublicKey($publicKey);
        }

        return 
$this;
    }

    
/**
     * Setter for the value of the public number
     *
     * @param string $number
     * @param string $format
     * @return DiffieHellman
     * @throws ZendCryptExceptionInvalidArgumentException
     */
    
public function setPublicKey($number$format self::FORMAT_NUMBER)
    {
        
$number $this->convert($number$formatself::FORMAT_NUMBER);
        if (!
preg_match('/^d+$/'$number)) {
            throw new 
ExceptionInvalidArgumentException('Invalid parameter; not a positive natural number');
        }
        
$this->publicKey = (string) $number;

        return 
$this;
    }

    
/**
     * Returns own public key for communication to the second party to this transaction
     *
     * @param string $format
     * @return string
     * @throws ZendCryptExceptionInvalidArgumentException
     */
    
public function getPublicKey($format self::FORMAT_NUMBER)
    {
        if (
$this->publicKey === null) {
            throw new 
ExceptionInvalidArgumentException(
                
'A public key has not yet been generated using a prior call to generateKeys()'
            
);
        }

        return 
$this->convert($this->publicKeyself::FORMAT_NUMBER$format);
    }

    
/**
     * Compute the shared secret key based on the public key received from the
     * the second party to this transaction. This should agree to the secret
     * key the second party computes on our own public key.
     * Once in agreement, the key is known to only to both parties.
     * By default, the function expects the public key to be in binary form
     * which is the typical format when being transmitted.
     *
     * If you need the binary form of the shared secret key, call
     * getSharedSecretKey() with the optional parameter for Binary output.
     *
     * @param string $publicKey
     * @param string $publicKeyFormat
     * @param string $secretKeyFormat
     * @return string
     * @throws ZendCryptExceptionInvalidArgumentException
     * @throws ZendCryptExceptionRuntimeException
     */
    
public function computeSecretKey($publicKey$publicKeyFormat self::FORMAT_NUMBER,
                                                 
$secretKeyFormat self::FORMAT_NUMBER)
    {
        if (
function_exists('openssl_dh_compute_key') && static::$useOpenssl !== false) {
            
$publicKey $this->convert($publicKey$publicKeyFormatself::FORMAT_BINARY);
            
$secretKey openssl_dh_compute_key($publicKey$this->opensslKeyResource);
            if (
false === $secretKey) {
                throw new 
ExceptionRuntimeException(
                    
'Can not compute key; openssl ' openssl_error_string()
                );
            }
            
$this->secretKey $this->convert($secretKeyself::FORMAT_BINARYself::FORMAT_NUMBER);
        } else {
            
$publicKey $this->convert($publicKey$publicKeyFormatself::FORMAT_NUMBER);
            if (!
preg_match('/^d+$/'$publicKey)) {
                throw new 
ExceptionInvalidArgumentException(
                    
'Invalid parameter; not a positive natural number'
                
);
            }
            
$this->secretKey $this->math->powmod($publicKey$this->getPrivateKey(), $this->getPrime());
        }

        return 
$this->getSharedSecretKey($secretKeyFormat);
    }

    
/**
     * Return the computed shared secret key from the DiffieHellman transaction
     *
     * @param string $format
     * @return string
     * @throws ZendCryptExceptionInvalidArgumentException
     */
    
public function getSharedSecretKey($format self::FORMAT_NUMBER)
    {
        if (!isset(
$this->secretKey)) {
            throw new 
ExceptionInvalidArgumentException(
                
'A secret key has not yet been computed; call computeSecretKey() first'
            
);
        }

        return 
$this->convert($this->secretKeyself::FORMAT_NUMBER$format);
    }

    
/**
     * Setter for the value of the prime number
     *
     * @param string $number
     * @return DiffieHellman
     * @throws ZendCryptExceptionInvalidArgumentException
     */
    
public function setPrime($number)
    {
        if (!
preg_match('/^d+$/'$number) || $number 11) {
            throw new 
ExceptionInvalidArgumentException(
                
'Invalid parameter; not a positive natural number or too small: ' .
                
'should be a large natural number prime'
            
);
        }
        
$this->prime = (string) $number;

        return 
$this;
    }

    
/**
     * Getter for the value of the prime number
     *
     * @param string $format
     * @return string
     * @throws ZendCryptExceptionInvalidArgumentException
     */
    
public function getPrime($format self::FORMAT_NUMBER)
    {
        if (!isset(
$this->prime)) {
            throw new 
ExceptionInvalidArgumentException('No prime number has been set');
        }

        return 
$this->convert($this->primeself::FORMAT_NUMBER$format);
    }


    
/**
     * Setter for the value of the generator number
     *
     * @param string $number
     * @return DiffieHellman
     * @throws ZendCryptExceptionInvalidArgumentException
     */
    
public function setGenerator($number)
    {
        if (!
preg_match('/^d+$/'$number) || $number 2) {
            throw new 
ExceptionInvalidArgumentException(
                
'Invalid parameter; not a positive natural number greater than 1'
            
);
        }
        
$this->generator = (string) $number;

        return 
$this;
    }

    
/**
     * Getter for the value of the generator number
     *
     * @param string $format
     * @return string
     * @throws ZendCryptExceptionInvalidArgumentException
     */
    
public function getGenerator($format self::FORMAT_NUMBER)
    {
        if (!isset(
$this->generator)) {
            throw new 
ExceptionInvalidArgumentException('No generator number has been set');
        }

        return 
$this->convert($this->generatorself::FORMAT_NUMBER$format);
    }

    
/**
     * Setter for the value of the private number
     *
     * @param string $number
     * @param string $format
     * @return DiffieHellman
     * @throws ZendCryptExceptionInvalidArgumentException
     */
    
public function setPrivateKey($number$format self::FORMAT_NUMBER)
    {
        
$number $this->convert($number$formatself::FORMAT_NUMBER);
        if (!
preg_match('/^d+$/'$number)) {
            throw new 
ExceptionInvalidArgumentException('Invalid parameter; not a positive natural number');
        }
        
$this->privateKey = (string) $number;

        return 
$this;
    }

    
/**
     * Getter for the value of the private number
     *
     * @param string $format
     * @return string
     */
    
public function getPrivateKey($format self::FORMAT_NUMBER)
    {
        if (!
$this->hasPrivateKey()) {
            
$this->setPrivateKey($this->generatePrivateKey(), self::FORMAT_BINARY);
        }

        return 
$this->convert($this->privateKeyself::FORMAT_NUMBER$format);
    }

    
/**
     * Check whether a private key currently exists.
     *
     * @return bool
     */
    
public function hasPrivateKey()
    {
        return isset(
$this->privateKey);
    }

    
/**
     * Convert number between formats
     *
     * @param $number
     * @param string $inputFormat
     * @param string $outputFormat
     * @return string
     */
    
protected function convert($number$inputFormat self::FORMAT_NUMBER,
                                        
$outputFormat self::FORMAT_BINARY)
    {
        if (
$inputFormat == $outputFormat) {
            return 
$number;
        }

        
// convert to number
        
switch ($inputFormat) {
            case 
self::FORMAT_BINARY:
            case 
self::FORMAT_BTWOC:
                
$number $this->math->binToInt($number);
                break;
            case 
self::FORMAT_NUMBER:
            default:
                
// do nothing
                
break;
        }

        
// convert to output format
        
switch ($outputFormat) {
            case 
self::FORMAT_BINARY:
                return 
$this->math->intToBin($number);
                break;
            case 
self::FORMAT_BTWOC:
                return 
$this->math->intToBin($numbertrue);
                break;
            case 
self::FORMAT_NUMBER:
            default:
                return 
$number;
                break;
        }
    }

    
/**
     * In the event a private number/key has not been set by the user,
     * or generated by ext/openssl, a best attempt will be made to
     * generate a random key. Having a random number generator installed
     * on linux/bsd is highly recommended! The alternative is not recommended
     * for production unless without any other option.
     *
     * @return string
     */
    
protected function generatePrivateKey()
    {
        return 
MathRand::getBytes(strlen($this->getPrime()), true);
    }
}
Онлайн: 3
Реклама