[ Index ]

PHP Cross Reference of MantisBT

title

Body

[close]

/core/ -> crypto_api.php (source)

   1  <?php
   2  # MantisBT - A PHP based bugtracking system
   3  
   4  # MantisBT is free software: you can redistribute it and/or modify
   5  # it under the terms of the GNU General Public License as published by
   6  # the Free Software Foundation, either version 2 of the License, or
   7  # (at your option) any later version.
   8  #
   9  # MantisBT is distributed in the hope that it will be useful,
  10  # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  # GNU General Public License for more details.
  13  #
  14  # You should have received a copy of the GNU General Public License
  15  # along with MantisBT.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * Crypto API
  19   *
  20   * @package CoreAPI
  21   * @subpackage CryptoAPI
  22   * @copyright Copyright (C) 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
  23   * @copyright Copyright (C) 2002 - 2011  MantisBT Team - mantisbt-dev@lists.sourceforge.net
  24   * @link http://www.mantisbt.org
  25   *
  26   * @uses config_api.php
  27   * @uses constant_inc.php
  28   * @uses error_api.php
  29   * @uses utility_api.php
  30   */
  31  
  32  require_api( 'config_api.php' );
  33  require_api( 'constant_inc.php' );
  34  require_api( 'error_api.php' );
  35  require_api( 'utility_api.php' );
  36  
  37  /**
  38   * Initialise the CryptoAPI subsystem. This function checks whether the master
  39   * salt is specified correctly within the configuration. If not, a fatal error
  40   * is produced to protect against invalid configuration impacting the security
  41   * of the MantisBT installation.
  42   * @return null
  43   */
  44  function crypto_init() {
  45      if ( !defined( 'MANTIS_MAINTENANCE_MODE' ) ) {
  46          if ( strlen( config_get_global( 'crypto_master_salt' ) ) < 16 ) {
  47              trigger_error( ERROR_CRYPTO_MASTER_SALT_INVALID, ERROR );
  48          }
  49      }
  50      return;
  51  }
  52  
  53  /**
  54   * Generate a random string (raw binary output) for cryptographic purposes such
  55   * as nonces, IVs, default passwords, etc. This function will attempt to
  56   * generate strong randomness but can optionally be used to generate weaker
  57   * randomness if less security is needed or a strong source of randomness isn't
  58   * available. The use of weak randomness for cryptographic purposes is strongly
  59   * discouraged because it contains low entropy and is predictable.
  60   *
  61   * Note that openssl_random_pseudo_bytes seems to perform very poorly on
  62   * Windows servers. Therefore we don't event attempt to use this PRNG source
  63   * if the server is running Windows.
  64   *
  65   * @param int $p_bytes Number of bytes of randomness required
  66   * @param bool $p_require_strong_generator Whether or not a weak source of randomness can be used by this function
  67   * @return string|null Raw binary string containing the requested number of bytes of random output or null if the output couldn't be created
  68   */
  69  function crypto_generate_random_string( $p_bytes, $p_require_strong_generator = true ) {
  70  
  71      # First we attempt to use the secure PRNG provided by OpenSSL in PHP 5.3
  72      # Exclude Windows as per http://bugs.php.net/bug.php?id=51636
  73      if ( !is_windows_server() && function_exists( 'openssl_random_pseudo_bytes' ) ) {
  74          $t_random_bytes = openssl_random_pseudo_bytes( $p_bytes, $t_strong );
  75          if ( $t_random_bytes !== false ) {
  76              if ( $p_require_strong_generator && $t_strong === true ) {
  77                  $t_random_string = $t_random_bytes;
  78              } else if ( !$p_require_strong_generator ) {
  79                  $t_random_string = $t_random_bytes;
  80              }
  81          }
  82      }
  83  
  84      # Next we try to use the /dev/urandom PRNG provided on Linux systems. This
  85      # is nowhere near as secure as /dev/random but it is still satisfactory for
  86      # the needs of MantisBT, especially given the fact that we don't want this
  87      # function to block while waiting for the system to generate more entropy.
  88      if ( !is_windows_server() ) {
  89          $t_urandom_fp = @fopen( '/dev/urandom', 'rb' );
  90          if ( $t_urandom_fp !== false ) {
  91              $t_random_bytes = @fread( $t_urandom_fp, $p_bytes );
  92              if ( $t_random_bytes !== false ) {
  93                  $t_random_string = $t_random_bytes;
  94              }
  95              @fclose( $t_urandom_fp );
  96          }
  97      }
  98  
  99      # For Windows systems, we can try using Microsoft CryptoAPI to retrieve
 100      # more reliable PRNG output than what PHP can provide by itself.
 101      # !TODO
 102  
 103      # At this point we've run out of possibilities for generating randomness
 104      # from a strong source. Unless weak output is specifically allowed by the
 105      # $p_require_strong_generator argument, we should return null as we've
 106      # failed to generate randomness to a satisfactory security level.
 107      if ( !isset( $t_random_string ) && $p_require_strong_generator ) {
 108          return null;
 109      }
 110  
 111      # As a last resort we have to fall back to using the insecure Mersenne
 112      # Twister pseudo random number generator provided in PHP. This DOES NOT
 113      # produce cryptographically secure randomness and thus the output of the
 114      # PRNG is easily guessable. In an attempt to make it harder to guess the
 115      # internal state of the PRNG, we salt the PRNG output with a known secret
 116      # and hash it.
 117      if ( !isset( $t_random_string ) ) {
 118          $t_secret_key = 'prng' . config_get_global( 'crypto_master_salt' );
 119          $t_random_bytes = '';
 120          for ( $i = 0; $i < $p_bytes; $i += 64 ) {
 121              $t_random_segment = '';
 122              for ( $j = 0; $j < 64; $j++ ) {
 123                  $t_random_segment .= base_convert( mt_rand(), 10, 36 );
 124              }
 125              $t_random_segment .= $i;
 126              $t_random_segment .= $t_secret_key;
 127              $t_random_bytes .= hash( 'whirlpool', $t_random_segment, true );
 128          }
 129          $t_random_string = substr( $t_random_bytes, 0, $p_bytes );
 130          if ( $t_random_string === false ) {
 131              return null; # Unexpected error
 132          }
 133      }
 134  
 135      return $t_random_string;
 136  }
 137  
 138  /**
 139   * Generate a strong random string (raw binary output) for cryptographic
 140   * purposes such as nonces, IVs, default passwords, etc. If a strong source
 141   * of randomness is not available, this function will fail and produce an
 142   * error. Strong randomness is different from weak randomness in that a strong
 143   * randomness generator doesn't produce predictable output and has much higher
 144   * entropy. Where randomness is being used for cryptographic purposes, a strong
 145   * source of randomness should always be used.
 146   * @param int $p_bytes Number of bytes of strong randomness required
 147   * @return string Raw binary string containing the requested number of bytes of random output
 148   */
 149  function crypto_generate_strong_random_string( $p_bytes ) {
 150      $t_random_string = crypto_generate_random_string( $p_bytes, true );
 151      if ( $t_random_string === null ) {
 152          trigger_error( ERROR_CRYPTO_CAN_NOT_GENERATE_STRONG_RANDOMNESS, ERROR );
 153      }
 154      return $t_random_string;
 155  }
 156  
 157  /**
 158   * Generate a nonce encoded using the base64 with URI safe alphabet approach
 159   * described in RFC4648. Note that the minimum length is rounded up to the next
 160   * number with a factor of 4 so that padding is never added to the end of the
 161   * base64 output. This means the '=' padding character is never present in the
 162   * output. Due to the reduced character set of base64 encoding, the actual
 163   * amount of entropy produced by this function for a given output string length
 164   * is 3/4 (0.75) that of raw unencoded output produced with the
 165   * crypto_generate_strong_random_string( $p_bytes ) function.
 166   * @param int $p_minimum_length Minimum number of characters required for the nonce
 167   * @return string Nonce encoded according to the base64 with URI safe alphabet approach described in RFC4648
 168   */
 169  function crypto_generate_uri_safe_nonce( $p_minimum_length ) {
 170      $t_length_mod4 = $p_minimum_length % 4;
 171      $t_adjusted_length = $p_minimum_length + 4 - ($t_length_mod4 ? $t_length_mod4 : 4);
 172      $t_raw_bytes_required = ( $t_adjusted_length / 4 ) * 3;
 173      if ( !is_windows_server() ) {
 174          $t_random_bytes = crypto_generate_strong_random_string( $t_raw_bytes_required );
 175      } else {
 176          # It's currently not possible to generate strong random numbers
 177          # with PHP on Windows so we have to resort to using PHP's
 178          # built-in insecure PRNG.
 179          $t_random_bytes = crypto_generate_random_string( $t_raw_bytes_required, false );
 180      }
 181      $t_base64_encoded = base64_encode( $t_random_bytes );
 182      # Note: no need to translate trailing = padding characters because our
 183      # length rounding ensures that padding is never required.
 184      $t_random_nonce = strtr( $t_base64_encoded, '+/', '-_' );
 185      return $t_random_nonce;
 186  }


Generated: Thu Jul 28 15:48:31 2011 Cross-referenced by PHPXref 0.7