Skip to content

Commit

Permalink
Add parseConfig() method to hash modules
Browse files Browse the repository at this point in the history
  • Loading branch information
rchouinard committed Jul 21, 2012
1 parent d2b4910 commit ced2e68
Show file tree
Hide file tree
Showing 19 changed files with 353 additions and 5 deletions.
8 changes: 8 additions & 0 deletions src/PHPassLib/Hash.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ interface Hash
*/
public static function genConfig(array $config = array ());

/**
* Parse a config string and extract the options used to build it.
*
* @param string $config Configuration string.
* @return array Options array or false on failure.
*/
public static function parseConfig($config);

/**
* Generate a hash using a pre-defined config string.
*
Expand Down
21 changes: 21 additions & 0 deletions src/PHPassLib/Hash/BCrypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,27 @@ public static function genConfig(array $config = array ())
}
}

/**
* Parse a config string and extract the options used to build it.
*
* @param string $config Configuration string.
* @return array Options array or false on failure.
*/
public static function parseConfig($config)
{
$options = false;
$matches = array ();
if (preg_match('/^\$(2a|2y|2x)\$(\d{2})\$([\.\/0-9A-Za-z]{22})/', $config, $matches)) {
$options = array (
'ident' => $matches[1],
'rounds' => (int) $matches[2],
'salt' => $matches[3],
);
}

return $options;
}

/**
* Generate a hash using a pre-defined config string.
*
Expand Down
24 changes: 22 additions & 2 deletions src/PHPassLib/Hash/BSDiCrypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public static function genConfig(array $config = array ())
$string = '*1';
try {
self::validateOptions($config);
// Rounds needs to be odd in order to avoid exposing wek DES keys
// Rounds needs to be odd in order to avoid exposing weak DES keys
if (($config['rounds'] % 2) == 0) {
--$config['rounds'];
}
Expand All @@ -73,6 +73,26 @@ public static function genConfig(array $config = array ())
return $string;
}

/**
* Parse a config string and extract the options used to build it.
*
* @param string $config Configuration string.
* @return array Options array or false on failure.
*/
public static function parseConfig($config)
{
$options = false;
$matches = array ();
if (preg_match('/^_([\.\/0-9A-Za-z]{4})([\.\/0-9A-Za-z]{4})/', $config, $matches)) {
$options = array (
'rounds' => (int) Utilities::decodeInt24($matches[1]),
'salt' => $matches[2],
);
}

return $options;
}

/**
* Generate a hash using a pre-defined config string.
*
Expand Down Expand Up @@ -136,7 +156,7 @@ protected static function validateOptions(array $options)
foreach ($options as $option => $value) switch ($option) {

case 'rounds':
if ($value < 0 || $value > 0xffffff) {
if ($value < 1 || $value > 0xffffff) {
throw new InvalidArgumentException('Rounds must be in the range 1 - 16777215.');
}
break;
Expand Down
19 changes: 19 additions & 0 deletions src/PHPassLib/Hash/DESCrypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,25 @@ public static function genConfig(array $config = array ())
return $string;
}

/**
* Parse a config string and extract the options used to build it.
*
* @param string $config Configuration string.
* @return array Options array or false on failure.
*/
public static function parseConfig($config)
{
$options = false;
$matches = array ();
if (preg_match('/^([\.\/0-9A-Za-z]{2})/', $config, $matches)) {
$options = array (
'salt' => $matches[1],
);
}

return $options;
}

/**
* Generate a hash using a pre-defined config string.
*
Expand Down
21 changes: 20 additions & 1 deletion src/PHPassLib/Hash/MD5Crypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,33 @@ public static function genConfig(array $config = array ())
$string = '*1';
try {
self::validateOptions($config);
$string = sprintf('$1$%s$', $config['salt']);
$string = sprintf('$1$%s', $config['salt']);
} catch (InvalidArgumentException $e) {
trigger_error($e->getMessage(), E_USER_WARNING);
}

return $string;
}

/**
* Parse a config string and extract the options used to build it.
*
* @param string $config Configuration string.
* @return array Options array or false on failure.
*/
public static function parseConfig($config)
{
$options = false;
$matches = array ();
if (preg_match('/^\$1\$([\.\/0-9A-Za-z]{0,8})\$?/', $config, $matches)) {
$options = array (
'salt' => $matches[1],
);
}

return $options;
}

