Index: src/wp-includes/pluggable.php
===================================================================
--- src/wp-includes/pluggable.php	(revision 31466)
+++ src/wp-includes/pluggable.php	(working copy)
@@ -2005,30 +2005,210 @@
 	for ( $i = 0; $i < $length; $i++ ) {
 		$password .= substr($chars, wp_rand(0, strlen($chars) - 1), 1);
 	}
 
 	/**
 	 * Filter the randomly-generated password.
 	 *
 	 * @since 3.0.0
 	 *
 	 * @param string $password The generated password.
 	 */
 	return apply_filters( 'random_password', $password );
 }
 endif;
 
+/**
+ * Generate a cryptographically secure random string
+ * @ref http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
+ *
+ * @param int $bytes Number of random bytes.
+ * @return string A string of random charcters of $bytes length.
+ */
+function wp_random_bytes( $bytes = 32 ) {
+
+	// Uses system native Crypto API in most OS's
+	// Uses native Windows Crypto API in PHP 5.3+ (MCRYPT_DEV_URANDOM)
+	// Prior to 5.3.7 this may also fatal on Windows - https://bugs.php.net/bug.php?id=55169
+	$use_mcrypt = function_exists('mcrypt_create_iv');
+	$use_mcrypt = $use_mcrypt && ! ( 'WIN' == substr( PHP_OS, 0, 3 ) && version_compare( phpversion(), '5.3.7', '<') );
+	if ( $use_mcrypt ) {
+		$buf = mcrypt_create_iv( $bytes, MCRYPT_DEV_URANDOM );
+		if ( $buf !== false ) {
+			return $buf;
+		}
+	}
+
+	// Use /dev/urandom if available
+	// Will cause issues with open_basedir denying access
+	if ( @is_readable( '/dev/urandom' ) ) {
+		$fp = @fopen( '/dev/urandom', 'rb' );
+
+		// Use unbuffered reads if available in PHP 5.3.3+ to avoid read-ahead buffering eating entropy
+		if ( $fp && function_exists( 'stream_set_read_buffer' ) ) {
+			if ( false === stream_set_read_buffer( $fp, 0 ) ) {
+				// We'll skip using /dev/urandom if we can't use an unbuffered file
+				fclose( $fp );
+				unset( $fp );
+			}
+		}
+
+		if ( $fp ) {
+			$buf = '';
+
+			mbstring_binary_safe_encoding();
+
+			// How many bytes do we need?
+			$bytes_remaining = $bytes;
+			do {
+				$buf .= $read = fread( $fp, $bytes_remaining );
+				if ( $read === false ) {
+					// We cannot safely read from /dev/urandom.
+					$buf = false;
+					break;
+				}
+				$bytes_remaining -= strlen( $read );
+			} while( $bytes_remaining > 0 );
+
+			reset_mbstring_encoding();
+
+			fclose( $fp );
+
+			if ( $buf ) {
+				return $buf;
+			}
+		}
+	}
+
+	// Available since PHP 5.3.0
+	// Uses native Windows Cyrpto API's in PHP 5.4+
+	// can be exceedingly slow before PHP 5.3.4 on windows - https://bugs.php.net/bug.php?id=51636
+	$use_openssl = function_exists('openssl_random_pseudo_bytes');
+	$use_openssl = $use_openssl && ! ( 'WIN' == substr( PHP_OS, 0, 3 ) && version_compare( phpversion(), '5.3.4', '<') );
+	if ( $use_openssl ) {
+		$buf = openssl_random_pseudo_bytes( $bytes );
+		if ( $buf !== false ) {
+			return $buf;
+		}
+	}
+
+	// CAPICOM: Supported on 32bit Windows 2008 and older only (includes non-server Windows 7 & XP)
+	// Windows 2008 R2 and newer with .NET 1.0+ should use \DOTNET('mscorlib', 'System.Security.Cryptography.RNGCryptoServiceProvider') if available
+	// Lots of reports of the DOTNET route not working for many under windows throwing fatals / exceptions due to type mismatches
+
+	// UNTESTED, and deprecated in windows.
+	if ( false && class_exists( 'COM', false ) ) {
+		try {
+			$execs = 0;
+		 	$buf = '';
+			$util = new COM( 'CAPICOM.Utilities.1' );
+			if ( ! is_callable( $util, 'GetRandom' ) ) {
+				throw new Exception( '$util->GetRandom not callable' );
+			}
+
+			/*
+		 	 * Let's not let it loop forever. If we run N times and fail to
+		 	 * get N bytes of entropy, then CAPICOM has failed us.
+		 	 */
+		 	mbstring_binary_safe_encoding();
+			while ( $execs++ < $bytes) {
+				$buf .= base64_decode( $util->GetRandom( $bytes, 0 ) );
+				if ( strlen( $buf ) >= $bytes ) {
+					reset_mbstring_encoding();
+					return substr( $buf, 0, $bytes );
+				}
+			}
+			reset_mbstring_encoding();
+		} catch ( Exception $e ) {
+			reset_mbstring_encoding();
+		}
+	}
+	if ( false && class_exists( 'DOTNET', false ) ) {
+		//DOTNET('mscorlib', 'System.Security.Cryptography.RNGCryptoServiceProvider')
+	}
+
+	// At this point, we're forced to fallback to a hash-based random source
+	$buf = '';
+	for ( $i = 0; $i < $bytes; ++$i ) {
+		$buf .= chr( wp_rand( 0, 255 ) );
+	}
+
+	return $buf;
+}
+
+/**
+ * Generate a random positive integer between 0 and PHP_INT_MAX.
+ *
+ * @return int A random positive integer.
+ */
+function wp_random_positive_int() {
+	$buf = wp_random_bytes( PHP_INT_SIZE );
+	
+	$val = 0;
+	$i = strlen( $buf );
+
+	// TODO: Test on a 32bit machine with PHP_INT_SIZE = 4
+	do {
+		$i--;
+		$val <<= 8;
+		$val |= ord( $buf[ $i ] );
+	} while( $i != 0 );
+
+	// effectively absint()
+	return $val & PHP_INT_MAX;
+}
+
+/**
+ * Generates an unbiased, unpredictably random number.
+ *
+ * @since x.x.x
+ *
+ * @param int $min Lower limit for the generated number.
+ * @param int $max Upper limit for the generated number.
+ * @return int A random number between min and max inclusively.
+ */
+function wp_secure_rand( $min = 0, $max = PHP_INT_MAX ) {
+	if ( $min == $max ) {
+		return $min;
+	}
+
+	// Calculate from 0..($max-$min), resulting in $min+$rand..$max
+	$max -= $min;
+
+	// 7776 -> 13
+	$bits = ceil( log( $max + 1 ) / log( 2 ) );
+
+	// 2^13 - 1 == 8191 or 0x00001111 11111111
+	// Calculate a mask of how much of the PHP int we're interested in
+	$mask = ceil( pow( 2, $bits ) ) - 1;
+
+	$val = 0;
+	do {
+		// Grab a random integer
+		$val = wp_random_positive_int();
+
+		// Apply the mask
+		$val &= $mask;
+
+		// Try again if this exceeds our upper limit.
+	} while ( $val > $max );
+
+	// $min..($min+$max)
+	return (int) ( $min + $val );
+}
+
+
 if ( !function_exists('wp_rand') ) :
 /**
  * Generates a random number
  *
  * @since 2.6.2
  *
  * @param int $min Lower limit for the generated number
  * @param int $max Upper limit for the generated number
  * @return int A random number between min and max
  */
 function wp_rand( $min = 0, $max = 0 ) {
 	global $rnd_value;
 
 	// Reset $rnd_value after 14 uses
 	// 32(md5) + 40(sha1) + 40(sha1) / 8 = 14 random numbers from $rnd_value
