From 122c6586bcc17a06f4aeffa88adf8e399276927b Mon Sep 17 00:00:00 2001 From: ljacqu Date: Fri, 25 Nov 2016 16:41:55 +0100 Subject: [PATCH] #685 Add php implementation for PBKDF2 - Create php sample for PBKDF2 - Rename pbkdf2 java classes (remove Crypt prefix) - Remove options from hash setting comment that should not be used --- .../website_integration/AuthMeController.php | 1 - samples/website_integration/Pbkdf2.php | 53 +++++++++++++++++++ samples/website_integration/Sha256.php | 4 +- .../xephi/authme/security/HashAlgorithm.java | 9 ++-- .../crypts/{CryptPBKDF2.java => Pbkdf2.java} | 2 +- ...yptPBKDF2Django.java => Pbkdf2Django.java} | 4 +- .../settings/properties/SecuritySettings.java | 7 +-- ...2DjangoTest.java => Pbkdf2DjangoTest.java} | 8 +-- .../{CryptPBKDF2Test.java => Pbkdf2Test.java} | 8 +-- 9 files changed, 75 insertions(+), 21 deletions(-) create mode 100644 samples/website_integration/Pbkdf2.php rename src/main/java/fr/xephi/authme/security/crypts/{CryptPBKDF2.java => Pbkdf2.java} (96%) rename src/main/java/fr/xephi/authme/security/crypts/{CryptPBKDF2Django.java => Pbkdf2Django.java} (95%) rename src/test/java/fr/xephi/authme/security/crypts/{CryptPBKDF2DjangoTest.java => Pbkdf2DjangoTest.java} (72%) rename src/test/java/fr/xephi/authme/security/crypts/{CryptPBKDF2Test.java => Pbkdf2Test.java} (83%) diff --git a/samples/website_integration/AuthMeController.php b/samples/website_integration/AuthMeController.php index 66fe03b4a..f67cf0608 100644 --- a/samples/website_integration/AuthMeController.php +++ b/samples/website_integration/AuthMeController.php @@ -109,7 +109,6 @@ private function getAuthmeMySqli() { * @return string|null the hash, or null if unavailable (e.g. username doesn't exist) */ private function getHashFromDatabase($username) { - // Add here your database host, username, password and database name $mysqli = $this->getAuthmeMySqli(); if ($mysqli !== null) { $stmt = $mysqli->prepare('SELECT password FROM ' . self::AUTHME_TABLE . ' WHERE username = ?'); diff --git a/samples/website_integration/Pbkdf2.php b/samples/website_integration/Pbkdf2.php new file mode 100644 index 000000000..456c004fc --- /dev/null +++ b/samples/website_integration/Pbkdf2.php @@ -0,0 +1,53 @@ +CHARS = self::initCharRange(); + } + + protected function isValidPassword($password, $hash) { + // hash := pbkdf2_sha256$iterations$salt$hash + $parts = explode('$', $hash); + return count($parts) === 4 && $hash === $this->computeHash($parts[1], $parts[2], $password); + } + + protected function hash($password) { + $salt = $this->generateSalt(); + return $this->computeHash(self::NUMBER_OF_ITERATIONS, $salt, $password); + } + + private function computeHash($iterations, $salt, $password) { + return 'pbkdf2_sha256$' . self::NUMBER_OF_ITERATIONS . '$' . $salt + . '$' . hash_pbkdf2('sha256', $password, $salt, self::NUMBER_OF_ITERATIONS, 64, false); + } + + /** + * @return string randomly generated salt + */ + private function generateSalt() { + $maxCharIndex = count($this->CHARS) - 1; + $salt = ''; + for ($i = 0; $i < self::SALT_LENGTH; ++$i) { + $salt .= $this->CHARS[mt_rand(0, $maxCharIndex)]; + } + return $salt; + } + + private static function initCharRange() { + return array_merge(range('0', '9'), range('a', 'f')); + } +} diff --git a/samples/website_integration/Sha256.php b/samples/website_integration/Sha256.php index 815abe59a..80c0588fe 100644 --- a/samples/website_integration/Sha256.php +++ b/samples/website_integration/Sha256.php @@ -15,7 +15,7 @@ class Sha256 extends AuthMeController { const SALT_LENGTH = 16; public function __construct() { - $this->CHARS = self::initRandomChars(); + $this->CHARS = self::initCharRange(); } protected function isValidPassword($password, $hash) { @@ -41,7 +41,7 @@ private function generateSalt() { return $salt; } - private static function initRandomChars() { + private static function initCharRange() { return array_merge(range('0', '9'), range('a', 'f')); } diff --git a/src/main/java/fr/xephi/authme/security/HashAlgorithm.java b/src/main/java/fr/xephi/authme/security/HashAlgorithm.java index 7bb5681ff..2cfc1b4b4 100644 --- a/src/main/java/fr/xephi/authme/security/HashAlgorithm.java +++ b/src/main/java/fr/xephi/authme/security/HashAlgorithm.java @@ -1,10 +1,11 @@ package fr.xephi.authme.security; import fr.xephi.authme.security.crypts.EncryptionMethod; +import fr.xephi.authme.security.crypts.Pbkdf2; +import fr.xephi.authme.security.crypts.Pbkdf2Django; /** - * The list of hash algorithms supported by AuthMe. The linked {@link EncryptionMethod} implementation - * must be able to be instantiated with the default constructor. + * Hash algorithms supported by AuthMe. */ public enum HashAlgorithm { @@ -18,8 +19,8 @@ public enum HashAlgorithm { MD5(fr.xephi.authme.security.crypts.MD5.class), MD5VB(fr.xephi.authme.security.crypts.MD5VB.class), MYBB(fr.xephi.authme.security.crypts.MYBB.class), - PBKDF2(fr.xephi.authme.security.crypts.CryptPBKDF2.class), - PBKDF2DJANGO(fr.xephi.authme.security.crypts.CryptPBKDF2Django.class), + PBKDF2(Pbkdf2.class), + PBKDF2DJANGO(Pbkdf2Django.class), PHPBB(fr.xephi.authme.security.crypts.PHPBB.class), PHPFUSION(fr.xephi.authme.security.crypts.PHPFUSION.class), @Deprecated diff --git a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java similarity index 96% rename from src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java rename to src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java index 90cfd809e..6b4dd6259 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java +++ b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java @@ -7,7 +7,7 @@ import fr.xephi.authme.security.crypts.description.Usage; @Recommendation(Usage.RECOMMENDED) -public class CryptPBKDF2 extends HexSaltedMethod { +public class Pbkdf2 extends HexSaltedMethod { private static final int NUMBER_OF_ITERATIONS = 10_000; diff --git a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2Django.java b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java similarity index 95% rename from src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2Django.java rename to src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java index 6628ca917..528c1eb11 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2Django.java +++ b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java @@ -9,7 +9,7 @@ import javax.xml.bind.DatatypeConverter; @AsciiRestricted -public class CryptPBKDF2Django extends HexSaltedMethod { +public class Pbkdf2Django extends HexSaltedMethod { private static final int DEFAULT_ITERATIONS = 24000; @@ -32,7 +32,7 @@ public boolean comparePassword(String password, HashedPassword hashedPassword, S try { iterations = Integer.parseInt(line[1]); } catch (NumberFormatException e) { - ConsoleLogger.warning("Could not read number of rounds for CryptPBKDF2Django:" + ConsoleLogger.warning("Could not read number of rounds for Pbkdf2Django:" + StringUtils.formatException(e)); return false; } diff --git a/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java b/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java index 3711715d0..80b0fdf10 100644 --- a/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java +++ b/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java @@ -64,9 +64,10 @@ public class SecuritySettings implements SettingsHolder { newProperty("settings.security.unLoggedinGroup", "unLoggedinGroup"); @Comment({ - "Possible values: MD5, SHA1, SHA256, WHIRLPOOL, XAUTH, MD5VB, PHPBB,", - "MYBB, IPB3, PHPFUSION, SMF, XENFORO, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512,", - "DOUBLEMD5, PBKDF2, PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM (for developers only)" + "Possible values: SHA256, BCRYPT, BCRYPT2Y, PBKDF2, SALTEDSHA512, WHIRLPOOL,", + "MYBB, IPB3, PHPBB, PHPFUSION, SMF, XENFORO, XAUTH, JOOMLA, WBB3, WBB4, MD5VB,", + "PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM (for developers only). See full list at", + "https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/hash_algorithms.md" }) public static final Property PASSWORD_HASH = newProperty(HashAlgorithm.class, "settings.security.passwordHash", HashAlgorithm.SHA256); diff --git a/src/test/java/fr/xephi/authme/security/crypts/CryptPBKDF2DjangoTest.java b/src/test/java/fr/xephi/authme/security/crypts/Pbkdf2DjangoTest.java similarity index 72% rename from src/test/java/fr/xephi/authme/security/crypts/CryptPBKDF2DjangoTest.java rename to src/test/java/fr/xephi/authme/security/crypts/Pbkdf2DjangoTest.java index afff6bf87..a5a1af616 100644 --- a/src/test/java/fr/xephi/authme/security/crypts/CryptPBKDF2DjangoTest.java +++ b/src/test/java/fr/xephi/authme/security/crypts/Pbkdf2DjangoTest.java @@ -1,12 +1,12 @@ package fr.xephi.authme.security.crypts; /** - * Test for {@link CryptPBKDF2Django}. + * Test for {@link Pbkdf2Django}. */ -public class CryptPBKDF2DjangoTest extends AbstractEncryptionMethodTest { +public class Pbkdf2DjangoTest extends AbstractEncryptionMethodTest { - public CryptPBKDF2DjangoTest() { - super(new CryptPBKDF2Django(), + public Pbkdf2DjangoTest() { + super(new Pbkdf2Django(), "pbkdf2_sha256$15000$50a7ff2d7e00$t7Qx2CfzMhGEbyCa3Wk5nJvNjj3N+FdxhpwJDerl4Fs=", // password "pbkdf2_sha256$15000$f9d8a58f3fe2$oMqmMGuJetdubW0cpubmT8CltQLjHT+L2GuwKsaWLx8=", // PassWord1 "pbkdf2_sha256$15000$1170bc7a31f5$Ex/2aQsXm4kogLIYARpUPn04ccK5LYYjyVPpl32ALjE=", // &^%te$t?Pw@_ diff --git a/src/test/java/fr/xephi/authme/security/crypts/CryptPBKDF2Test.java b/src/test/java/fr/xephi/authme/security/crypts/Pbkdf2Test.java similarity index 83% rename from src/test/java/fr/xephi/authme/security/crypts/CryptPBKDF2Test.java rename to src/test/java/fr/xephi/authme/security/crypts/Pbkdf2Test.java index fcfd4d751..1d7b8de7f 100644 --- a/src/test/java/fr/xephi/authme/security/crypts/CryptPBKDF2Test.java +++ b/src/test/java/fr/xephi/authme/security/crypts/Pbkdf2Test.java @@ -1,12 +1,12 @@ package fr.xephi.authme.security.crypts; /** - * Test for {@link CryptPBKDF2}. + * Test for {@link Pbkdf2}. */ -public class CryptPBKDF2Test extends AbstractEncryptionMethodTest { +public class Pbkdf2Test extends AbstractEncryptionMethodTest { - public CryptPBKDF2Test() { - super(new CryptPBKDF2(), + public Pbkdf2Test() { + super(new Pbkdf2(), "pbkdf2_sha256$10000$b25801311edf$093E38B16DFF13FCE5CD64D5D888EE6E0376A3E572FE5DA6749515EA0F384413223A21C464B0BE899E64084D1FFEFD44F2AC768453C87F41B42CC6954C416900", // password "pbkdf2_sha256$10000$fe705da06c57$A41527BD58FED9C9E6F452FC1BA8B0C4C4224ECC63E37F71EB1A0865D2AB81BBFEBCA9B7B6A6E8AEF4717B43F8EB6FB4EDEFFBB399D9D991EF7E23013595BAF0", // PassWord1 "pbkdf2_sha256$10000$05603593cdda$1D30D1D90D826C866755969F06C312E21CC3E8DA0B777E2C764700E4E1FD890B731FAF44753D68F3FC025D3EAA709E800FBF2AF61DB23464311FCE7D35353A30", // &^%te$t?Pw@_