Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Issue #10730: Implement new crypto_api
This implements the foundation of a new Cryptography API which is responsible for providing cryptography functionality to MantisBT. For now, the only feature available in this new API is the generation of secure and strong randomness using openssl_random_pseudo_bytes in PHP 5.3 (if available), /dev/urandom if available on the system or an enhanced mt_rand generator built on top of PHP's existing Mersenne Twister pseudo random number. We used to just rely on a single mt_rand() for generating nonces or providing other cryptographic functionality. This posed a number of problems including the leakage of the internal state of the Mersenne Twister PRNG, enabling users to predict all future outputs of the PRNG. Additionally, the total number of combinations available from mt_rand() is very small when in many cases we need more than a few million combinations of keys. The new approach calls mt_rand() multiple times and then using a secret unique salt known only to each MantisBT installation, hashes the output using the Whirlpool algorithm. This produces 512bits of output that can be used for creating a random string/nonce. If more than 512bits of output are required, we simply perform this operation multiple times until we have generated enough output. While the new Mersenne Twister method for generating random strings is still anything but strong or secure, it does raise the bar significantly. It is hoped that this method is only used as a last resort when no other options for generating strong randomness are available. A new configuration option $g_crypto_master_salt was also added to form the basis of salting and hashing functions in the future. Currently we use different keys for RSS, signup/lost password verification and so forth when it'd be much easier to just derive keys as needed from the master salt. If $g_crypto_master_salt is not defined by the user, MantisBT will refuse to work. This salt must be at least 16 characters long in the hope that users who don't understand the importance of setting a strong master salt are informed of their mistake. This refusal to work unless the user sets a strong $g_crypto_master_salt value in config_inc.php is necessary because it forms the basis for a lot of the security features implemented in MantisBT. We don't want users to forgetting to set $g_crypto_master_salt and using a default value known to the entire world.
- Loading branch information
1 parent
cca2566
commit 045a897
Showing
10 changed files
with
266 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
<?php | ||
# MantisBT - A PHP based bugtracking system | ||
|
||
# MantisBT is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 2 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# MantisBT is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with MantisBT. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
/** | ||
* Crypto API | ||
* | ||
* @package CoreAPI | ||
* @subpackage CryptoAPI | ||
* @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org | ||
* @copyright Copyright (C) 2002 - 2010 MantisBT Team - mantisbt-dev@lists.sourceforge.net | ||
* @link http://www.mantisbt.org | ||
* | ||
* @uses config_api.php | ||
* @uses constant_inc.php | ||
* @uses error_api.php | ||
*/ | ||
|
||
require_api( 'config_api.php' ); | ||
require_api( 'constant_inc.php' ); | ||
require_api( 'error_api.php' ); | ||
|
||
/** | ||
* Initialise the CryptoAPI subsystem. This function checks whether the master | ||
* salt is specified correctly within the configuration. If not, a fatal error | ||
* is produced to protect against invalid configuration impacting the security | ||
* of the MantisBT installation. | ||
* @return null | ||
*/ | ||
function crypto_init() { | ||
if ( !defined( 'MANTIS_MAINTENANCE_MODE' ) ) { | ||
if ( strlen( config_get_global( 'crypto_master_salt' ) ) < 16 ) { | ||
trigger_error( ERROR_CRYPTO_MASTER_SALT_INVALID, ERROR ); | ||
} | ||
} | ||
return; | ||
} | ||
|
||
/** | ||
* Generate a random string (raw binary output) for cryptographic purposes such | ||
* as nonces, IVs, default passwords, etc. This function will attempt to | ||
* generate strong randomness but can optionally be used to generate weaker | ||
* randomness if less security is needed or a strong source of randomness isn't | ||
* available. The use of weak randomness for cryptographic purposes is strongly | ||
* discouraged because it contains low entropy and is predictable. | ||
* @param int $p_bytes Number of bytes of randomness required | ||
* @param bool $p_require_strong_generator Whether or not a weak source of randomness can be used by this function | ||
* @return string|null Raw binary string containing the requested number of bytes of random output or null if the output couldn't be created | ||
*/ | ||
function crypto_generate_random_string( $p_bytes, $p_require_strong_generator = true ) { | ||
|
||
# First we attempt to use the secure PRNG provided by OpenSSL in PHP 5.3 | ||
if ( function_exists( 'openssl_random_pseudo_bytes' ) ) { | ||
$t_random_bytes = openssl_random_pseudo_bytes( $p_bytes, $t_strong ); | ||
if ( $t_random_bytes !== false ) { | ||
if ( $p_require_strong_generator && $t_strong === true ) { | ||
$t_random_string = $t_random_bytes; | ||
} else if ( !$p_require_strong_generator ) { | ||
$t_random_string = $t_random_bytes; | ||
} | ||
} | ||
} | ||
|
||
# Next we try to use the /dev/urandom PRNG provided on Linux systems. This | ||
# is nowhere near as secure as /dev/random but it is still satisfactory for | ||
# the needs of MantisBT, especially given the fact that we don't want this | ||
# function to block while waiting for the system to generate more entropy. | ||
$t_urandom_fp = @fopen( '/dev/urandom', 'rb' ); | ||
if ( $t_urandom_fp !== false ) { | ||
$t_random_bytes = @fread( $t_urandom_fp, $p_bytes ); | ||
if ( $t_random_bytes !== false ) { | ||
$t_random_string = $t_random_bytes; | ||
} | ||
@fclose( $t_urandom_fp ); | ||
} | ||
|
||
# For Windows systems, we can try using Microsoft CryptoAPI to retrieve | ||
# more reliable PRNG output than what PHP can provide by itself. | ||
# !TODO | ||
|
||
# At this point we've run out of possibilities for generating randomness | ||
# from a strong source. Unless weak output is specifically allowed by the | ||
# $p_require_strong_generator argument, we should return null as we've | ||
# failed to generate randomness to a satisfactory security level. | ||
if ( !isset( $t_random_string ) && $p_require_strong_generator ) { | ||
return null; | ||
} | ||
|
||
# As a last resort we have to fall back to using the insecure Mersenne | ||
# Twister pseudo random number generator provided in PHP. This DOES NOT | ||
# produce cryptographically secure randomness and thus the output of the | ||
# PRNG is easily guessable. In an attempt to make it harder to guess the | ||
# internal state of the PRNG, we salt the PRNG output with a known secret | ||
# and hash it. | ||
if ( !isset( $t_random_string ) ) { | ||
$t_secret_key = 'prng' . config_get_global( 'crypto_master_salt' ); | ||
$t_random_bytes = ''; | ||
for ( $i = 0; $i < $p_bytes; $i += 64 ) { | ||
$t_random_segment = ''; | ||
for ( $j = 0; $j < 64; $j++ ) { | ||
$t_random_segment .= base_convert( mt_rand(), 10, 36 ); | ||
} | ||
$t_random_segment .= $i; | ||
$t_random_segment .= $t_secret_key; | ||
$t_random_bytes .= hash( 'whirlpool', $t_random_segment, true ); | ||
} | ||
$t_random_string = substr( $t_random_bytes, 0, $p_bytes ); | ||
if ( $t_random_string === false ) { | ||
return null; # Unexpected error | ||
} | ||
} | ||
|
||
return $t_random_string; | ||
} | ||
|
||
/** | ||
* Generate a strong random string (raw binary output) for cryptographic | ||
* purposes such as nonces, IVs, default passwords, etc. If a strong source | ||
* of randomness is not available, this function will fail and produce an | ||
* error. Strong randomness is different from weak randomness in that a strong | ||
* randomness generator doesn't produce predictable output and has much higher | ||
* entropy. Where randomness is being used for cryptographic purposes, a strong | ||
* source of randomness should always be used. | ||
* @param int $p_bytes Number of bytes of strong randomness required | ||
* @return string Raw binary string containing the requested number of bytes of random output | ||
*/ | ||
function crypto_generate_strong_random_string( $p_bytes ) { | ||
$t_random_string = crypto_generate_random_string( $p_bytes, true ); | ||
if ( $t_random_string === null ) { | ||
trigger_error( ERROR_CRYPTO_CAN_NOT_GENERATE_STRONG_RANDOMNESS, ERROR ); | ||
} | ||
return $t_random_string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.