mirror of
https://github.com/sbrl/Pepperminty-Wiki.git
synced 2024-11-22 04:23:01 +00:00
Bugfix: Fix inadvertent cost-climbing when recalculating the password hashing cost
This commit is contained in:
parent
1a11c84e1d
commit
57ec8b82b5
5 changed files with 47 additions and 14 deletions
|
@ -1,6 +1,11 @@
|
|||
# Changelog
|
||||
This file holds the changelog for Pepperminty Wiki. This is the master list of things that have changed (second only to the commit history!) - though the information for any particular release can also be found in the description of it's page for every release made on GitHub too.
|
||||
|
||||
## v0.17-beta2
|
||||
|
||||
### Fixed
|
||||
- Fixed the cost-climbing bug in the last beta release
|
||||
|
||||
## v0.17-beta1
|
||||
|
||||
### Added
|
||||
|
|
|
@ -59,7 +59,7 @@ $guiConfig = <<<'GUICONFIG'
|
|||
"user_preferences_button_text": { "type": "text", "description": "The text to display on the button that lets logged in users change their settings. Defaults to a cog (aka a 'gear' in unicode-land).", "default": "⚙ " },
|
||||
"password_algorithm": { "type": "text", "description": "The algorithm to utilise when hashing passwords. Takes any value PHP's password_hash() does.", "default": "PASSWORD_DEFAULT" },
|
||||
"password_cost": { "type": "number", "description": "The cost to use when hashing passwords.", "default": 12},
|
||||
"password_cost_time": { "type": "number", "description": "The desired number of milliseconds to delay by when hashing passwords. Pepperminty Wiki will automatically update the value of password_cost to take the length of time specified here. If you're using PASSWORD_ARGON2I, then the auto-update will be disabled.", "default": 100},
|
||||
"password_cost_time": { "type": "number", "description": "The desired number of milliseconds to delay by when hashing passwords. Pepperminty Wiki will automatically update the value of password_cost to take the length of time specified here. If you're using PASSWORD_ARGON2I, then the auto-update will be disabled.", "default": 350},
|
||||
"password_cost_time_interval": { "type": "number", "description": "The interval, in seconds, at which the password cost should be recalculated. Set to -1 to disable. Default: 1 week", "default": 604800},
|
||||
"password_cost_time_lastcheck": { "type": "number", "description": "Pseudo-setting used to keep track of the last recalculation of password_cost. Is updated with the current unix timestamp every time password_cost is recalculated.", "default": 0},
|
||||
"new_password_length": { "type": "number", "description": "The length of newly-generated passwords. This is currently used in the user table when creating new accounts.", "default": 32},
|
||||
|
@ -407,7 +407,7 @@ if($settings->sessionprefix == "auto")
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
/** The version of Pepperminty Wiki currently running. */
|
||||
$version = "v0.17-beta1";
|
||||
$commit = "a45a3aa087752b4f26af0a02785efc8b08436ce2";
|
||||
$commit = "1a11c84e1dd0104e1cc9dc44eaaa737982165f4c";
|
||||
/// Environment ///
|
||||
/** Holds information about the current request environment. */
|
||||
$env = new stdClass();
|
||||
|
@ -8016,6 +8016,22 @@ register_module([
|
|||
}
|
||||
});
|
||||
|
||||
add_action("hash-cost-test", function() {
|
||||
header("content-type: text/plain");
|
||||
|
||||
$time_compute = microtime(true);
|
||||
$cost = hash_password_compute_cost();
|
||||
$time_compute = (microtime(true) - $time_compute)*1000;
|
||||
|
||||
$time_cost = microtime(true);
|
||||
password_hash("testing", PASSWORD_DEFAULT, [ "cost" => $cost ]);
|
||||
$time_cost = (microtime(true) - $time_cost)*1000;
|
||||
|
||||
echo("Calculated cost: $cost ({$time_cost}ms)\n");
|
||||
echo("Time taken: {$time_compute}ms\n");
|
||||
exit(date("r"));
|
||||
});
|
||||
|
||||
// Register a section on logging in on the help page.
|
||||
add_help_section("30-login", "Logging in", "<p>In order to edit $settings->sitename and have your edit attributed to you, you need to be logged in. Depending on the settings, logging in may be a required step if you want to edit at all. Thankfully, loggging in is not hard. Simply click the "Login" link in the top left, type your username and password, and then click login.</p>
|
||||
<p>If you do not have an account yet and would like one, try contacting <a href='mailto:" . hide_email($settings->admindetails_email) . "'>$settings->admindetails_name</a>, $settings->sitename's administrator and ask them nicely to see if they can create you an account.</p>");
|
||||
|
@ -8121,23 +8137,21 @@ function hash_password_compute_cost() {
|
|||
$props = hash_password_properties();
|
||||
if($props["algorithm"] == PASSWORD_ARGON2I)
|
||||
return null;
|
||||
if(!is_int($props["options"]["cost"]))
|
||||
$props["options"]["cost"] = 10;
|
||||
|
||||
$target_cost_time = $settings->password_cost_time / 1000; // The setting is in ms
|
||||
|
||||
$start = microtime(true);
|
||||
do {
|
||||
$props["options"]["cost"]++;
|
||||
$start_i = microtime(true);
|
||||
password_hash("testing", $props["algorithm"], $props["options"]);
|
||||
$end_i = microtime(true);
|
||||
echo("Attempt | cost = {$props["options"]["cost"]}, time = " . ($end_i - $start_i)*1000 . "ms\n");
|
||||
// Iterate until we find a cost high enough
|
||||
// ....but don't keep going forever - try for at most 10x the target
|
||||
// time in total (in case the specified algorithm doesn't take a
|
||||
// cost parameter)
|
||||
} while($end_i - $start_i < $target_cost_time &&
|
||||
$end_i - $start < $target_cost_time * 10);
|
||||
} while($end_i - $start_i < $target_cost_time);
|
||||
|
||||
return $props["options"]["cost"];
|
||||
}
|
||||
|
|
|
@ -212,7 +212,7 @@
|
|||
"author": "Starbeamrainbowlabs",
|
||||
"description": "Adds a pair of actions (login and checklogin) that allow users to login. You need this one if you want your users to be able to login.",
|
||||
"id": "page-login",
|
||||
"lastupdate": 1527246396,
|
||||
"lastupdate": 1538314946,
|
||||
"optional": false
|
||||
},
|
||||
{
|
||||
|
|
|
@ -150,6 +150,22 @@ register_module([
|
|||
}
|
||||
});
|
||||
|
||||
add_action("hash-cost-test", function() {
|
||||
header("content-type: text/plain");
|
||||
|
||||
$time_compute = microtime(true);
|
||||
$cost = hash_password_compute_cost();
|
||||
$time_compute = (microtime(true) - $time_compute)*1000;
|
||||
|
||||
$time_cost = microtime(true);
|
||||
password_hash("testing", PASSWORD_DEFAULT, [ "cost" => $cost ]);
|
||||
$time_cost = (microtime(true) - $time_cost)*1000;
|
||||
|
||||
echo("Calculated cost: $cost ({$time_cost}ms)\n");
|
||||
echo("Time taken: {$time_compute}ms\n");
|
||||
exit(date("r"));
|
||||
});
|
||||
|
||||
// Register a section on logging in on the help page.
|
||||
add_help_section("30-login", "Logging in", "<p>In order to edit $settings->sitename and have your edit attributed to you, you need to be logged in. Depending on the settings, logging in may be a required step if you want to edit at all. Thankfully, loggging in is not hard. Simply click the "Login" link in the top left, type your username and password, and then click login.</p>
|
||||
<p>If you do not have an account yet and would like one, try contacting <a href='mailto:" . hide_email($settings->admindetails_email) . "'>$settings->admindetails_name</a>, $settings->sitename's administrator and ask them nicely to see if they can create you an account.</p>");
|
||||
|
@ -255,23 +271,21 @@ function hash_password_compute_cost() {
|
|||
$props = hash_password_properties();
|
||||
if($props["algorithm"] == PASSWORD_ARGON2I)
|
||||
return null;
|
||||
if(!is_int($props["options"]["cost"]))
|
||||
$props["options"]["cost"] = 10;
|
||||
|
||||
$target_cost_time = $settings->password_cost_time / 1000; // The setting is in ms
|
||||
|
||||
$start = microtime(true);
|
||||
do {
|
||||
$props["options"]["cost"]++;
|
||||
$start_i = microtime(true);
|
||||
password_hash("testing", $props["algorithm"], $props["options"]);
|
||||
$end_i = microtime(true);
|
||||
echo("Attempt | cost = {$props["options"]["cost"]}, time = " . ($end_i - $start_i)*1000 . "ms\n");
|
||||
// Iterate until we find a cost high enough
|
||||
// ....but don't keep going forever - try for at most 10x the target
|
||||
// time in total (in case the specified algorithm doesn't take a
|
||||
// cost parameter)
|
||||
} while($end_i - $start_i < $target_cost_time &&
|
||||
$end_i - $start < $target_cost_time * 10);
|
||||
} while($end_i - $start_i < $target_cost_time);
|
||||
|
||||
return $props["options"]["cost"];
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
"user_preferences_button_text": { "type": "text", "description": "The text to display on the button that lets logged in users change their settings. Defaults to a cog (aka a 'gear' in unicode-land).", "default": "⚙ " },
|
||||
"password_algorithm": { "type": "text", "description": "The algorithm to utilise when hashing passwords. Takes any value PHP's password_hash() does.", "default": "PASSWORD_DEFAULT" },
|
||||
"password_cost": { "type": "number", "description": "The cost to use when hashing passwords.", "default": 12},
|
||||
"password_cost_time": { "type": "number", "description": "The desired number of milliseconds to delay by when hashing passwords. Pepperminty Wiki will automatically update the value of password_cost to take the length of time specified here. If you're using PASSWORD_ARGON2I, then the auto-update will be disabled.", "default": 100},
|
||||
"password_cost_time": { "type": "number", "description": "The desired number of milliseconds to delay by when hashing passwords. Pepperminty Wiki will automatically update the value of password_cost to take the length of time specified here. If you're using PASSWORD_ARGON2I, then the auto-update will be disabled.", "default": 350},
|
||||
"password_cost_time_interval": { "type": "number", "description": "The interval, in seconds, at which the password cost should be recalculated. Set to -1 to disable. Default: 1 week", "default": 604800},
|
||||
"password_cost_time_lastcheck": { "type": "number", "description": "Pseudo-setting used to keep track of the last recalculation of password_cost. Is updated with the current unix timestamp every time password_cost is recalculated.", "default": 0},
|
||||
"new_password_length": { "type": "number", "description": "The length of newly-generated passwords. This is currently used in the user table when creating new accounts.", "default": 32},
|
||||
|
|
Loading…
Reference in a new issue