Xenforo support.

- Added getPassword method in DataSource and all implementations.
This commit is contained in:
DNx5
2015-12-31 11:05:18 +07:00
parent aed23cb1ef
commit bd5d341e67
9 changed files with 130 additions and 100 deletions
@@ -36,12 +36,8 @@ public class PasswordSecurity {
}
public boolean comparePassword(String password, String playerName) {
// TODO ljacqu 20151230: Defining a dataSource.getPassword() method would be more efficient
PlayerAuth auth = dataSource.getAuth(playerName);
if (auth != null) {
return comparePassword(password, auth.getPassword(), playerName);
}
return false;
HashedPassword auth = dataSource.getPassword(playerName);
return auth != null && comparePassword(password, auth, playerName);
}
public boolean comparePassword(String password, HashedPassword hashedPassword, String playerName) {
@@ -15,9 +15,9 @@ package fr.xephi.authme.security.crypts;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.security.crypts.description.HasSalt;
import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.SaltType;
import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.StringUtils;
@@ -25,43 +25,45 @@ import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
/**
* <p>
* BCrypt implements OpenBSD-style Blowfish password hashing using the scheme
* described in "A Future-Adaptable Password Scheme" by Niels Provos and David
* Mazieres.
* <p/>
* </p><p>
* This password hashing system tries to thwart off-line password cracking using
* a computationally-intensive hashing algorithm, based on Bruce Schneier's
* Blowfish cipher. The work factor of the algorithm is parameterised, so it can
* be increased as computers get faster.
* <p/>
* </p><p>
* Usage is really simple. To hash a password for the first time, call the
* hashpw method with a random salt, like this:
* <p/>
* </p><p>
* <code>
* String pw_hash = BCrypt.hashpw(plain_password, BCrypt.gensalt()); <br />
* String pw_hash = BCrypt.hashpw(plain_password, BCrypt.gensalt()); <br>
* </code>
* <p/>
* </p><p>
* To check whether a plaintext password matches one that has been hashed
* previously, use the checkpw method:
* <p/>
* </p><p>
* <code>
* if (BCrypt.checkpw(candidate_password, stored_hash))<br />
* &nbsp;&nbsp;&nbsp;&nbsp;System.out.println("It matches");<br />
* else<br />
* &nbsp;&nbsp;&nbsp;&nbsp;System.out.println("It does not match");<br />
* if (BCrypt.checkpw(candidate_password, stored_hash))<br>
* &nbsp;&nbsp;&nbsp;&nbsp;System.out.println("It matches");<br>
* else<br>
* &nbsp;&nbsp;&nbsp;&nbsp;System.out.println("It does not match");<br>
* </code>
* <p/>
* </p><p>
* The gensalt() method takes an optional parameter (log_rounds) that determines
* the computational complexity of the hashing:
* <p/>
* </p><p>
* <code>
* String strong_salt = BCrypt.gensalt(10)<br />
* String stronger_salt = BCrypt.gensalt(12)<br />
* String strong_salt = BCrypt.gensalt(10)<br>
* String stronger_salt = BCrypt.gensalt(12)<br>
* </code>
* <p/>
* </p><p>
* The amount of work increases exponentially (2**log_rounds), so each increment
* is twice as much work. The default log_rounds is 10, and the valid range is 4
* to 31.
* </p>
*
* @author Damien Miller
* @version 0.2
@@ -102,8 +104,11 @@ public class BCRYPT implements EncryptionMethod {
* @param d the byte array to encode
* @param len the number of bytes to encode
*
* @return base64-encoded string * @throws IllegalArgumentException if the length is invalid * @throws IllegalArgumentException
* @return base64-encoded string
*
* @throws IllegalArgumentException if the length is invalid
*/
private static String encode_base64(byte d[], int len)
throws IllegalArgumentException {
int off = 0;
@@ -160,6 +165,7 @@ public class BCRYPT implements EncryptionMethod {
* @param maxolen the maximum number of bytes to decode
*
* @return an array containing the decoded bytes
*
* @throws IllegalArgumentException if maxolen is invalid
*/
private static byte[] decode_base64(String s, int maxolen)
@@ -4,7 +4,7 @@ package fr.xephi.authme.security.crypts;
* The result of a hash computation. See {@link #salt} for details.
*/
public class HashedPassword {
/** The generated hash. */
private final String hash;
/**
@@ -36,13 +36,13 @@ public class HashedPassword {
public HashedPassword(String hash) {
this(hash, null);
}
public String getHash() {
return hash;
}
public String getSalt() {
return salt;
}
}
@@ -1,74 +1,22 @@
package fr.xephi.authme.security.crypts;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class XF implements EncryptionMethod {
@Override
public String computeHash(String password, String salt, String name) {
return getSha256(getSha256(password) + regmatch("\"salt\";.:..:\"(.*)\";.:.:\"hashFunc\"", salt));
}
@Override
public HashedPassword computeHash(String password, String name) {
String salt = generateSalt();
return new HashedPassword(computeHash(password, salt, null), salt);
}
@Override
public boolean comparePassword(String password, HashedPassword hashedPassword, String name) {
// TODO #137: Write the comparePassword method. See commit 121d323 for what was here previously; it was
// utter non-sense
return false;
}
// TODO #137: If this method corresponds to HashUtils.sha256(), use it instead of this
private String getSha256(String password) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
md.update(password.getBytes());
byte byteData[] = md.digest();
StringBuilder sb = new StringBuilder();
for (byte element : byteData) {
sb.append(Integer.toString((element & 0xff) + 0x100, 16).substring(1));
}
StringBuilder hexString = new StringBuilder();
for (byte element : byteData) {
String hex = Integer.toHexString(0xff & element);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
public class XF extends BCRYPT {
private static final Pattern HASH_PATTERN = Pattern.compile("\"hash\";s.*\"(.*)?\"");
@Override
public String generateSalt() {
// TODO #137: Find out what kind of salt format XF uses to generate new passwords
return "";
return BCRYPT.gensalt();
}
@Override
public boolean hasSeparateSalt() {
return true;
}
private String regmatch(String pattern, String line) {
List<String> allMatches = new ArrayList<>();
Matcher m = Pattern.compile(pattern).matcher(line);
while (m.find()) {
allMatches.add(m.group(1));
public static String getHashFromBlob(byte[] blob) {
String line = new String(blob);
Matcher m = HASH_PATTERN.matcher(line);
if (m.find()) {
return m.group(1);
}
return allMatches.get(0);
return "*"; // what?
}
}