• Like
  • Save
Password Hashing: The Right Way
Upcoming SlideShare
Loading in...5
×
 

Password Hashing: The Right Way

on

  • 1,198 views

Introduces the new PHP password hashing functions and Password Validator library.

Introduces the new PHP password hashing functions and Password Validator library.

Statistics

Views

Total Views
1,198
Views on SlideShare
1,198
Embed Views
0

Actions

Likes
1
Downloads
8
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Password Hashing: The Right Way Password Hashing: The Right Way Presentation Transcript

    • Password Hashing: The Right Way Jeremy Kendall - Memphis PHP January 28, 2014 Wednesday, January 29, 14
    • Wednesday, January 29, 14
    • I love to code Wednesday, January 29, 14
    • I love to code I’m terribly forgetful Wednesday, January 29, 14
    • I love to code I’m terribly forgetful I take pictures Wednesday, January 29, 14
    • I love to code I’m terribly forgetful I take pictures I work at OpenSky Wednesday, January 29, 14
    • I’m a Little Off My Game Wednesday, January 29, 14
    • What Qualifies Me To Talk About Security? Wednesday, January 29, 14
    • Not Much Wednesday, January 29, 14
    • Not Much But that will work in our favor ... Wednesday, January 29, 14
    • Cryptography is Hard Wednesday, January 29, 14
    • Cryptography is Hard Pro Tip: Leave it to the experts Wednesday, January 29, 14
    • The Wrong Way <?php class SecurityFail { // Encrypt Passwords for Highest Level of Security. static public function encrypt($pword) { return md5($pword); } } http://csiphp.com/blog/2012/02/16/encrypt-passwords-for-highest-level-of-security/ Wednesday, January 29, 14
    • The Right Way http://php.net/manual/en/ref.password.php Wednesday, January 29, 14
    • The Awesomer Way Wednesday, January 29, 14
    • Password Hashing Functions Wednesday, January 29, 14
    • Password Hashing Functions Pro Tip: Use password_compat for PHP 5.3.7+ Wednesday, January 29, 14
    • Password Hashing Functions Pro Tip: Use password_compat for PHP 5.3.7+ Pro Tip: Use phpass for PHP <= 5.3.6 Wednesday, January 29, 14
    • password_hash http://www.php.net/manual/en/function.password-hash.php Wednesday, January 29, 14
    • password_hash ‣ Creates a new password hash http://www.php.net/manual/en/function.password-hash.php Wednesday, January 29, 14
    • password_hash ‣ Strong, one-way hashing algorithm ‣ Creates a new password hash http://www.php.net/manual/en/function.password-hash.php Wednesday, January 29, 14
    • password_hash ‣ Strong, one-way hashing algorithm ‣ Creates a new password hash ‣ PASSWORD_DEFAULT or PASSWORD_BCRYPT http://www.php.net/manual/en/function.password-hash.php Wednesday, January 29, 14
    • password_hash ‣ Strong, one-way hashing algorithm ‣ Creates a new password hash ‣ ‣ PASSWORD_DEFAULT or PASSWORD_BCRYPT Optional cost and salt http://www.php.net/manual/en/function.password-hash.php Wednesday, January 29, 14
    • password_hash http://www.php.net/manual/en/function.password-hash.php Wednesday, January 29, 14
    • password_hash ‣ Always use PASSWORD_DEFAULT http://www.php.net/manual/en/function.password-hash.php Wednesday, January 29, 14
    • password_hash ‣ Your DB’s password field should be varchar(255) ‣ Always use PASSWORD_DEFAULT http://www.php.net/manual/en/function.password-hash.php Wednesday, January 29, 14
    • password_hash ‣ Your DB’s password field should be varchar(255) ‣ Do not use your own salt ‣ Always use PASSWORD_DEFAULT http://www.php.net/manual/en/function.password-hash.php Wednesday, January 29, 14
    • password_hash ‣ Your DB’s password field should be varchar(255) ‣ Do not use your own salt ‣ Check for an appropriate cost using the example script ‣ in the manual Always use PASSWORD_DEFAULT http://www.php.net/manual/en/function.password-hash.php Wednesday, January 29, 14
    • password_hash $hash = password_hash('secret pass', PASSWORD_DEFAULT); // or $options = array('cost' => 12); $hash = password_hash('secret pass', PASSWORD_DEFAULT, $options); Wednesday, January 29, 14
    • password_verify Wednesday, January 29, 14
    • password_verify ‣ Wednesday, January 29, 14 Verifies that a password matches a hash
    • password_verify ‣ Uh, yeah, that’s about it ‣ Verifies that a password matches a hash Wednesday, January 29, 14
    • password_verify $valid = password_verify($_POST['pass'], $hashFromDb); Wednesday, January 29, 14
    • password_needs_rehash Wednesday, January 29, 14
    • password_needs_rehash ‣ Wednesday, January 29, 14 Checks password to see if it needs to be updated
    • password_needs_rehash ‣ Uses both hash and cost to check current hash ‣ Checks password to see if it needs to be updated Wednesday, January 29, 14
    • password_needs_rehash $needsRehash = password_needs_rehash($hashFromDb, PASSWORD_DEFAULT); // or $options = array('cost' => 12); $needsRehash = password_needs_rehash($hashFromDb, PASSWORD_DEFAULT, $options); Wednesday, January 29, 14
    • That’s Awesome and Secure Wednesday, January 29, 14
    • But Could It Be Awesomer, Securer, and Easier? Wednesday, January 29, 14
    • Password Validator Wednesday, January 29, 14
    • Password Validator ‣ Wednesday, January 29, 14 Validates passwords against password_hash
    • Password Validator ‣ Will rehash when needed ‣ Validates passwords against password_hash Wednesday, January 29, 14
    • Password Validator ‣ Will rehash when needed ‣ Will upgrade legacy passwords ‣ Validates passwords against password_hash Wednesday, January 29, 14
    • Password Validator ‣ Will rehash when needed ‣ Will upgrade legacy passwords ‣ Requires PHP 5.3.7+ ‣ Validates passwords against password_hash Wednesday, January 29, 14
    • Password Validator ‣ Will rehash when needed ‣ Will upgrade legacy passwords ‣ Requires PHP 5.3.7+ ‣ (No version for <=5.3.6 is in the works) ‣ Validates passwords against password_hash Wednesday, January 29, 14
    • Password Validator use JeremyKendallPasswordPasswordValidator; use JeremyKendallPasswordResult as ValidationResult; $passwordHash = password_hash('password', PASSWORD_DEFAULT); $validator = new PasswordValidator(); $result = $validator->isValid('password', $passwordHash); $valid = $result->isValid(); $code = $result->getCode(); // $valid = true // $code = ValidationResult::SUCCESS Wednesday, January 29, 14
    • Password Validator use JeremyKendallPasswordPasswordValidator; use JeremyKendallPasswordResult as ValidationResult; $options = array('cost' => 9); $passwordHash = password_hash('password', PASSWORD_DEFAULT, $options); $validator = new PasswordValidator(); $validator->setOptions($options); $result = $validator->isValid('password', $passwordHash); $valid = $result->isValid(); $code = $result->getCode(); // $valid = true // $code = ValidationResult::SUCCESS Wednesday, January 29, 14
    • Password Validator use JeremyKendallPasswordPasswordValidator; use JeremyKendallPasswordResult as ValidationResult; $options = array('cost' => 9); $passwordHash = password_hash('password', PASSWORD_DEFAULT, $options); $validator = new PasswordValidator(); // Remember, default cost is 10, so a cost 9 hash gets rehashed $result = $validator->isValid('password', $passwordHash); $valid = $result->isValid(); $code = $result->getCode(); $hash = $result->getPassword(); // $valid = true // $code = ValidationResult::SUCCESS_PASSWORD_REHASHED // $hash = the new, rehashed password. Save it! Wednesday, January 29, 14
    • Fine, But We’re Not Using password_hash Yet ... Wednesday, January 29, 14
    • Decorator Pattern http://en.wikipedia.org/wiki/Decorator_pattern Wednesday, January 29, 14
    • Decorator Pattern ‣ Wrap an object http://en.wikipedia.org/wiki/Decorator_pattern Wednesday, January 29, 14
    • Decorator Pattern ‣ Change its behavior ‣ Wrap an object http://en.wikipedia.org/wiki/Decorator_pattern Wednesday, January 29, 14
    • Decorator Pattern ‣ Change its behavior ‣ Dynamically attach additional responsibilities ‣ Wrap an object http://en.wikipedia.org/wiki/Decorator_pattern Wednesday, January 29, 14
    • PasswordValidatorInterface interface PasswordValidatorInterface { public function isValid($password, $passwordHash, $identity = null); public function rehash($password); public function setOptions(array $options); public function getOptions(); } Wednesday, January 29, 14
    • Upgrade Decorator Wednesday, January 29, 14
    • Upgrade Decorator ‣ Wednesday, January 29, 14 Used when you’re not already using password_hash ...
    • Upgrade Decorator ‣ ... but you’re ready to do things the right way ‣ Used when you’re not already using password_hash ... Wednesday, January 29, 14
    • Upgrade Decorator ‣ ... but you’re ready to do things the right way ‣ Accepts an instance of PasswordValidatorInterface ... ‣ Used when you’re not already using password_hash ... Wednesday, January 29, 14
    • Upgrade Decorator ‣ ... but you’re ready to do things the right way ‣ Accepts an instance of PasswordValidatorInterface ... ‣ ... and a validation callback ‣ Used when you’re not already using password_hash ... Wednesday, January 29, 14
    • Upgrade Decorator // Somewhere in your authentication script if (hash('sha512', $password) === $passwordHash) { $valid = true; } $valid = false; Wednesday, January 29, 14
    • Upgrade Decorator // Same authentication check expressed as a callback $validationCallback = function ($password, $passwordHash) { if (hash('sha512', $password) === $passwordHash) { return true; } return false; }; Wednesday, January 29, 14
    • Upgrade Decorator $validator = new UpgradeDecorator( new PasswordValidator(), $validationCallback ); $passwordHash = hash('sha512', 'password'); $result = $validator->isValid('password', $passwordHash); $valid = $result->isValid(); $code = $result->getCode(); $hash = $result->getPassword(); // $valid = true // $code = ValidationResult::SUCCESS_PASSWORD_REHASHED // $hash = the new, rehashed password. Save it! Wednesday, January 29, 14
    • Fine, But Now I Have to Test for SUCCESS_PASSWORD_REHASHED Every Time Wednesday, January 29, 14
    • Storage Decorator Wednesday, January 29, 14
    • Storage Decorator ‣ Wednesday, January 29, 14 Automatically stores all rehashed passwords
    • Storage Decorator ‣ Accepts two constructor args: ‣ Automatically stores all rehashed passwords Wednesday, January 29, 14
    • Storage Decorator ‣ Accepts two constructor args: ‣ Instance of PasswordValidatorInterface ‣ Automatically stores all rehashed passwords Wednesday, January 29, 14
    • Storage Decorator ‣ Accepts two constructor args: ‣ Instance of PasswordValidatorInterface ‣ Instance of StorageInterface ‣ Automatically stores all rehashed passwords Wednesday, January 29, 14
    • StorageInterface interface StorageInterface { /** * Updates user's password in persistent storage * * @param string $identity Unique user identifier * @param string $password New password hash */ public function updatePassword($identity, $password); } Wednesday, January 29, 14
    • UserDao use JeremyKendallPasswordStorageStorageInterface; class UserDao implements StorageInterface { protected $db; public function __construct(PDO $db) { $this->db = $db; } public function updatePassword($identity, $newPasswordHash) { $sql = 'UPDATE users SET passwordHash = :passwordHash WHERE identity = :identity'; $stmt = $this->db->prepare($sql); $stmt->execute(array('passwordHash' => $newPasswordHash, 'identity' => $identity)); return $this->find($identity); } } Wednesday, January 29, 14
    • Storage Decorator use JeremyKendallPasswordDecoratorStorageDecorator; $validator = new StorageDecorator($upgradeDecorator, $userDao); // Uses the optional third argument for PasswordValidatorInterface::isValid() $result = $validator->isValid('password', $passwordHash, 'arthur@arthurdent.com'); // Result is the same as any other validation attempt except ... // ... ValidationResult::SUCCESS_PASSWORD_REHASHED hashes are automatically persisted! Wednesday, January 29, 14
    • Recap Wednesday, January 29, 14
    • Recap ‣ Wednesday, January 29, 14 Use the new PHP password hashing functions
    • Recap ‣ Use Password Validator to make it dead simple ‣ Use the new PHP password hashing functions Wednesday, January 29, 14
    • Recap ‣ Use Password Validator to make it dead simple ‣ If you’re not at PHP 5.5, use password_compat ‣ Use the new PHP password hashing functions Wednesday, January 29, 14
    • Recap ‣ Use Password Validator to make it dead simple ‣ If you’re not at PHP 5.5, use password_compat ‣ If you’re not at PHP 5.3.7+, UPGRADE ‣ Use the new PHP password hashing functions Wednesday, January 29, 14
    • Recap ‣ Use Password Validator to make it dead simple ‣ If you’re not at PHP 5.5, use password_compat ‣ If you’re not at PHP 5.3.7+, UPGRADE ‣ If you can’t upgrade, use OpenWall’s phpass ‣ Use the new PHP password hashing functions Wednesday, January 29, 14
    • Recap ‣ Use Password Validator to make it dead simple ‣ If you’re not at PHP 5.5, use password_compat ‣ If you’re not at PHP 5.3.7+, UPGRADE ‣ If you can’t upgrade, use OpenWall’s phpass ‣ DO NOT ROLL YOUR OWN ‣ Use the new PHP password hashing functions Wednesday, January 29, 14
    • Resources Wednesday, January 29, 14
    • Resources ‣ Wednesday, January 29, 14 PHP Password Hashing Functions: http://php.net/password
    • Resources ‣ Original password_hash RFC: ‣ PHP Password Hashing Functions: http://php.net/password Wednesday, January 29, 14 https://wiki.php.net/rfc/password_hash
    • Resources ‣ Original password_hash RFC: ‣ Password Validator: ‣ PHP Password Hashing Functions: http://php.net/password https://wiki.php.net/rfc/password_hash https://github.com/jeremykendall/password-validator Wednesday, January 29, 14
    • Resources ‣ Original password_hash RFC: ‣ Password Validator: ‣ password_compat: ‣ PHP Password Hashing Functions: http://php.net/password https://wiki.php.net/rfc/password_hash https://github.com/jeremykendall/password-validator https://github.com/ircmaxell/password_compat Wednesday, January 29, 14
    • Resources ‣ Original password_hash RFC: ‣ Password Validator: ‣ password_compat: ‣ OpenWall phpass: ‣ PHP Password Hashing Functions: http://php.net/password https://wiki.php.net/rfc/password_hash https://github.com/jeremykendall/password-validator https://github.com/ircmaxell/password_compat http://www.openwall.com/phpass/ Wednesday, January 29, 14
    • Thanks! jeremy@jeremykendall.net http://about.me/jeremykendall @jeremykendall http://365.jeremykendall.net Wednesday, January 29, 14