Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

simplify base64-related code

  • Loading branch information...
commit 60c340ef5add768fff401e1117801cefd11bb84b 1 parent f25eb4a
@ddebernardy ddebernardy authored nateabele committed
View
53 libraries/lithium/security/Crypto.php
@@ -34,7 +34,6 @@ class Crypto {
* {{{
* $bits = String::random(8); // 64 bits
* $hex = bin2hex($bits); // [0-9a-f]+
- * $salt = Crypto::encode64($bits); // [./0-9A-Za-z]+
* }}}
*
* @param integer $bytes The number of random bytes to generate
@@ -46,47 +45,25 @@ public static function random($bytes) {
}
/**
- * Encodes bytes into an `./0-9A-Za-z` alphabet, for use as salt when
- * hashing passwords for instance.
+ * Generates random bytes encoded into an `./0-9A-Za-z` alphabet, for use
+ * as salt when hashing passwords for instance.
*
- * Note: this is not the same as `base64_encode()` (RFC 1421) which
- * uses an `+/0-9A-Za-z` alphabet.
+ * Note: this is not the same as `base64_encode()`, which encodes bytes
+ * using an `A-Za-z0-9+/` alphabet.
*
- * @param string $input The input bytes.
- * @return string The same bytes in the `./0-9A-Za-z` alphabet.
+ * @param integer $bytes The number of random bytes to generate.
+ * @return string The random bytes encoded in the `./0-9A-Za-z` alphabet.
* @see lithium\security\Crypto::random()
*/
- public static function encode64($input) {
- $base64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
- $i = 0;
-
- $count = strlen($input);
- $output = '';
-
- do {
- $value = ord($input[$i++]);
- $output .= $base64[$value & 0x3f];
-
- if ($i < $count) {
- $value |= ord($input[$i]) << 8;
- }
- $output .= $base64[($value >> 6) & 0x3f];
-
- if ($i++ >= $count) {
- break;
- }
- if ($i < $count) {
- $value |= ord($input[$i]) << 16;
- }
- $output .= $base64[($value >> 12) & 0x3f];
-
- if ($i++ >= $count) {
- break;
- }
- $output .= $base64[($value >> 18) & 0x3f];
- } while ($i < $count);
-
- return $output;
+ public static function random64($bytes) {
+ // The alphabet used by base64_encode() is different than the one we
+ // should be using. When considering the meaty part of the resulting
+ // string, however, a bijection allows to go the from one to another.
+ // Given that we're working on random bytes, we can use safely use
+ // base64_encode() without losing any entropy, sparing ourselves the
+ // hassle of maintaining more code than needed.
+ $base64 = base64_encode(static::random($bytes));
+ return strtr(rtrim($base64, '='), '+', '.');
}
/**
View
63 libraries/lithium/security/Password.php
@@ -16,6 +16,16 @@
*/
class Password extends \lithium\security\Crypto {
/**
+ * The default log2 number of iterations for Blowfish encryption
+ */
+ const BF = 10;
+
+ /**
+ * The default log2 number of iterations for XDES encryption
+ */
+ const XDES = 18;
+
+ /**
* Hashes a password using PHP's `crypt()` and an optional salt. If no
* salt is supplied, a cryptographically strong salt will be generated
* using `lithium\security\Password::genSalt()`.
@@ -109,8 +119,8 @@ public static function check($password, $hash) {
* Note2: this method should not be use to generate custom salts. Indeed,
* the resulting salts are prefixed with information expected by PHP's
* `crypt()`. To get an arbitrarily long, cryptographically strong salt
- * consisting in random sequences of alpha numeric characters, use
- * `lithium\security\Crypto::random()` instead.
+ * consisting in random bits encoded as alpha numeric characters, use
+ * `lithium\security\Crypto::random64()` instead.
*
* @param string $type The hash type. Optional. Defaults to the best
* available option. Supported values, along with their maximum
@@ -127,7 +137,7 @@ public static function check($password, $hash) {
* @link http://www.postgresql.org/docs/9.0/static/pgcrypto.html
* @see lithium\security\Password::hash()
* @see lithium\security\Password::check()
- * @see lithium\security\Crypto::random()
+ * @see lithium\security\Crypto::random64()
*/
public static function genSalt($type = null, $count = null) {
switch (true) {
@@ -147,43 +157,16 @@ public static function genSalt($type = null, $count = null) {
* Defaults to `10`. Can be `4` to `31`.
* @return string The Blowfish salt
*/
- protected static function _genSaltBf($count = 10) {
+ protected static function _genSaltBf($count = static::BF) {
$count = (integer) $count;
if ($count < 4 || $count > 31)
- $count = 10;
-
- // We don't use the encode64() method here because it could result
- // in 2 bits less of entropy depending on the last char.
- $base64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
- $i = 0;
-
- $input = static::random(16); // 128 bits of salt
- $output = '';
-
- do {
- $c1 = ord($input[$i++]);
- $output .= $base64[$c1 >> 2];
- $c1 = ($c1 & 0x03) << 4;
- if ($i >= 16) {
- $output .= $base64[$c1];
- break;
- }
-
- $c2 = ord($input[$i++]);
- $c1 |= $c2 >> 4;
- $output .= $base64[$c1];
- $c1 = ($c2 & 0x0f) << 2;
-
- $c2 = ord($input[$i++]);
- $c1 |= $c2 >> 6;
- $output .= $base64[$c1];
- $output .= $base64[$c2 & 0x3f];
- } while (1);
+ $count = static::BF;
return '$2a$'
- // zeroize $count
+ // zeroize iterations
. chr(ord('0') + $count / 10) . chr(ord('0') + $count % 10)
- . '$' . $output;
+ // 128 bits of salt
+ . '$' . static::random64(16);
}
/**
@@ -195,10 +178,10 @@ protected static function _genSaltBf($count = 10) {
* use a weak DES key.
* @return string The XDES salt.
*/
- protected static function _genSaltXDES($count = 18) {
+ protected static function _genSaltXDES($count = static::XDES) {
$count = (integer) $count;
if ($count < 1 || $count > 24)
- $count = 16;
+ $count = static::XDES;
// Count should be odd to not reveal weak DES keys
$count = (1 << $count) - 1;
@@ -206,13 +189,13 @@ protected static function _genSaltXDES($count = 18) {
$base64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$output = '_'
- // iterations
+ // encode iterations
. $base64[$count & 0x3f]
. $base64[($count >> 6) & 0x3f]
. $base64[($count >> 12) & 0x3f]
. $base64[($count >> 18) & 0x3f]
// 24 bits of salt
- . static::encode64(static::random(3));
+ . static::random64(3);
return $output;
}
@@ -225,7 +208,7 @@ protected static function _genSaltXDES($count = 18) {
protected static function _genSaltMD5() {
$output = '$1$'
// 48 bits of salt
- . static::encode64(static::random(6));
+ . static::random64(6);
return $output;
}
}
View
20 libraries/lithium/tests/cases/security/CryptoTest.php
@@ -18,11 +18,25 @@ class CryptoTest extends \lithium\test\Unit {
**/
public function testRandomGenerator() {
$check = array();
- $count = 50;
- $pattern = "/^[0-9A-Za-z\.\/]+$/";
+ $count = 25;
for ($i = 0; $i < $count; $i++) {
$result = Crypto::random(8);
- $this->assertPattern($pattern, Crypto::encode64($result));
+ $this->assertFalse(in_array($result, $check));
+ $check[] = $result;
+ }
+ }
+ /**
+ * testRandomGenerator method
+ *
+ * @return void
+ **/
+ public function testRandom64Generator() {
+ $check = array();
+ $count = 25;
+ $pattern = "/^[0-9A-Za-z\.\/]{11}$/";
+ for ($i = 0; $i < $count; $i++) {
+ $result = Crypto::random64(8);
+ $this->assertPattern($pattern, $result);
$this->assertFalse(in_array($result, $check));
$check[] = $result;
}
Please sign in to comment.
Something went wrong with that request. Please try again.