/**
* Generate a hash using a pre-defined config string.
*
Expand Down
26 changes: 24 additions & 2 deletions src/PHPassLib/Hash/PBKDF2.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public static function genConfig(array $config = array ())
// pbkdf2-sha1 doesn't include the digest in the hash identifier
// We also have to treat the rounds parameter as a float, otherwise
// values above 2147483647 will wrap on 32-bit systems.
$string = str_replace('-sha1', '', sprintf('$pbkdf2-%s$%0.0f$%s$', $config['digest'], $config['rounds'], $config['salt']));
$string = str_replace('-sha1', '', sprintf('$pbkdf2-%s$%0.0f$%s', $config['digest'], $config['rounds'], $config['salt']));
} catch (InvalidArgumentException $e) {
trigger_error($e->getMessage(), E_USER_WARNING);
} catch (RuntimeException $e) {
Expand All @@ -91,6 +91,28 @@ public static function genConfig(array $config = array ())
return $string;
}

/**
* Parse a config string and extract the options used to build it.
*
* @param string $config Configuration string.
* @return array Options array or false on failure.
*/
public static function parseConfig($config)
{
$options = false;
$matches = array ();
if (preg_match('/^\$pbkdf2-?(sha256|sha512)?\$(\d+)\$([\.\/0-9A-Za-z]{0,1366})\$?/', $config, $matches)) {
$options = array (
'digest' => $matches[1] ?: 'sha1',
'rounds' => $matches[2],
'salt' => $matches[3],
'saltSize' => $matches[3] ? strlen(Utilities::altBase64Decode($matches[3])) : 0,
);
}

return $options;
}

/**
* Generate a hash using a pre-defined config string.
*
Expand Down Expand Up @@ -140,7 +162,7 @@ public static function genHash($password, $config)

// Calculate the checksum and encode the hash string
$checksum = self::hashPbkdf2($password, Utilities::altBase64Decode($config['salt']), $config['rounds'], $keysize, $config['digest']);
$hash = self::genConfig($config) . Utilities::altBase64Encode($checksum);
$hash = self::genConfig($config) . '$' . Utilities::altBase64Encode($checksum);

return $hash;
}
Expand Down
21 changes: 21 additions & 0 deletions src/PHPassLib/Hash/Portable.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,27 @@ public static function genConfig(array $config = array ())
return $string;
}

/**
* Parse a config string and extract the options used to build it.
*
* @param string $config Configuration string.
* @return array Options array or false on failure.
*/
public static function parseConfig($config)
{
$options = false;
$matches = array ();
if (preg_match('/^\$(P|H)\$([5-9A-S]{1})([\.\/0-9A-Za-z]{8})/', $config, $matches)) {
$options = array (
'ident' => $matches[1],
'rounds' => strpos(Utilities::CHARS_H64, $config[3]),
'salt' => $matches[3],
);
}

return $options;
}

/**
* Generate a hash using a pre-defined config string.
*
Expand Down
20 changes: 20 additions & 0 deletions src/PHPassLib/Hash/SHA1Crypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,26 @@ public static function genConfig(array $config = array ())
return $string;
}

/**
* Parse a config string and extract the options used to build it.
*
* @param string $config Configuration string.
* @return array Options array or false on failure.
*/
public static function parseConfig($config)
{
$options = false;
$matches = array ();
if (preg_match('/^\$sha1\$(\d+)\$([\.\/0-9A-Za-z]{0,64})\$?/', $config, $matches)) {
$options = array (
'rounds' => (int) $matches[1],
'salt' => $matches[2],
);
}

return $options;
}

