#358 Create encryption method supertypes, add new methods
This commit is contained in:
@@ -17,6 +17,7 @@ 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.settings.Settings;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.SecureRandom;
|
||||
@@ -63,9 +64,9 @@ import java.security.SecureRandom;
|
||||
* @author Damien Miller
|
||||
* @version 0.2
|
||||
*/
|
||||
@Recommendation(Usage.RECOMMENDED)
|
||||
@HasSalt(value = SaltType.TEXT, length = BCRYPT.BCRYPT_SALT_LEN)
|
||||
public class BCRYPT implements EncryptionMethod {
|
||||
@Recommendation(Usage.RECOMMENDED) // provided the salt length is >= 8
|
||||
@HasSalt(value = SaltType.TEXT) // length depends on Settings.bCryptLog2Rounds
|
||||
public class BCRYPT implements NewEncrMethod {
|
||||
|
||||
// BCrypt parameters
|
||||
private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10;
|
||||
@@ -518,8 +519,10 @@ public class BCRYPT implements EncryptionMethod {
|
||||
return hashpw(password, salt);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
return hashpw(password, generateSalt());
|
||||
@Override
|
||||
public HashResult computeHash(String password, String name) {
|
||||
String salt = generateSalt();
|
||||
return new HashResult(hashpw(password, salt), salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -527,7 +530,18 @@ public class BCRYPT implements EncryptionMethod {
|
||||
return checkpw(password, hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
||||
return comparePassword(hash, password, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateSalt() {
|
||||
return BCRYPT.gensalt();
|
||||
return BCRYPT.gensalt(Settings.bCryptLog2Rounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSeparateSalt() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.security.MessageDigest;
|
||||
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
@HasSalt(SaltType.USERNAME)
|
||||
public class CRAZYCRYPT1 implements EncryptionMethod {
|
||||
public class CRAZYCRYPT1 extends UsernameSaltMethod {
|
||||
|
||||
private static final char[] CRYPTCHARS =
|
||||
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
@@ -28,23 +28,11 @@ public class CRAZYCRYPT1 implements EncryptionMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return computeHash(password, name);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
public HashResult computeHash(String password, String name) {
|
||||
final String text = "ÜÄaeut//&/=I " + password + "7421€547" + name + "__+IÄIH§%NK " + password;
|
||||
final MessageDigest md = HashUtils.getDigest(MessageDigestAlgorithm.SHA512);
|
||||
md.update(text.getBytes(charset), 0, text.length());
|
||||
return byteArrayToHexString(md.digest());
|
||||
return new HashResult(byteArrayToHexString(md.digest()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return hash.equals(computeHash(password, playerName));
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,7 @@ import java.util.Arrays;
|
||||
public class CryptPBKDF2 implements EncryptionMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
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);
|
||||
@@ -22,8 +21,7 @@ public class CryptPBKDF2 implements EncryptionMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
String[] line = hash.split("\\$");
|
||||
String salt = line[2];
|
||||
String derivedKey = line[3];
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
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.security.pbkdf2.PBKDF2Engine;
|
||||
import fr.xephi.authme.security.pbkdf2.PBKDF2Parameters;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
@Recommendation(Usage.ACCEPTABLE)
|
||||
@HasSalt(value = SaltType.TEXT, length = 12)
|
||||
public class CryptPBKDF2Django implements EncryptionMethod {
|
||||
public class CryptPBKDF2Django extends HexSaltedMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
@@ -23,12 +16,8 @@ public class CryptPBKDF2Django implements EncryptionMethod {
|
||||
return result + String.valueOf(DatatypeConverter.printBase64Binary(engine.deriveKey(password, 32)));
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
return computeHash(password, generateSalt(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
public boolean comparePassword(String hash, String password, String unusedSalt, String unusedName) {
|
||||
String[] line = hash.split("\\$");
|
||||
String salt = line[2];
|
||||
byte[] derivedKey = DatatypeConverter.parseBase64Binary(line[3]);
|
||||
@@ -37,8 +26,9 @@ public class CryptPBKDF2Django implements EncryptionMethod {
|
||||
return engine.verifyKey(password);
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return RandomString.generateHex(12);
|
||||
@Override
|
||||
public int getSaltLength() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,31 +1,12 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.HashUtils;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
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 static fr.xephi.authme.security.HashUtils.md5;
|
||||
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
@HasSalt(SaltType.NONE)
|
||||
public class DOUBLEMD5 implements EncryptionMethod {
|
||||
public class DOUBLEMD5 extends UnsaltedMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return computeHash(password, null);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
return HashUtils.md5(HashUtils.md5(password));
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return hash.equals(computeHash(password, null, null));
|
||||
public String computeHash(String password) {
|
||||
return md5(md5(password));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* Public interface for custom password encryption methods.
|
||||
*/
|
||||
@@ -16,8 +14,7 @@ public interface EncryptionMethod {
|
||||
*
|
||||
* @return The hashed password
|
||||
*/
|
||||
String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException;
|
||||
String computeHash(String password, String salt, String name);
|
||||
|
||||
/**
|
||||
* Check whether a given hash matches the clear-text password.
|
||||
@@ -30,7 +27,6 @@ public interface EncryptionMethod {
|
||||
* @return True if the password matches, false otherwise
|
||||
*/
|
||||
@Deprecated
|
||||
boolean comparePassword(String hash, String password, String playerName)
|
||||
throws NoSuchAlgorithmException;
|
||||
boolean comparePassword(String hash, String password, String playerName);
|
||||
|
||||
}
|
||||
|
||||
@@ -14,6 +14,10 @@ public class HashResult {
|
||||
this.hash = hash;
|
||||
this.salt = salt;
|
||||
}
|
||||
|
||||
public HashResult(String hash) {
|
||||
this(hash, null);
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
return hash;
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
/**
|
||||
* Common type for encryption methods which use a random String of hexadecimal characters
|
||||
* and store the salt with the hash itself.
|
||||
*/
|
||||
@Recommendation(Usage.ACCEPTABLE)
|
||||
@HasSalt(SaltType.TEXT) // See saltLength() for length
|
||||
public abstract class HexSaltedMethod implements NewEncrMethod {
|
||||
|
||||
public abstract int getSaltLength();
|
||||
|
||||
@Override
|
||||
public abstract String computeHash(String password, String salt, String name);
|
||||
|
||||
@Override
|
||||
public HashResult computeHash(String password, String name) {
|
||||
String salt = generateSalt();
|
||||
return new HashResult(computeHash(password, salt, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract boolean comparePassword(String hash, String password, String salt, String name);
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateSalt() {
|
||||
return RandomString.generateHex(getSaltLength());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSeparateSalt() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,52 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.security.HashUtils;
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
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 java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class IPB3 implements EncryptionMethod {
|
||||
import static fr.xephi.authme.security.HashUtils.md5;
|
||||
|
||||
private static String getMD5(String message)
|
||||
throws NoSuchAlgorithmException {
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
md5.reset();
|
||||
md5.update(message.getBytes());
|
||||
byte[] digest = md5.digest();
|
||||
return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest));
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
@HasSalt(value = SaltType.TEXT, length = 5)
|
||||
public class IPB3 implements NewEncrMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return md5(md5(salt) + md5(password));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
return getMD5(getMD5(salt) + getMD5(password));
|
||||
public HashResult computeHash(String password, String name) {
|
||||
String salt = generateSalt();
|
||||
return new HashResult(computeHash(password, salt, name), salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
String salt = AuthMe.getInstance().database.getAuth(playerName).getSalt();
|
||||
return hash.equals(computeHash(password, salt, playerName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
||||
return hash.equals(computeHash(password, salt, name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateSalt() {
|
||||
return RandomString.generateHex(5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSeparateSalt() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,26 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.HashUtils;
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
@Recommendation(Usage.ACCEPTABLE)
|
||||
@HasSalt(value = SaltType.TEXT, length = 32)
|
||||
public class JOOMLA implements EncryptionMethod {
|
||||
@Recommendation(Usage.RECOMMENDED)
|
||||
public class JOOMLA extends HexSaltedMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return HashUtils.md5(password + salt) + ":" + salt;
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
return computeHash(password, generateSalt(), null);
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return RandomString.generateHex(32);
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String unusedSalt, String unusedName) {
|
||||
String[] hashParts = hash.split(":");
|
||||
return hashParts.length == 2 && hash.equals(computeHash(password, hashParts[1], null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
String[] hashParts = hash.split(":");
|
||||
if (hashParts.length != 2) {
|
||||
return false;
|
||||
}
|
||||
String salt = hashParts[1];
|
||||
return hash.equals(computeHash(password, salt, null));
|
||||
public int getSaltLength() {
|
||||
return 32;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,21 +6,11 @@ import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
@HasSalt(SaltType.NONE)
|
||||
public class MD5 implements EncryptionMethod {
|
||||
public class MD5 extends UnsaltedMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return computeHash(password, null);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
public String computeHash(String password) {
|
||||
return HashUtils.md5(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return hash.equals(computeHash(password, null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,23 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
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 static fr.xephi.authme.security.HashUtils.md5;
|
||||
|
||||
@Recommendation(Usage.ACCEPTABLE)
|
||||
@HasSalt(value = SaltType.TEXT, length = 16)
|
||||
public class MD5VB implements EncryptionMethod {
|
||||
public class MD5VB extends HexSaltedMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return "$MD5vb$" + salt + "$" + md5(md5(password) + salt);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
return computeHash(password, generateSalt(), null);
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
||||
String[] line = hash.split("\\$");
|
||||
return line.length == 4 && hash.equals(computeHash(password, line[2], name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
String[] line = hash.split("\\$");
|
||||
return line.length == 4 && hash.equals(computeHash(password, line[2], ""));
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return RandomString.generateHex(16);
|
||||
public int getSaltLength() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,34 +1,46 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.security.HashUtils;
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class MYBB implements EncryptionMethod {
|
||||
import static fr.xephi.authme.security.HashUtils.md5;
|
||||
|
||||
private static String getMD5(String message)
|
||||
throws NoSuchAlgorithmException {
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
md5.reset();
|
||||
md5.update(message.getBytes());
|
||||
byte[] digest = md5.digest();
|
||||
return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest));
|
||||
public class MYBB implements NewEncrMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return md5(md5(salt) + md5(password));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
return getMD5(getMD5(salt) + getMD5(password));
|
||||
public HashResult computeHash(String password, String name) {
|
||||
String salt = generateSalt();
|
||||
return new HashResult(computeHash(password, salt, name), salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
String salt = AuthMe.getInstance().database.getAuth(playerName).getSalt();
|
||||
return hash.equals(computeHash(password, salt, playerName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
||||
return hash.equals(computeHash(password, salt, name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateSalt() {
|
||||
return RandomString.generateHex(8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSeparateSalt() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,19 +4,20 @@
|
||||
*/
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* @author stefano
|
||||
*/
|
||||
public class PHPBB implements EncryptionMethod {
|
||||
public class PHPBB extends HexSaltedMethod {
|
||||
|
||||
private static final String itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
public static String md5(String data) {
|
||||
private static String md5(String data) {
|
||||
try {
|
||||
byte[] bytes = data.getBytes("ISO-8859-1");
|
||||
MessageDigest md5er = MessageDigest.getInstance("MD5");
|
||||
@@ -58,7 +59,7 @@ public class PHPBB implements EncryptionMethod {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String phpbb_hash(String password, String salt) {
|
||||
private String phpbb_hash(String password, String salt) {
|
||||
String random_state = salt;
|
||||
StringBuilder random = new StringBuilder();
|
||||
int count = 6;
|
||||
@@ -109,7 +110,7 @@ public class PHPBB implements EncryptionMethod {
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
String _hash_crypt_private(String password, String setting) {
|
||||
private String _hash_crypt_private(String password, String setting) {
|
||||
String output = "*";
|
||||
if (!setting.substring(0, 3).equals("$H$"))
|
||||
return output;
|
||||
@@ -130,21 +131,25 @@ public class PHPBB implements EncryptionMethod {
|
||||
return output;
|
||||
}
|
||||
|
||||
public boolean phpbb_check_hash(String password, String hash) {
|
||||
private boolean phpbb_check_hash(String password, String hash) {
|
||||
if (hash.length() == 34)
|
||||
return _hash_crypt_private(password, hash).equals(hash);
|
||||
else return md5(password).equals(hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return phpbb_hash(password, salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
||||
return phpbb_check_hash(password, hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSaltLength() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.security.HashUtils;
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
@@ -10,27 +14,15 @@ import java.security.InvalidKeyException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class PHPFUSION implements EncryptionMethod {
|
||||
|
||||
private static String getSHA1(String message)
|
||||
throws NoSuchAlgorithmException {
|
||||
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
|
||||
sha1.reset();
|
||||
sha1.update(message.getBytes());
|
||||
byte[] digest = sha1.digest();
|
||||
return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest));
|
||||
}
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
public class PHPFUSION implements NewEncrMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
String digest = null;
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
String algo = "HmacSHA256";
|
||||
String keyString = getSHA1(salt);
|
||||
String keyString = HashUtils.sha1(salt);
|
||||
try {
|
||||
SecretKeySpec key = new SecretKeySpec((keyString).getBytes("UTF-8"), algo);
|
||||
SecretKeySpec key = new SecretKeySpec(keyString.getBytes("UTF-8"), algo);
|
||||
Mac mac = Mac.getInstance(algo);
|
||||
mac.init(key);
|
||||
byte[] bytes = mac.doFinal(password.getBytes("ASCII"));
|
||||
@@ -42,19 +34,38 @@ public class PHPFUSION implements EncryptionMethod {
|
||||
}
|
||||
hash.append(hex);
|
||||
}
|
||||
digest = hash.toString();
|
||||
return hash.toString();
|
||||
} catch (UnsupportedEncodingException | InvalidKeyException | NoSuchAlgorithmException e) {
|
||||
//ingore
|
||||
throw new UnsupportedOperationException("Cannot create PHPFUSION hash for " + name, e);
|
||||
}
|
||||
}
|
||||
|
||||
return digest;
|
||||
@Override
|
||||
public HashResult computeHash(String password, String name) {
|
||||
String salt = generateSalt();
|
||||
return new HashResult(computeHash(password, salt, name), salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
String playerName) {
|
||||
String salt = AuthMe.getInstance().database.getAuth(playerName).getSalt();
|
||||
return hash.equals(computeHash(password, salt, ""));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
||||
return hash.equals(computeHash(password, salt, name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateSalt() {
|
||||
return RandomString.generateHex(12);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSeparateSalt() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,21 +1,11 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class PLAINTEXT implements EncryptionMethod {
|
||||
@Deprecated
|
||||
public class PLAINTEXT extends UnsaltedMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
public String computeHash(String password) {
|
||||
return password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
return hash.equals(password);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,35 +1,16 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import fr.xephi.authme.security.HashUtils;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class ROYALAUTH implements EncryptionMethod {
|
||||
public class ROYALAUTH extends UnsaltedMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
for (int i = 0; i < 25; i++)
|
||||
password = hash(password, salt);
|
||||
public String computeHash(String password) {
|
||||
for (int i = 0; i < 25; i++) {
|
||||
// TODO ljacqu 20151228: HashUtils#sha512 gets a new message digest each time...
|
||||
password = HashUtils.sha512(password);
|
||||
}
|
||||
return password;
|
||||
}
|
||||
|
||||
public String hash(String password, String salt)
|
||||
throws NoSuchAlgorithmException {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-512");
|
||||
md.update(password.getBytes());
|
||||
byte byteData[] = md.digest();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte aByteData : byteData)
|
||||
sb.append(Integer.toString((aByteData & 0xff) + 0x100, 16).substring(1));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
return hash.equalsIgnoreCase(computeHash(password, "", ""));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.security.HashUtils;
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
@@ -12,50 +13,15 @@ import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import static fr.xephi.authme.security.HashUtils.md5;
|
||||
|
||||
@Recommendation(Usage.ACCEPTABLE) // presuming that length is something sensible (>= 8)
|
||||
@HasSalt(value = SaltType.TEXT) // length defined by Settings.saltLength
|
||||
public class SALTED2MD5 implements NewEncrMethod {
|
||||
|
||||
private static String getMD5(String message)
|
||||
throws NoSuchAlgorithmException {
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
md5.reset();
|
||||
md5.update(message.getBytes());
|
||||
byte[] digest = md5.digest();
|
||||
return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest));
|
||||
}
|
||||
public class SALTED2MD5 extends SeparateSaltMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
return getMD5(getMD5(password) + salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashResult computeHash(String password, String name) {
|
||||
try {
|
||||
String salt = generateSalt();
|
||||
return new HashResult(computeHash(password, salt, name), salt);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e); // TODO #358: Remove try-catch clause
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
String salt = AuthMe.getInstance().database.getAuth(playerName).getSalt();
|
||||
return hash.equals(getMD5(getMD5(password) + salt));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
||||
try {
|
||||
return hash.equals(computeHash(password, salt, name));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
// TODO #358: Remove try-catch
|
||||
}
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return md5(md5(password) + salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,9 +29,4 @@ public class SALTED2MD5 implements NewEncrMethod {
|
||||
return RandomString.generateHex(Settings.saltLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSeparateSalt() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,34 +1,20 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.security.HashUtils;
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@Recommendation(Usage.RECOMMENDED)
|
||||
public class SALTEDSHA512 extends SeparateSaltMethod {
|
||||
|
||||
/**
|
||||
*/
|
||||
public class SALTEDSHA512 implements EncryptionMethod {
|
||||
|
||||
private static String getSHA512(String message)
|
||||
throws NoSuchAlgorithmException {
|
||||
MessageDigest sha512 = MessageDigest.getInstance("SHA-512");
|
||||
sha512.reset();
|
||||
sha512.update(message.getBytes());
|
||||
byte[] digest = sha512.digest();
|
||||
return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest));
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return HashUtils.sha512(password + salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
return getSHA512(password + salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
String salt = AuthMe.getInstance().database.getAuth(playerName).getSalt();
|
||||
return hash.equals(computeHash(password, salt, ""));
|
||||
public String generateSalt() {
|
||||
return RandomString.generateHex(32);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,12 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.HashUtils;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
@HasSalt(SaltType.NONE)
|
||||
public class SHA1 implements EncryptionMethod {
|
||||
public class SHA1 extends UnsaltedMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return computeHash(password, null);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
public String computeHash(String password) {
|
||||
return HashUtils.sha1(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return hash.equals(computeHash(password, null));
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,34 +1,27 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
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 static fr.xephi.authme.security.HashUtils.sha256;
|
||||
|
||||
@Recommendation(Usage.RECOMMENDED)
|
||||
@HasSalt(value = SaltType.TEXT, length = 16)
|
||||
public class SHA256 implements EncryptionMethod {
|
||||
public class SHA256 extends HexSaltedMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return "$SHA$" + salt + "$" + sha256(sha256(password) + salt);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
return computeHash(password, generateSalt(), name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
public boolean comparePassword(String hash, String password, String salt, String playerName) {
|
||||
String[] line = hash.split("\\$");
|
||||
return line.length == 4 && hash.equals(computeHash(password, line[2], ""));
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return RandomString.generateHex(16);
|
||||
@Override
|
||||
public int getSaltLength() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,30 +1,12 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.HashUtils;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
@HasSalt(SaltType.NONE)
|
||||
public class SHA512 implements EncryptionMethod {
|
||||
public class SHA512 extends UnsaltedMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return computeHash(password, name);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
public String computeHash(String password) {
|
||||
return HashUtils.sha512(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return hash.equals(computeHash(password, "", ""));
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,11 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.HashUtils;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
@HasSalt(SaltType.USERNAME)
|
||||
public class SMF implements EncryptionMethod {
|
||||
public class SMF extends UsernameSaltMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return computeHash(password, name);
|
||||
public HashResult computeHash(String password, String name) {
|
||||
return new HashResult(HashUtils.sha1(name.toLowerCase() + password));
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
return HashUtils.sha1(name.toLowerCase() + password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return hash.equals(computeHash(password, playerName));
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
/**
|
||||
* Common supertype for encryption methods which store their salt separately from the hash.
|
||||
*/
|
||||
public abstract class SeparateSaltMethod implements NewEncrMethod {
|
||||
|
||||
@Override
|
||||
public abstract String computeHash(String password, String salt, String name);
|
||||
|
||||
@Override
|
||||
public abstract String generateSalt();
|
||||
|
||||
@Override
|
||||
public HashResult computeHash(String password, String name) {
|
||||
String salt = generateSalt();
|
||||
return new HashResult(computeHash(password, salt, name), salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
||||
return hash.equals(computeHash(password, salt, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSeparateSalt() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
/**
|
||||
* Common type for encryption methods which do not use any salt whatsoever.
|
||||
*/
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
@HasSalt(SaltType.NONE)
|
||||
public abstract class UnsaltedMethod implements NewEncrMethod {
|
||||
|
||||
public abstract String computeHash(String password);
|
||||
|
||||
@Override
|
||||
public HashResult computeHash(String password, String name) {
|
||||
return new HashResult(computeHash(password));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return computeHash(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
||||
return hash.equals(computeHash(password));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateSalt() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSeparateSalt() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
/**
|
||||
* Common supertype of encryption methods that use a player's username
|
||||
* (or something based on it) as salt.
|
||||
*/
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
@HasSalt(SaltType.USERNAME)
|
||||
public abstract class UsernameSaltMethod implements NewEncrMethod {
|
||||
|
||||
@Override
|
||||
public abstract HashResult computeHash(String password, String name);
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
||||
return hash.equals(computeHash(password, name).getHash());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return computeHash(password, name).getHash();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateSalt() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSeparateSalt() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +1,19 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import static fr.xephi.authme.security.HashUtils.sha1;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class WBB3 implements EncryptionMethod {
|
||||
public class WBB3 extends SeparateSaltMethod {
|
||||
|
||||
private static String getSHA1(String message)
|
||||
throws NoSuchAlgorithmException {
|
||||
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
|
||||
sha1.reset();
|
||||
sha1.update(message.getBytes());
|
||||
byte[] digest = sha1.digest();
|
||||
return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest));
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return sha1(salt.concat(sha1(salt.concat(sha1(password)))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
return getSHA1(salt.concat(getSHA1(salt.concat(getSHA1(password)))));
|
||||
public String generateSalt() {
|
||||
return RandomString.generateHex(40);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
String salt = AuthMe.getInstance().database.getAuth(playerName).getSalt();
|
||||
return hash.equals(computeHash(password, salt, ""));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,12 @@ import java.security.NoSuchAlgorithmException;
|
||||
public class WBB4 implements EncryptionMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return BCRYPT.getDoubleHash(password, salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return BCRYPT.checkpw(password, hash, 2);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,16 +59,9 @@ package fr.xephi.authme.security.crypts;
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
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 java.util.Arrays;
|
||||
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
@HasSalt(SaltType.NONE)
|
||||
public class WHIRLPOOL implements EncryptionMethod {
|
||||
public class WHIRLPOOL extends UnsaltedMethod {
|
||||
|
||||
/**
|
||||
* The message digest size (in bits)
|
||||
@@ -386,12 +379,7 @@ public class WHIRLPOOL implements EncryptionMethod {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return computeHash(password, null);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
public String computeHash(String password) {
|
||||
byte[] digest = new byte[DIGESTBYTES];
|
||||
NESSIEinit();
|
||||
NESSIEadd(password);
|
||||
@@ -399,9 +387,4 @@ public class WHIRLPOOL implements EncryptionMethod {
|
||||
return display(digest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return hash.equals(computeHash(password, null, null));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,9 @@ import java.util.Arrays;
|
||||
|
||||
@Recommendation(Usage.ACCEPTABLE)
|
||||
@HasSalt(value = SaltType.TEXT, length = 9)
|
||||
public class WORDPRESS implements EncryptionMethod {
|
||||
// Note ljacqu 20151228: Wordpress is actually a salted algorithm but salt generation is handled internally
|
||||
// and isn't exposed to the outside, so we treat it as an unsalted implementation
|
||||
public class WORDPRESS extends UnsaltedMethod {
|
||||
|
||||
private static final String itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
private final SecureRandom randomGen = new SecureRandom();
|
||||
@@ -107,25 +109,16 @@ public class WORDPRESS implements EncryptionMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
public String computeHash(String password) {
|
||||
byte random[] = new byte[6];
|
||||
randomGen.nextBytes(random);
|
||||
return crypt(password, gensaltPrivate(stringToUtf8(new String(random))));
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
return computeHash(password, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
||||
String comparedHash = crypt(password, hash);
|
||||
return comparedHash.equals(hash);
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
// This hash uses a salt, but it is not exposed to the outside
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
@Recommendation(Usage.RECOMMENDED)
|
||||
@HasSalt(value = SaltType.TEXT, length = 12)
|
||||
public class XAUTH implements EncryptionMethod {
|
||||
public class XAUTH extends HexSaltedMethod {
|
||||
|
||||
public static String getWhirlpool(String message) {
|
||||
private static String getWhirlpool(String message) {
|
||||
WHIRLPOOL w = new WHIRLPOOL();
|
||||
byte[] digest = new byte[WHIRLPOOL.DIGESTBYTES];
|
||||
w.NESSIEinit();
|
||||
@@ -26,19 +22,16 @@ public class XAUTH implements EncryptionMethod {
|
||||
return hash.substring(0, saltPos) + salt + hash.substring(saltPos);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
return computeHash(password, generateSalt(), null);
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String salt, String playerName) {
|
||||
int saltPos = (password.length() >= hash.length() ? hash.length() - 1 : password.length());
|
||||
String saltFromHash = hash.substring(saltPos, saltPos + 12);
|
||||
return hash.equals(computeHash(password, saltFromHash, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
int saltPos = (password.length() >= hash.length() ? hash.length() - 1 : password.length());
|
||||
String salt = hash.substring(saltPos, saltPos + 12);
|
||||
return hash.equals(computeHash(password, salt, ""));
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return RandomString.generateHex(12);
|
||||
public int getSaltLength() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,23 +11,37 @@ import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class XF implements EncryptionMethod {
|
||||
public class XF implements NewEncrMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return getSha256(getSha256(password) + regmatch("\"salt\";.:..:\"(.*)\";.:.:\"hashFunc\"", salt));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
public HashResult computeHash(String password, String name) {
|
||||
String salt = generateSalt();
|
||||
return new HashResult(computeHash(password, salt, null), salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
String salt = AuthMe.getInstance().database.getAuth(playerName).getSalt();
|
||||
return hash.equals(regmatch("\"hash\";.:..:\"(.*)\";.:.:\"salt\"", salt));
|
||||
}
|
||||
|
||||
private String getSha256(String password) throws NoSuchAlgorithmException {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
public boolean comparePassword(String hash, String password, String salt, String name) {
|
||||
return hash.equals(regmatch("\"hash\";.:..:\"(.*)\";.:.:\"salt\"", salt));
|
||||
}
|
||||
|
||||
private String getSha256(String password) {
|
||||
MessageDigest md = null;
|
||||
try {
|
||||
md = MessageDigest.getInstance("SHA-256");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// TODO #358: Handle exception properly
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
md.update(password.getBytes());
|
||||
byte byteData[] = md.digest();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -45,6 +59,17 @@ public class XF implements EncryptionMethod {
|
||||
return hexString.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateSalt() {
|
||||
// TODO #369: Find out what kind of salt format XF uses
|
||||
return "";
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
Reference in New Issue
Block a user