diff --git a/docs/hash_algorithms.md b/docs/hash_algorithms.md index e7fd0ae36..02bcafe6f 100644 --- a/docs/hash_algorithms.md +++ b/docs/hash_algorithms.md @@ -1,5 +1,5 @@ - + ## Hash Algorithms AuthMe supports the following hash algorithms for storing your passwords safely. @@ -13,11 +13,11 @@ CRAZYCRYPT1 | Do not use | 128 | | | Username | | DOUBLEMD5 | Do not use | 32 | | | None | | IPB3 | Acceptable | 32 | | | Text | 5 | Y IPB4 | Does not work | 60 | | | Text | 22 | Y -JOOMLA | Recommended | 65 | | | Text | 32 | +JOOMLA | Acceptable | 65 | | | Text | 32 | MD5 | Do not use | 32 | | | None | | MD5VB | Acceptable | 56 | | | Text | 16 | MYBB | Acceptable | 32 | | | Text | 8 | Y -PBKDF2 | Does not work | 332 | | | Text | 12 | +PBKDF2 | Recommended | 165 | | | Text | 16 | PBKDF2DJANGO | Acceptable | 77 | Y | | Text | 12 | PHPBB | Acceptable | 34 | | | Text | 16 | PHPFUSION | Do not use | 64 | Y | | | | Y @@ -82,4 +82,4 @@ or bad. --- -This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sat Oct 01 23:42:20 CEST 2016 +This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Fri Nov 25 15:48:35 CET 2016 diff --git a/pom.xml b/pom.xml index 44196e876..24a202455 100644 --- a/pom.xml +++ b/pom.xml @@ -268,6 +268,10 @@ net.ricecode.similarity fr.xephi.authme.libs.ricecode.similarity + + de.rtner + fr.xephi.authme.libs.de.rtner + javax.inject fr.xephi.authme.libs.javax.inject @@ -319,6 +323,10 @@ net.ricecode.similarity fr.xephi.authme.libs.ricecode.similarity + + de.rtner + fr.xephi.authme.libs.de.rtner + javax.inject fr.xephi.authme.libs.javax.inject @@ -524,6 +532,13 @@ true + + + de.rtner + PBKDF2 + 1.1.2 + + 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 @@ abstract class AuthMeController { * @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 @@ class Sha256 extends AuthMeController { 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/permission/AuthGroupHandler.java b/src/main/java/fr/xephi/authme/permission/AuthGroupHandler.java index 492c69115..537c3ebc5 100644 --- a/src/main/java/fr/xephi/authme/permission/AuthGroupHandler.java +++ b/src/main/java/fr/xephi/authme/permission/AuthGroupHandler.java @@ -10,6 +10,7 @@ import fr.xephi.authme.settings.properties.PluginSettings; import fr.xephi.authme.settings.properties.SecuritySettings; import org.bukkit.entity.Player; +import javax.annotation.PostConstruct; import javax.inject.Inject; import java.util.Arrays; @@ -115,6 +116,7 @@ public class AuthGroupHandler implements Reloadable { } @Override + @PostConstruct public void reload() { unloggedInGroup = settings.getProperty(SecuritySettings.UNLOGGEDIN_GROUP); unregisteredGroup = settings.getProperty(HooksSettings.UNREGISTERED_GROUP); diff --git a/src/main/java/fr/xephi/authme/security/HashAlgorithm.java b/src/main/java/fr/xephi/authme/security/HashAlgorithm.java index 7bb5681ff..732582e03 100644 --- a/src/main/java/fr/xephi/authme/security/HashAlgorithm.java +++ b/src/main/java/fr/xephi/authme/security/HashAlgorithm.java @@ -3,8 +3,7 @@ package fr.xephi.authme.security; import fr.xephi.authme.security.crypts.EncryptionMethod; /** - * 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 +17,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(fr.xephi.authme.security.crypts.Pbkdf2.class), + PBKDF2DJANGO(fr.xephi.authme.security.crypts.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/CryptPBKDF2.java deleted file mode 100644 index 57c13ee6c..000000000 --- a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java +++ /dev/null @@ -1,40 +0,0 @@ -package fr.xephi.authme.security.crypts; - -import fr.xephi.authme.security.crypts.description.Recommendation; -import fr.xephi.authme.security.crypts.description.Usage; -import fr.xephi.authme.security.pbkdf2.PBKDF2Engine; -import fr.xephi.authme.security.pbkdf2.PBKDF2Parameters; - -import java.util.Arrays; - -@Recommendation(Usage.DOES_NOT_WORK) -public class CryptPBKDF2 extends HexSaltedMethod { - - @Override - public String computeHash(String password, String salt, String name) { - String result = "pbkdf2_sha256$10000$" + salt + "$"; - PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 10000); - PBKDF2Engine engine = new PBKDF2Engine(params); - - return result + Arrays.toString(engine.deriveKey(password, 64)); - } - - @Override - public boolean comparePassword(String password, HashedPassword hashedPassword, String unusedName) { - String[] line = hashedPassword.getHash().split("\\$"); - if (line.length != 4) { - return false; - } - String salt = line[2]; - String derivedKey = line[3]; - PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 10000, derivedKey.getBytes()); - PBKDF2Engine engine = new PBKDF2Engine(params); - return engine.verifyKey(password); - } - - @Override - public int getSaltLength() { - return 12; - } - -} diff --git a/src/main/java/fr/xephi/authme/security/crypts/JOOMLA.java b/src/main/java/fr/xephi/authme/security/crypts/JOOMLA.java index ee7e49c79..ca72674b3 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/JOOMLA.java +++ b/src/main/java/fr/xephi/authme/security/crypts/JOOMLA.java @@ -4,7 +4,7 @@ import fr.xephi.authme.security.HashUtils; import fr.xephi.authme.security.crypts.description.Recommendation; import fr.xephi.authme.security.crypts.description.Usage; -@Recommendation(Usage.RECOMMENDED) +@Recommendation(Usage.ACCEPTABLE) public class JOOMLA extends HexSaltedMethod { @Override diff --git a/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java new file mode 100644 index 000000000..5367a2a12 --- /dev/null +++ b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java @@ -0,0 +1,60 @@ +package fr.xephi.authme.security.crypts; + +import de.rtner.misc.BinTools; +import de.rtner.security.auth.spi.PBKDF2Engine; +import de.rtner.security.auth.spi.PBKDF2Parameters; +import fr.xephi.authme.ConsoleLogger; +import fr.xephi.authme.security.crypts.description.Recommendation; +import fr.xephi.authme.security.crypts.description.Usage; +import fr.xephi.authme.settings.Settings; +import fr.xephi.authme.settings.properties.SecuritySettings; + +import javax.inject.Inject; + +@Recommendation(Usage.RECOMMENDED) +public class Pbkdf2 extends HexSaltedMethod { + + private static final int DEFAULT_ROUNDS = 10_000; + private int numberOfRounds; + + @Inject + Pbkdf2(Settings settings) { + int configuredRounds = settings.getProperty(SecuritySettings.PBKDF2_NUMBER_OF_ROUNDS); + this.numberOfRounds = configuredRounds > 0 ? configuredRounds : DEFAULT_ROUNDS; + } + + @Override + public String computeHash(String password, String salt, String name) { + String result = "pbkdf2_sha256$" + numberOfRounds + "$" + salt + "$"; + PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "UTF-8", salt.getBytes(), numberOfRounds); + PBKDF2Engine engine = new PBKDF2Engine(params); + + return result + BinTools.bin2hex(engine.deriveKey(password, 64)); + } + + @Override + public boolean comparePassword(String password, HashedPassword hashedPassword, String unusedName) { + String[] line = hashedPassword.getHash().split("\\$"); + if (line.length != 4) { + return false; + } + int iterations; + try { + iterations = Integer.parseInt(line[1]); + } catch (NumberFormatException e) { + ConsoleLogger.logException("Cannot read number of rounds for Pbkdf2", e); + return false; + } + String salt = line[2]; + byte[] derivedKey = BinTools.hex2bin(line[3]); + PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "UTF-8", salt.getBytes(), iterations, derivedKey); + PBKDF2Engine engine = new PBKDF2Engine(params); + return engine.verifyKey(password); + } + + @Override + public int getSaltLength() { + return 16; + } + +} 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 75% 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 79d06e0a8..93988e0d0 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2Django.java +++ b/src/main/java/fr/xephi/authme/security/crypts/Pbkdf2Django.java @@ -1,15 +1,14 @@ package fr.xephi.authme.security.crypts; +import de.rtner.security.auth.spi.PBKDF2Engine; +import de.rtner.security.auth.spi.PBKDF2Parameters; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.security.crypts.description.AsciiRestricted; -import fr.xephi.authme.security.pbkdf2.PBKDF2Engine; -import fr.xephi.authme.security.pbkdf2.PBKDF2Parameters; -import fr.xephi.authme.util.StringUtils; import javax.xml.bind.DatatypeConverter; @AsciiRestricted -public class CryptPBKDF2Django extends HexSaltedMethod { +public class Pbkdf2Django extends HexSaltedMethod { private static final int DEFAULT_ITERATIONS = 24000; @@ -19,7 +18,7 @@ public class CryptPBKDF2Django extends HexSaltedMethod { PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), DEFAULT_ITERATIONS); PBKDF2Engine engine = new PBKDF2Engine(params); - return result + String.valueOf(DatatypeConverter.printBase64Binary(engine.deriveKey(password, 32))); + return result + DatatypeConverter.printBase64Binary(engine.deriveKey(password, 32)); } @Override @@ -32,8 +31,7 @@ public class CryptPBKDF2Django extends HexSaltedMethod { try { iterations = Integer.parseInt(line[1]); } catch (NumberFormatException e) { - ConsoleLogger.warning("Could not read number of rounds for CryptPBKDF2Django:" - + StringUtils.formatException(e)); + ConsoleLogger.logException("Could not read number of rounds for Pbkdf2Django:", e); return false; } String salt = line[2]; diff --git a/src/main/java/fr/xephi/authme/security/pbkdf2/BinTools.java b/src/main/java/fr/xephi/authme/security/pbkdf2/BinTools.java deleted file mode 100644 index 34bf8aac2..000000000 --- a/src/main/java/fr/xephi/authme/security/pbkdf2/BinTools.java +++ /dev/null @@ -1,114 +0,0 @@ -package fr.xephi.authme.security.pbkdf2; - -/* - * Free auxiliary functions. Copyright 2007, 2014, Matthias Gärtner - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ - -/** - * Free auxiliary functions - * - * @author Matthias Gärtner - */ -public class BinTools { - public static final String hex = "0123456789ABCDEF"; - - /** - * Simple binary-to-hexadecimal conversion. - * - * @param b - * Input bytes. May be null. - * @return Hexadecimal representation of b. Uppercase A-F, two characters - * per byte. Empty string on null input. - */ - public static String bin2hex(final byte[] b) { - if (b == null) { - return ""; - } - StringBuffer sb = new StringBuffer(2 * b.length); - for (int i = 0; i < b.length; i++) { - int v = (256 + b[i]) % 256; - sb.append(hex.charAt((v / 16) & 15)); - sb.append(hex.charAt((v % 16) & 15)); - } - return sb.toString(); - } - - /** - * Convert hex string to array of bytes. - * - * @param s - * String containing hexadecimal digits. May be null - * . On odd length leading zero will be assumed. - * @return Array on bytes, non-null. - * @throws IllegalArgumentException - * when string contains non-hex character - */ - public static byte[] hex2bin(final String s) { - String m = s; - if (s == null) { - // Allow empty input string. - m = ""; - } else if (s.length() % 2 != 0) { - // Assume leading zero for odd string length - m = "0" + s; - } - byte r[] = new byte[m.length() / 2]; - for (int i = 0, n = 0; i < m.length(); n++) { - char h = m.charAt(i++); - char l = m.charAt(i++); - r[n] = (byte) (hex2bin(h) * 16 + hex2bin(l)); - } - return r; - } - - /** - * Convert hex digit to numerical value. - * - * @param c - * 0-9, a-f, A-F allowd. - * @return 0-15 - * @throws IllegalArgumentException - * on non-hex character - */ - public static int hex2bin(char c) { - if (c >= '0' && c <= '9') { - return (c - '0'); - } - if (c >= 'A' && c <= 'F') { - return (c - 'A' + 10); - } - if (c >= 'a' && c <= 'f') { - return (c - 'a' + 10); - } - throw new IllegalArgumentException("Input string may only contain hex digits, but found '" + c + "'"); - } - - public static void main(String[] args) { - byte b[] = new byte[256]; - byte bb = 0; - for (int i = 0; i < 256; i++) { - b[i] = bb++; - } - String s = bin2hex(b); - byte c[] = hex2bin(s); - String t = bin2hex(c); - if (!s.equals(t)) { - throw new AssertionError("Mismatch"); - } - } -} diff --git a/src/main/java/fr/xephi/authme/security/pbkdf2/MacBasedPRF.java b/src/main/java/fr/xephi/authme/security/pbkdf2/MacBasedPRF.java deleted file mode 100644 index 88ff11bfc..000000000 --- a/src/main/java/fr/xephi/authme/security/pbkdf2/MacBasedPRF.java +++ /dev/null @@ -1,96 +0,0 @@ -package fr.xephi.authme.security.pbkdf2; - -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - -/** - *

