File indexing completed on 2024-12-22 05:36:34

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Crypt
0017  * @subpackage Math
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  * @version    $Id$
0021  */
0022 
0023 /**
0024  * @see Zend_Crypt_Math_BigInteger
0025  */
0026 // require_once 'Zend/Crypt/Math/BigInteger.php';
0027 
0028 /**
0029  * @category   Zend
0030  * @package    Zend_Crypt
0031  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0032  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0033  */
0034 class Zend_Crypt_Math extends Zend_Crypt_Math_BigInteger
0035 {
0036 
0037     /**
0038      * Generate a pseudorandom number within the given range.
0039      * Will attempt to read from a systems RNG if it exists or else utilises
0040      * a simple random character to maximum length process. Simplicity
0041      * is a factor better left for development...
0042      *
0043      * @param string|int $minimum
0044      * @param string|int $maximum
0045      * @return string
0046      */
0047     public function rand($minimum, $maximum)
0048     {
0049         if (file_exists('/dev/urandom')) {
0050             $frandom = fopen('/dev/urandom', 'r');
0051             if ($frandom !== false) {
0052                 return fread($frandom, strlen($maximum) - 1);
0053             }
0054         }
0055         if (strlen($maximum) < 4) {
0056             return mt_rand($minimum, $maximum - 1);
0057         }
0058         $rand = '';
0059         $i2 = strlen($maximum) - 1;
0060         for ($i = 1; $i < $i2; $i++) {
0061             $rand .= mt_rand(0, 9);
0062         }
0063         $rand .= mt_rand(0, 9);
0064         return $rand;
0065     }
0066 
0067     /**
0068      * Return a random strings of $length bytes
0069      *
0070      * @param  integer $length
0071      * @param  boolean $strong
0072      * @return string
0073      */
0074     public static function randBytes($length, $strong = false)
0075     {
0076         $length = (int) $length;
0077         if ($length <= 0) {
0078             return false;
0079         }
0080         if (function_exists('random_bytes')) { // available in PHP 7
0081             return random_bytes($length);
0082         }
0083         if (function_exists('mcrypt_create_iv')) {
0084             $bytes = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
0085             if ($bytes !== false && strlen($bytes) === $length) {
0086                 return $bytes;
0087             }
0088         }
0089         if (file_exists('/dev/urandom') && is_readable('/dev/urandom')) {
0090             $frandom = fopen('/dev/urandom', 'r');
0091             if ($frandom !== false) {
0092                 return fread($frandom, $length);
0093             }
0094         }
0095         if (true === $strong) {
0096             // require_once 'Zend/Crypt/Exception.php';
0097             throw new Zend_Crypt_Exception(
0098                 'This PHP environment doesn\'t support secure random number generation. ' .
0099                 'Please consider installing the OpenSSL and/or Mcrypt extensions'
0100             );
0101         }
0102         $rand = '';
0103         for ($i = 0; $i < $length; $i++) {
0104             $rand .= chr(mt_rand(0, 255));
0105         }
0106         return $rand;
0107     }
0108 
0109     /**
0110      * Return a random integer between $min and $max
0111      *
0112      * @param  integer $min
0113      * @param  integer $max
0114      * @param  boolean $strong
0115      * @return integer
0116      */
0117     public static function randInteger($min, $max, $strong = false)
0118     {
0119         if ($min > $max) {
0120             // require_once 'Zend/Crypt/Exception.php';
0121             throw new Zend_Crypt_Exception(
0122                 'The min parameter must be lower than max parameter'
0123             );
0124         }
0125         $range = $max - $min;
0126         if ($range == 0) {
0127             return $max;
0128         } elseif ($range > PHP_INT_MAX || is_float($range)) {
0129             // require_once 'Zend/Crypt/Exception.php';
0130             throw new Zend_Crypt_Exception(
0131                 'The supplied range is too great to generate'
0132             );
0133         }
0134         if (function_exists('random_int')) { // available in PHP 7
0135             return random_int($min, $max);
0136         }
0137         // calculate number of bits required to store range on this machine
0138         $r = $range;
0139         $bits = 0;
0140         while ($r) {
0141             $bits++;
0142             $r >>= 1;
0143         }
0144         $bits   = (int) max($bits, 1);
0145         $bytes  = (int) max(ceil($bits / 8), 1);
0146         $filter = (int) ((1 << $bits) - 1);
0147         do {
0148             $rnd  = hexdec(bin2hex(self::randBytes($bytes, $strong)));
0149             $rnd &= $filter;
0150         } while ($rnd > $range);
0151         return ($min + $rnd);
0152     }
0153 
0154     /**
0155      * Get the big endian two's complement of a given big integer in
0156      * binary notation
0157      *
0158      * @param string $long
0159      * @return string
0160      */
0161     public function btwoc($long)
0162     {
0163         if (ord($long[0]) > 127) {
0164             return "\x00" . $long;
0165         }
0166         return $long;
0167     }
0168 
0169     /**
0170      * Translate a binary form into a big integer string
0171      *
0172      * @param string $binary
0173      * @return string
0174      */
0175     public function fromBinary($binary)
0176     {
0177         return $this->_math->binaryToInteger($binary);
0178     }
0179 
0180     /**
0181      * Translate a big integer string into a binary form
0182      *
0183      * @param string $integer
0184      * @return string
0185      */
0186     public function toBinary($integer)
0187     {
0188         return $this->_math->integerToBinary($integer);
0189     }
0190 }