/**
* Generate a hash using a pre-defined config string.
*
Expand Down
25 changes: 25 additions & 0 deletions src/PHPassLib/Hash/SHA256Crypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,31 @@ public static function genConfig(array $config = array ())
return $string;
}

/**
* Parse a config string and extract the options used to build it.
*
* @param string $config Configuration string.
* @return array Options array or false on failure.
*/
public static function parseConfig($config)
{
// Cheat because regex is hard :-)
if (strpos($config, 'rounds=') === false) {
$config = str_replace('$5$', '$5$rounds=5000$', $config);
}

$options = false;
$matches = array ();
if (preg_match('/^\$5\$rounds=(\d{4,9})\$([\.\/0-9A-Za-z]{0,16})\$?/', $config, $matches)) {
$options = array (
'rounds' => (int) $matches[1],
'salt' => $matches[2],
);
}

return $options;
}

/**
* Generate a hash using a pre-defined config string.
*
Expand Down
25 changes: 25 additions & 0 deletions src/PHPassLib/Hash/SHA512Crypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,31 @@ public static function genConfig(array $config = array ())
return $string;
}

/**
* Parse a config string and extract the options used to build it.
*
* @param string $config Configuration string.
* @return array Options array or false on failure.
*/
public static function parseConfig($config)
{
// Cheat because regex is hard :-)
if (strpos($config, 'rounds=') === false) {
$config = str_replace('$5$', '$5$rounds=5000$', $config);
}

$options = false;
$matches = array ();
if (preg_match('/^\$6\$rounds=(\d{4,9})\$([\.\/0-9A-Za-z]{0,16})\$?/', $config, $matches)) {
$options = array (
'rounds' => (int) $matches[1],
'salt' => $matches[2],
);
}

return $options;
}

/**
* Generate a hash using a pre-defined config string.
*
Expand Down
16 changes: 16 additions & 0 deletions tests/PHPassLib/Test/Hash/BCryptTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,20 @@ public function invalidTestVectorsProduceExpectedResults($password, $hash, $erro
$this->assertFalse(BCrypt::verify($password, $hash));
}

/**
* @test
*/
public function genconfigAndParseconfigProduceMatchingResults()
{
$options = array (
'ident' => '2x',
'rounds' => 8,
'salt' => 'CCCCCCCCCCCCCCCCCCCCC.',
);
$config = BCrypt::genConfig($options);

$this->assertEquals('$2x$08$CCCCCCCCCCCCCCCCCCCCC.', $config);
$this->assertSame($options, BCrypt::parseConfig($config));
}

}
26 changes: 26 additions & 0 deletions tests/PHPassLib/Test/Hash/BSDiCryptTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,30 @@ public function invalidTestVectorsProduceExpectedResults($password, $hash, $erro
$this->assertFalse(BSDiCrypt::verify($password, $hash));
}

/**
* @test
*/
public function genconfigAndParseconfigProduceMatchingResults()
{
$options = array (
'rounds' => 5001,
'salt' => 'CCC.',
);
$config = BSDiCrypt::genConfig($options);

$this->assertEquals('_7C/.CCC.', $config);
$this->assertSame($options, BSDiCrypt::parseConfig($config));

$options = array (
'rounds' => 5000,
'salt' => 'CCC.',
);
$config = BSDiCrypt::genConfig($options);
$options['rounds'] = 4999; // Module subtracts 1 from even rounds
// when generating the config string.

$this->assertEquals('_5C/.CCC.', $config, $config);
$this->assertSame($options, BSDiCrypt::parseConfig($config));
}

}
14 changes: 14 additions & 0 deletions tests/PHPassLib/Test/Hash/DESCryptTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,18 @@ public function invalidTestVectorsProduceExpectedResults($password, $hash, $erro
$this->assertFalse(DESCrypt::verify($password, $hash));
}

/**
* @test
*/
public function genconfigAndParseconfigProduceMatchingResults()
{
$options = array (
'salt' => 'C.',
);
$config = DESCrypt::genConfig($options);

$this->assertEquals('C.', $config);
$this->assertSame($options, DESCrypt::parseConfig($config));
}

}
Loading

0 comments on commit ced2e68

Please sign in to comment.