- * Default PRF implementation based on standard javax.crypt.Mac mechanisms. - *

- *

- * A free Java implementation of Password Based Key Derivation Function 2 as - * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner - *

- *

- * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2.1 of the License, or (at your option) - * any later version. - *

- *

- * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - *

- *

- * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - *

- *

- * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - *

- * - * @author Matthias Gärtner - * @version 1.0 - */ -public class MacBasedPRF implements PRF { - - protected Mac mac; - - protected int hLen; - - protected final String macAlgorithm; - - /** - * Create Mac-based Pseudo Random Function. - * - * @param macAlgorithm Mac algorithm to use, i.e. HMacSHA1 or HMacMD5. - */ - public MacBasedPRF(String macAlgorithm) { - this.macAlgorithm = macAlgorithm; - try { - mac = Mac.getInstance(macAlgorithm); - hLen = mac.getMacLength(); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - } - - public MacBasedPRF(String macAlgorithm, String provider) { - this.macAlgorithm = macAlgorithm; - try { - mac = Mac.getInstance(macAlgorithm, provider); - hLen = mac.getMacLength(); - } catch (NoSuchAlgorithmException | NoSuchProviderException e) { - throw new RuntimeException(e); - } - } - - @Override - public byte[] doFinal(byte[] M) { - byte[] r = mac.doFinal(M); - return r; - } - - @Override - public int getHLen() { - return hLen; - } - - @Override - public void init(byte[] P) { - try { - mac.init(new SecretKeySpec(P, macAlgorithm)); - } catch (InvalidKeyException e) { - throw new RuntimeException(e); - } - } -} diff --git a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2.java b/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2.java deleted file mode 100644 index 59bc96df2..000000000 --- a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2.java +++ /dev/null @@ -1,97 +0,0 @@ -package fr.xephi.authme.security.pbkdf2; - -/** - *

- * A free Java implementation of Password Based Key Derivation Function 2 as - * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner - *

- *

- * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2.1 of the License, or (at your option) - * any later version. - *

- *

- * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - *

- *

- * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - *

- *

- * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - *

- * - * @author Matthias Gärtner - * @version 1.0 - */ -public interface PBKDF2 { - - /** - * Convert String-based input to internal byte array, then invoke PBKDF2. - * Desired key length defaults to Pseudo Random Function block size. - * - * @param inputPassword Candidate password to compute the derived key for. - * - * @return internal byte array - */ - byte[] deriveKey(String inputPassword); - - /** - * Convert String-based input to internal byte array, then invoke PBKDF2. - * - * @param inputPassword Candidate password to compute the derived key for. - * @param dkLen Specify desired key length - * - * @return internal byte array - */ - byte[] deriveKey(String inputPassword, int dkLen); - - /** - * Convert String-based input to internal byte arrays, then invoke PBKDF2 - * and verify result against the reference data that is supplied in the - * PBKDF2Parameters. - * - * @param inputPassword Candidate password to compute the derived key for. - * - * @return true password match; false incorrect - * password - */ - boolean verifyKey(String inputPassword); - - /** - * Allow reading of configured parameters. - * - * @return Currently set parameters. - */ - PBKDF2Parameters getParameters(); - - /** - * Allow setting of configured parameters. - * - * @param parameters PBKDF2Parameters - */ - void setParameters(PBKDF2Parameters parameters); - - /** - * Get currently set Pseudo Random Function. - * - * @return Currently set Pseudo Random Function - */ - PRF getPseudoRandomFunction(); - - /** - * Set the Pseudo Random Function to use. Note that deriveKeys/getPRF does - * init this object using the supplied candidate password. If this is - * undesired, one has to override getPRF. - * - * @param prf Pseudo Random Function to set. - */ - void setPseudoRandomFunction(PRF prf); -} diff --git a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Engine.java b/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Engine.java deleted file mode 100644 index d32b8752d..000000000 --- a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Engine.java +++ /dev/null @@ -1,346 +0,0 @@ -package fr.xephi.authme.security.pbkdf2; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; - -/** - *

- * Request for Comments: 2898 PKCS #5: Password-Based Cryptography Specification - *

- * Version 2.0 - *

- *

- * PBKDF2 (P, S, c, dkLen) - *

- * Options: - * - * Input: - * - * Output: - * - *

- * A free Java implementation of Password Based Key Derivation Function 2 as - * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner - *

- *

- * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2.1 of the License, or (at your option) - * any later version. - *

- *

- * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - *

- *

- * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - *

- *

- * For Details, see - * http://www. - * gnu.org/licenses/old-licenses/lgpl-2.1.html. - *

- * - * @author Matthias Gärtner - * @version 1.0 - * @see RFC 2898 - */ -public class PBKDF2Engine implements PBKDF2 { - - protected PBKDF2Parameters parameters; - - protected PRF prf; - - /** - * Constructor for PBKDF2 implementation object. PBKDF2 parameters must be - * passed later. - */ - public PBKDF2Engine() { - this.parameters = null; - prf = null; - } - - /** - * Constructor for PBKDF2 implementation object. PBKDF2 parameters are - * passed so that this implementation knows iteration count, method to use - * and String encoding. - * - * @param parameters Data holder for iteration count, method to use et cetera. - */ - public PBKDF2Engine(PBKDF2Parameters parameters) { - this.parameters = parameters; - prf = null; - } - - /** - * Constructor for PBKDF2 implementation object. PBKDF2 parameters are - * passed so that this implementation knows iteration count, method to use - * and String encoding. - * - * @param parameters Data holder for iteration count, method to use et cetera. - * @param prf Supply customer Pseudo Random Function. - */ - public PBKDF2Engine(PBKDF2Parameters parameters, PRF prf) { - this.parameters = parameters; - this.prf = prf; - } - - /** - * Convenience client function. Convert supplied password with random 8-byte - * salt and 1000 iterations using HMacSHA1. Assume that password is in - * ISO-8559-1 encoding. Output result as - * "Salt:iteration-count:PBKDF2" with binary data in hexadecimal - * encoding. - *

- * Example: Password "password" (without the quotes) leads to - * 48290A0B96C426C3:1000:973899B1D4AFEB3ED371060D0797E0EE0142BD04 - *

- * @param args Supply the password as argument. - * - * @throws IOException an ioexception occured - * @throws NoSuchAlgorithmException a NoSuchAlgorithmException occured - */ - public static void main(String[] args) - throws IOException, NoSuchAlgorithmException { - String password = "password"; - String candidate = null; - PBKDF2Formatter formatter = new PBKDF2HexFormatter(); - - if (args.length >= 1) { - password = args[0]; - } - if (args.length >= 2) { - candidate = args[1]; - } - if (candidate == null) { - // Creation mode - SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); - byte[] salt = new byte[8]; - sr.nextBytes(salt); - int iterations = 1000; - PBKDF2Parameters p = new PBKDF2Parameters("HmacSHA1", "ISO-8859-1", salt, iterations); - PBKDF2Engine e = new PBKDF2Engine(p); - p.setDerivedKey(e.deriveKey(password)); - candidate = formatter.toString(p); - } else { - // Verification mode - PBKDF2Parameters p = new PBKDF2Parameters(); - p.setHashAlgorithm("HmacSHA1"); - p.setHashCharset("ISO-8859-1"); - if (formatter.fromString(p, candidate)) { - throw new IllegalArgumentException("Candidate data does not have correct format (\"" + candidate + "\")"); - } - PBKDF2Engine e = new PBKDF2Engine(p); - boolean verifyOK = e.verifyKey(password); - System.exit(verifyOK ? 0 : 1); - } - } - - @Override - public byte[] deriveKey(String inputPassword) { - return deriveKey(inputPassword, 0); - } - - @Override - public byte[] deriveKey(String inputPassword, int dkLen) { - byte[] r = null; - byte[] P = null; - String charset = parameters.getHashCharset(); - if (inputPassword == null) { - inputPassword = ""; - } - try { - if (charset == null) { - P = inputPassword.getBytes(); - } else { - P = inputPassword.getBytes(charset); - } - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - assertPRF(P); - if (dkLen == 0) { - dkLen = prf.getHLen(); - } - r = PBKDF2(prf, parameters.getSalt(), parameters.getIterationCount(), dkLen); - return r; - } - - @Override - public boolean verifyKey(String inputPassword) { - byte[] referenceKey = getParameters().getDerivedKey(); - if (referenceKey == null || referenceKey.length == 0) { - return false; - } - byte[] inputKey = deriveKey(inputPassword, referenceKey.length); - - if (inputKey == null || inputKey.length != referenceKey.length) { - return false; - } - for (int i = 0; i < inputKey.length; i++) { - if (inputKey[i] != referenceKey[i]) { - return false; - } - } - return true; - } - - /** - * Factory method. Default implementation is (H)MAC-based. To be overridden - * in derived classes. - * - * @param P User-supplied candidate password as array of bytes. - */ - protected void assertPRF(byte[] P) { - if (prf == null) { - prf = new MacBasedPRF(parameters.getHashAlgorithm()); - } - prf.init(P); - } - - @Override - public PRF getPseudoRandomFunction() { - return prf; - } - - @Override - public void setPseudoRandomFunction(PRF prf) { - this.prf = prf; - } - - /** - * Core Password Based Key Derivation Function 2. - * - * @param prf Pseudo Random Function (i.e. HmacSHA1) - * @param S Salt as array of bytes. null means no salt. - * @param c Iteration count (see RFC 2898 4.2) - * @param dkLen desired length of derived key. - * - * @return internal byte array * @see RFC 2898 5.2 - */ - protected byte[] PBKDF2(PRF prf, byte[] S, int c, int dkLen) { - if (S == null) { - S = new byte[0]; - } - int hLen = prf.getHLen(); - int l = ceil(dkLen, hLen); - int r = dkLen - (l - 1) * hLen; - byte T[] = new byte[l * hLen]; - int ti_offset = 0; - for (int i = 1; i <= l; i++) { - _F(T, ti_offset, prf, S, c, i); - ti_offset += hLen; - } - if (r < hLen) { - // Incomplete last block - byte DK[] = new byte[dkLen]; - System.arraycopy(T, 0, DK, 0, dkLen); - return DK; - } - return T; - } - - /** - * Integer division with ceiling function. - * - * @param a Integer - * @param b Integer - * - * @return ceil(a/b) * @see RFC 2898 5.2 Step - * 2. - */ - protected int ceil(int a, int b) { - int m = 0; - if (a % b > 0) { - m = 1; - } - return a / b + m; - } - - /** - * Function F. - * - * @param dest Destination byte buffer - * @param offset Offset into destination byte buffer - * @param prf Pseudo Random Function - * @param S Salt as array of bytes - * @param c Iteration count - * @param blockIndex Integer - * - * @see RFC 2898 5.2 Step - * 3. - */ - protected void _F(byte[] dest, int offset, PRF prf, byte[] S, int c, - int blockIndex) { - int hLen = prf.getHLen(); - byte U_r[] = new byte[hLen]; - - // U0 = S || INT (i); - byte U_i[] = new byte[S.length + 4]; - System.arraycopy(S, 0, U_i, 0, S.length); - INT(U_i, S.length, blockIndex); - - for (int i = 0; i < c; i++) { - U_i = prf.doFinal(U_i); - xor(U_r, U_i); - } - System.arraycopy(U_r, 0, dest, offset, hLen); - } - - /** - * Block-Xor. Xor source bytes into destination byte buffer. Destination - * buffer must be same length or less than source buffer. - * - * @param dest byte array - * @param src byte array - */ - protected void xor(byte[] dest, byte[] src) { - for (int i = 0; i < dest.length; i++) { - dest[i] ^= src[i]; - } - } - - /** - * Four-octet encoding of the integer i, most significant octet first. - * - * @param dest byte array - * @param offset Integer - * @param i Integer - * - * @see RFC 2898 5.2 Step - * 3. - */ - protected void INT(byte[] dest, int offset, int i) { - dest[offset] = (byte) (i / (256 * 256 * 256)); - dest[offset + 1] = (byte) (i / (256 * 256)); - dest[offset + 2] = (byte) (i / (256)); - dest[offset + 3] = (byte) (i); - } - - @Override - public PBKDF2Parameters getParameters() { - return parameters; - } - - @Override - public void setParameters(PBKDF2Parameters parameters) { - this.parameters = parameters; - } -} diff --git a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Formatter.java b/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Formatter.java deleted file mode 100644 index 3916d1c03..000000000 --- a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Formatter.java +++ /dev/null @@ -1,56 +0,0 @@ -package fr.xephi.authme.security.pbkdf2; - -/** - *

- * A free Java implementation of Password Based Key Derivation Function 2 as - * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner - *

- *

- * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2.1 of the License, or (at your option) - * any later version. - *

- *

- * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - *

- *

- * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - *

- *

- * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - *

- * - * @author Matthias Gärtner - * @version 1.0 - */ -public interface PBKDF2Formatter { - - /** - * Convert parameters to String. - * - * @param p Parameters object to output. - * - * @return String representation - */ - String toString(PBKDF2Parameters p); - - /** - * Convert String to parameters. Depending on actual implementation, it may - * be required to set further fields externally. - * - * @param s String representation of parameters to decode. - * @param p PBKDF2Parameters - * - * @return false syntax OK, true some syntax - * issue. - */ - boolean fromString(PBKDF2Parameters p, String s); -} diff --git a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2HexFormatter.java b/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2HexFormatter.java deleted file mode 100644 index 54544a4c2..000000000 --- a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2HexFormatter.java +++ /dev/null @@ -1,62 +0,0 @@ -package fr.xephi.authme.security.pbkdf2; - -/** - *

- * A free Java implementation of Password Based Key Derivation Function 2 as - * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner - *

- *

- * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2.1 of the License, or (at your option) - * any later version. - *

- *

- * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - *

- *

- * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - *

- *

- * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - *

- * - * @author Matthias Gärtner - * @version 1.0 - */ -public class PBKDF2HexFormatter implements PBKDF2Formatter { - - @Override - public boolean fromString(PBKDF2Parameters p, String s) { - if (p == null || s == null) { - return true; - } - - String[] p123 = s.split(":"); - if (p123.length != 3) { - return true; - } - - byte salt[] = BinTools.hex2bin(p123[0]); - int iterationCount = Integer.parseInt(p123[1]); - byte bDK[] = BinTools.hex2bin(p123[2]); - - p.setSalt(salt); - p.setIterationCount(iterationCount); - p.setDerivedKey(bDK); - return false; - } - - @Override - public String toString(PBKDF2Parameters p) { - String s = BinTools.bin2hex(p.getSalt()) + ":" + String.valueOf(p.getIterationCount()) + ":" + BinTools.bin2hex(p.getDerivedKey()); - return s; - } -} diff --git a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Parameters.java b/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Parameters.java deleted file mode 100644 index 04abaa9f8..000000000 --- a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Parameters.java +++ /dev/null @@ -1,139 +0,0 @@ -package fr.xephi.authme.security.pbkdf2; - -/** - *

- * Parameter data holder for PBKDF2 configuration. - *

- *

- * A free Java implementation of Password Based Key Derivation Function 2 as - * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner - *

- *

- * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2.1 of the License, or (at your option) - * any later version. - *

- *

- * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - *

- *

- * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - *

- *

- * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - *

- * - * @author Matthias Gärtner - * @version 1.0 - */ -public class PBKDF2Parameters { - - protected byte[] salt; - - protected int iterationCount; - - protected String hashAlgorithm; - - protected String hashCharset; - - /** - * The derived key is actually only a convenience to store a reference - * derived key. It is not used during computation. - */ - protected byte[] derivedKey; - - /** - * Constructor. Defaults to null for byte arrays, UTF-8 as - * character set and 1000 for iteration count. - */ - public PBKDF2Parameters() { - this.hashAlgorithm = null; - this.hashCharset = "UTF-8"; - this.salt = null; - this.iterationCount = 1000; - this.derivedKey = null; - } - - /** - * Constructor. - * - * @param hashAlgorithm for example HMacSHA1 or HMacMD5 - * @param hashCharset for example UTF-8 - * @param salt Salt as byte array, may be null (not recommended) - * @param iterationCount Number of iterations to execute. Recommended value 1000. - */ - public PBKDF2Parameters(String hashAlgorithm, String hashCharset, - byte[] salt, int iterationCount) { - this.hashAlgorithm = hashAlgorithm; - this.hashCharset = hashCharset; - this.salt = salt; - this.iterationCount = iterationCount; - this.derivedKey = null; - } - - /** - * Constructor. - * - * @param hashAlgorithm for example HMacSHA1 or HMacMD5 - * @param hashCharset for example UTF-8 - * @param salt Salt as byte array, may be null (not recommended) - * @param iterationCount Number of iterations to execute. Recommended value 1000. - * @param derivedKey Convenience data holder, not used during computation. - */ - public PBKDF2Parameters(String hashAlgorithm, String hashCharset, - byte[] salt, int iterationCount, byte[] derivedKey) { - this.hashAlgorithm = hashAlgorithm; - this.hashCharset = hashCharset; - this.salt = salt; - this.iterationCount = iterationCount; - this.derivedKey = derivedKey; - } - - public int getIterationCount() { - return iterationCount; - } - - public void setIterationCount(int iterationCount) { - this.iterationCount = iterationCount; - } - - public byte[] getSalt() { - return salt; - } - - public void setSalt(byte[] salt) { - this.salt = salt; - } - - public byte[] getDerivedKey() { - return derivedKey; - } - - public void setDerivedKey(byte[] derivedKey) { - this.derivedKey = derivedKey; - } - - public String getHashAlgorithm() { - return hashAlgorithm; - } - - public void setHashAlgorithm(String hashAlgorithm) { - this.hashAlgorithm = hashAlgorithm; - } - - public String getHashCharset() { - return hashCharset; - } - - public void setHashCharset(String hashCharset) { - this.hashCharset = hashCharset; - } -} diff --git a/src/main/java/fr/xephi/authme/security/pbkdf2/PRF.java b/src/main/java/fr/xephi/authme/security/pbkdf2/PRF.java deleted file mode 100644 index af40e171d..000000000 --- a/src/main/java/fr/xephi/authme/security/pbkdf2/PRF.java +++ /dev/null @@ -1,60 +0,0 @@ -package fr.xephi.authme.security.pbkdf2; - -/** - *

- * A free Java implementation of Password Based Key Derivation Function 2 as - * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner - *

- *

- * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2.1 of the License, or (at your option) - * any later version. - *

- *

- * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - *

- *

- * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - *

- *

- * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - *

- * - * @author Matthias Gärtner - * @version 1.0 - */ -public interface PRF { - - /** - * Initialize this instance with the user-supplied password. - * - * @param P The password supplied as array of bytes. It is the caller's - * task to convert String passwords to bytes as appropriate. - */ - void init(byte[] P); - - /** - * Pseudo Random Function - * - * @param M Input data/message etc. Together with any data supplied during - * initilization. - * - * @return Random bytes of hLen length. - */ - byte[] doFinal(byte[] M); - - /** - * Query block size of underlying algorithm/mechanism. - * - * @return block size - */ - int getHLen(); -} 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..5bad44b07 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); @@ -85,6 +86,10 @@ public class SecuritySettings implements SettingsHolder { public static final Property> LEGACY_HASHES = new EnumSetProperty<>(HashAlgorithm.class, "settings.security.legacyHashes"); + @Comment("Number of rounds to use if passwordHash is set to PBKDF2. Default is 10000") + public static final Property PBKDF2_NUMBER_OF_ROUNDS = + newProperty("settings.security.pbkdf2Rounds", 10000); + @Comment({"Prevent unsafe passwords from being used; put them in lowercase!", "You should always set 'help' as unsafePassword due to possible conflicts.", "unsafePasswords:", diff --git a/src/main/resources/messages/messages_es.yml b/src/main/resources/messages/messages_es.yml index bc5bcb0f2..d72c7d44b 100644 --- a/src/main/resources/messages/messages_es.yml +++ b/src/main/resources/messages/messages_es.yml @@ -71,7 +71,7 @@ kick_antibot: '¡El modo de protección AntiBot está habilitado! Tienes que esp email_exists: '&c¡El correo de recuperación ya ha sido enviado! Puedes descartarlo y enviar uno nuevo utilizando el siguiente comando:' password_error_nick: '&cNo puedes utilizar tu nombre como contraseña, por favor elige otra...' accounts_owned_other: 'El jugador %name tiene %count cuentas:' -incomplete_email_settings: 'Error: no todos los ajustes necesario se han configurado para enviar correos. Por favor, contacta con un administrador.' +incomplete_email_settings: 'Error: no todos los ajustes necesarios se han configurado para enviar correos. Por favor, contacta con un administrador.' recovery_code_sent: 'El código de recuperación para recuperar tu contraseña se ha enviado a tu correo.' invalid_name_case: 'Solo puedes unirte mediante el nombre de usuario %valid, no %invalid.' email_show: '&2Tu dirección de E-Mail actual es: &f%email' diff --git a/src/test/java/fr/xephi/authme/security/HashAlgorithmIntegrationTest.java b/src/test/java/fr/xephi/authme/security/HashAlgorithmIntegrationTest.java index fcfa4fad3..2d5368197 100644 --- a/src/test/java/fr/xephi/authme/security/HashAlgorithmIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/security/HashAlgorithmIntegrationTest.java @@ -32,6 +32,7 @@ public class HashAlgorithmIntegrationTest { Settings settings = mock(Settings.class); given(settings.getProperty(HooksSettings.BCRYPT_LOG2_ROUND)).willReturn(8); given(settings.getProperty(SecuritySettings.DOUBLE_MD5_SALT_LENGTH)).willReturn(16); + given(settings.getProperty(SecuritySettings.PBKDF2_NUMBER_OF_ROUNDS)).willReturn(10_000); injector = new InjectorBuilder().addDefaultHandlers("fr.xephi.authme").create(); injector.register(Settings.class, settings); } diff --git a/src/test/java/fr/xephi/authme/security/crypts/AbstractEncryptionMethodTest.java b/src/test/java/fr/xephi/authme/security/crypts/AbstractEncryptionMethodTest.java index 4c06a8cc1..24093721a 100644 --- a/src/test/java/fr/xephi/authme/security/crypts/AbstractEncryptionMethodTest.java +++ b/src/test/java/fr/xephi/authme/security/crypts/AbstractEncryptionMethodTest.java @@ -2,7 +2,9 @@ package fr.xephi.authme.security.crypts; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import fr.xephi.authme.TestHelper; import fr.xephi.authme.security.crypts.description.AsciiRestricted; +import org.junit.BeforeClass; import org.junit.Test; import java.util.List; @@ -100,6 +102,11 @@ public abstract class AbstractEncryptionMethodTest { GIVEN_PASSWORDS[3], result3); } + @BeforeClass + public static void setupLogger() { + TestHelper.setupLogger(); + } + @Test public void testGivenPasswords() { // Start with the 2nd to last password if we skip long tests diff --git a/src/test/java/fr/xephi/authme/security/crypts/BcryptTest.java b/src/test/java/fr/xephi/authme/security/crypts/BcryptTest.java index 3c0f1475a..1fe9ed086 100644 --- a/src/test/java/fr/xephi/authme/security/crypts/BcryptTest.java +++ b/src/test/java/fr/xephi/authme/security/crypts/BcryptTest.java @@ -1,9 +1,7 @@ package fr.xephi.authme.security.crypts; -import fr.xephi.authme.TestHelper; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.HooksSettings; -import org.junit.BeforeClass; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -13,11 +11,6 @@ import static org.mockito.Mockito.mock; */ public class BcryptTest extends AbstractEncryptionMethodTest { - @BeforeClass - public static void initializeLogger() { - TestHelper.setupLogger(); - } - public BcryptTest() { super(new BCRYPT(mockSettings()), "$2a$10$6iATmYgwJVc3YONhVcZFve3Cfb5GnwvKhJ20r.hMjmcNkIT9.Uh9K", // password diff --git a/src/test/java/fr/xephi/authme/security/crypts/CryptPBKDF2Test.java b/src/test/java/fr/xephi/authme/security/crypts/CryptPBKDF2Test.java deleted file mode 100644 index 36ce7106a..000000000 --- a/src/test/java/fr/xephi/authme/security/crypts/CryptPBKDF2Test.java +++ /dev/null @@ -1,20 +0,0 @@ -package fr.xephi.authme.security.crypts; - -import org.junit.Ignore; - -/** - * Test for {@link CryptPBKDF2}. - */ -@Ignore -// TODO #685: This algorithm seems broken -public class CryptPBKDF2Test extends AbstractEncryptionMethodTest { - - public CryptPBKDF2Test() { - super(new CryptPBKDF2(), - "pbkdf2_sha256$10000$dd9b1cd071f2$[82, -69, -58, -51, 101, 105, 61, -48, -49, 25, 50, -126, 115, 36, 16, -94, 4, 84, -94, 13, -115, -12, 94, -27, 94, -103, 115, -31, -56, -18, 8, 77, 36, 78, -61, 105, -7, -114, 41, 3, 48, 122, 27, 1, 56, 76, 126, 68, -120, 127, -95, 119, -7, 100, -87, -128, -77, 83, -118, 28, 43, 84, 73, 103]", // password - "pbkdf2_sha256$10000$4b3b650288cd$[99, 25, 45, 22, -66, -109, -109, 30, 117, 77, 22, 63, -36, -126, -116, -66, 35, 109, -33, -4, -112, 53, 48, 33, -20, 107, -100, -37, -89, 59, -29, -83, 57, -123, -40, 11, 98, 32, -74, 77, 107, -76, 95, -9, 110, -92, -31, -2, -18, 115, 43, -27, 16, 36, 75, -56, -11, 58, -62, 21, 0, 37, -59, -82]", // PassWord1 - "pbkdf2_sha256$10000$035205f5ab39$[-121, -15, 97, 35, -105, -57, -49, -60, -58, -106, 101, 78, -103, 2, -116, -120, 0, 106, -107, 10, 78, -97, 111, 98, -15, 40, -53, 84, 120, -86, 116, 12, -60, 19, 105, 1, 71, 99, 4, 43, -4, -36, 35, -110, 59, 73, -20, -8, 46, 102, 51, 84, 54, -92, -41, -84, 28, 36, 37, 26, 90, -6, -49, 70]", // &^%te$t?Pw@_ - "pbkdf2_sha256$10000$ca72ded579e9$[-81, 76, -103, 78, 68, -10, -58, -88, -57, 88, -38, 108, 115, -86, 13, -84, 80, 69, 48, 15, 105, 25, -2, 123, 9, 97, 23, -96, 95, -64, -56, 59, -124, 116, 36, 10, 96, -12, -76, -121, -51, 76, -96, -27, 84, 66, 85, 75, 95, -97, -60, -98, -41, -32, -58, 39, 82, -19, -25, 98, -15, -68, 59, -48]"); // âË_3(íù* - } - -} diff --git a/src/test/java/fr/xephi/authme/security/crypts/IPB4Test.java b/src/test/java/fr/xephi/authme/security/crypts/IPB4Test.java index 325d37d57..28c76a09f 100644 --- a/src/test/java/fr/xephi/authme/security/crypts/IPB4Test.java +++ b/src/test/java/fr/xephi/authme/security/crypts/IPB4Test.java @@ -1,18 +1,10 @@ package fr.xephi.authme.security.crypts; -import fr.xephi.authme.TestHelper; -import org.junit.BeforeClass; - /** * Test for {@link IPB4}. */ public class IPB4Test extends AbstractEncryptionMethodTest { - @BeforeClass - public static void setUpSettings() { - TestHelper.setupLogger(); - } - public IPB4Test() { super(new IPB4(), new HashedPassword("$2a$13$leEvXu77OIwPwNvtZIJvaeAx8EItGHuR3nIlq8416g0gXeJaQdrr2", "leEvXu77OIwPwNvtZIJval"), //password 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 58% 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 1da3c5b91..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,20 +1,12 @@ package fr.xephi.authme.security.crypts; -import fr.xephi.authme.TestHelper; -import org.junit.BeforeClass; - /** - * Test for {@link CryptPBKDF2Django}. + * Test for {@link Pbkdf2Django}. */ -public class CryptPBKDF2DjangoTest extends AbstractEncryptionMethodTest { +public class Pbkdf2DjangoTest extends AbstractEncryptionMethodTest { - @BeforeClass - public static void setupLogger() { - TestHelper.setupLogger(); - } - - 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/Pbkdf2Test.java b/src/test/java/fr/xephi/authme/security/crypts/Pbkdf2Test.java new file mode 100644 index 000000000..8296e56ea --- /dev/null +++ b/src/test/java/fr/xephi/authme/security/crypts/Pbkdf2Test.java @@ -0,0 +1,44 @@ +package fr.xephi.authme.security.crypts; + +import fr.xephi.authme.settings.Settings; +import fr.xephi.authme.settings.properties.SecuritySettings; +import org.junit.Test; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/** + * Test for {@link Pbkdf2}. + */ +public class Pbkdf2Test extends AbstractEncryptionMethodTest { + + public Pbkdf2Test() { + super(new Pbkdf2(mockSettings()), + "pbkdf2_sha256$10000$b25801311edf$093E38B16DFF13FCE5CD64D5D888EE6E0376A3E572FE5DA6749515EA0F384413223A21C464B0BE899E64084D1FFEFD44F2AC768453C87F41B42CC6954C416900", // password + "pbkdf2_sha256$10000$fe705da06c57$A41527BD58FED9C9E6F452FC1BA8B0C4C4224ECC63E37F71EB1A0865D2AB81BBFEBCA9B7B6A6E8AEF4717B43F8EB6FB4EDEFFBB399D9D991EF7E23013595BAF0", // PassWord1 + "pbkdf2_sha256$10000$05603593cdda$1D30D1D90D826C866755969F06C312E21CC3E8DA0B777E2C764700E4E1FD890B731FAF44753D68F3FC025D3EAA709E800FBF2AF61DB23464311FCE7D35353A30", // &^%te$t?Pw@_ + "pbkdf2_sha256$10000$fb944d66d754$F7E3BF8CB07CE3B3C8C5C534F803252F7B4FD58832E33BA62BA46CA06F23BAE12BE03A9CB5874BCFD4469E42972406F920E59F002247B23C22A8CF3D0E7BFFE0"); // âË_3(íù* + } + + @Test + public void shouldDetectMatchForHashWithOtherRoundNumber() { + // given + Pbkdf2 pbkdf2 = new Pbkdf2(mockSettings()); + String hash = "pbkdf2_sha256$4128$3469b0d48b702046$DC8A54351008C6054E12FB19E0BF8A4EA6D4165E0EDC97A1ECD15231037C382DE5BF85D07D5BC9D1ADF9BBFE4CE257C6059FB1B9FF65DB69D8B205F064BE0DA9"; + String clearText = "PassWord1"; + + // when + boolean isMatch = pbkdf2.comparePassword(clearText, new HashedPassword(hash), ""); + + // then + assertThat(isMatch, equalTo(true)); + } + + private static Settings mockSettings() { + Settings settings = mock(Settings.class); + given(settings.getProperty(SecuritySettings.PBKDF2_NUMBER_OF_ROUNDS)).willReturn(4128); + return settings; + } +} diff --git a/src/test/java/fr/xephi/authme/security/crypts/XFBCRYPTTest.java b/src/test/java/fr/xephi/authme/security/crypts/XFBCRYPTTest.java index bda1c0f8c..4edafbdd0 100644 --- a/src/test/java/fr/xephi/authme/security/crypts/XFBCRYPTTest.java +++ b/src/test/java/fr/xephi/authme/security/crypts/XFBCRYPTTest.java @@ -1,18 +1,10 @@ package fr.xephi.authme.security.crypts; -import fr.xephi.authme.TestHelper; -import org.junit.BeforeClass; - /** * Test for {@link XFBCRYPT}. */ public class XFBCRYPTTest extends AbstractEncryptionMethodTest { - @BeforeClass - public static void setup() { - TestHelper.setupLogger(); - } - public XFBCRYPTTest() { super(new XFBCRYPT(), "$2a$10$UtuON/ZG.x8EWG/zQbryB.BHfQVrfxk3H7qykzP.UJQ8YiLjZyfqq", // password