#358 Add future interface methods, remove exception throwing
- Create Utils class for a common implementation of md5/sha1 - Create "foolproof" way of getting the MessageDigest for md5 etc. (MessageDigestAlgorithm enum) - Create description annotations to annotate algorithms with usage recommendation and salt type
This commit is contained in:
@@ -13,8 +13,12 @@
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
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 java.io.UnsupportedEncodingException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
@@ -59,11 +63,13 @@ 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 {
|
||||
|
||||
// BCrypt parameters
|
||||
private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10;
|
||||
private static final int BCRYPT_SALT_LEN = 16;
|
||||
protected static final int BCRYPT_SALT_LEN = 16;
|
||||
|
||||
// Blowfish parameters
|
||||
private static final int BLOWFISH_NUM_ROUNDS = 16;
|
||||
@@ -508,14 +514,20 @@ public class BCRYPT implements EncryptionMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return hashpw(password, salt);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
return hashpw(password, generateSalt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return checkpw(password, hash);
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return BCRYPT.gensalt();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,22 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
/**
|
||||
*/
|
||||
@Recommendation(Usage.DOES_NOT_WORK)
|
||||
public class BCRYPT2Y implements EncryptionMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
if (salt.length() == 22)
|
||||
salt = "$2y$10$" + salt;
|
||||
return (BCRYPT.hashpw(password, salt));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
String ok = hash.substring(0, 29);
|
||||
if (ok.length() != 29)
|
||||
return false;
|
||||
return hash.equals(computeHash(password, ok, playerName));
|
||||
return ok.length() == 29 && hash.equals(computeHash(password, ok, playerName));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.HashUtils;
|
||||
import fr.xephi.authme.security.MessageDigestAlgorithm;
|
||||
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.HasSalt;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
*/
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
@HasSalt(SaltType.USERNAME)
|
||||
public class CRAZYCRYPT1 implements EncryptionMethod {
|
||||
|
||||
private static final char[] CRYPTCHARS = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
protected final Charset charset = Charset.forName("UTF-8");
|
||||
private static final char[] CRYPTCHARS =
|
||||
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
private final Charset charset = Charset.forName("UTF-8");
|
||||
|
||||
|
||||
public static String byteArrayToHexString(final byte... args) {
|
||||
private static String byteArrayToHexString(final byte... args) {
|
||||
final char[] chars = new char[args.length * 2];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
chars[i * 2] = CRYPTCHARS[(args[i] >> 4) & 0xF];
|
||||
@@ -22,21 +28,23 @@ public class CRAZYCRYPT1 implements EncryptionMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return computeHash(password, name);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
final String text = "ÜÄaeut//&/=I " + password + "7421€547" + name + "__+IÄIH§%NK " + password;
|
||||
try {
|
||||
final MessageDigest md = MessageDigest.getInstance("SHA-512");
|
||||
md.update(text.getBytes(charset), 0, text.length());
|
||||
return byteArrayToHexString(md.digest());
|
||||
} catch (final NoSuchAlgorithmException e) {
|
||||
return null;
|
||||
}
|
||||
final MessageDigest md = HashUtils.getDigest(MessageDigestAlgorithm.SHA512);
|
||||
md.update(text.getBytes(charset), 0, text.length());
|
||||
return byteArrayToHexString(md.digest());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
return hash.equals(computeHash(password, null, playerName));
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return hash.equals(computeHash(password, playerName));
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
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.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
*/
|
||||
@Recommendation(Usage.DOES_NOT_WORK)
|
||||
public class CryptPBKDF2 implements EncryptionMethod {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
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 fr.xephi.authme.security.pbkdf2.PBKDF2Engine;
|
||||
import fr.xephi.authme.security.pbkdf2.PBKDF2Parameters;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
*/
|
||||
@Recommendation(Usage.OK)
|
||||
@HasSalt(value = SaltType.TEXT, length = 12)
|
||||
public class CryptPBKDF2Django 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$15000$" + salt + "$";
|
||||
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 15000);
|
||||
PBKDF2Engine engine = new PBKDF2Engine(params);
|
||||
@@ -20,9 +23,12 @@ 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) throws NoSuchAlgorithmException {
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
String[] line = hash.split("\\$");
|
||||
String salt = line[2];
|
||||
byte[] derivedKey = DatatypeConverter.parseBase64Binary(line[3]);
|
||||
@@ -31,4 +37,8 @@ public class CryptPBKDF2Django implements EncryptionMethod {
|
||||
return engine.verifyKey(password);
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return HashUtils.generateSalt(12);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,32 +1,31 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
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 DOUBLEMD5 implements EncryptionMethod {
|
||||
|
||||
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));
|
||||
@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 String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
return getMD5(getMD5(password));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
return hash.equals(computeHash(password, "", ""));
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return hash.equals(computeHash(password, null, null));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,4 +32,8 @@ public interface EncryptionMethod {
|
||||
boolean comparePassword(String hash, String password, String playerName)
|
||||
throws NoSuchAlgorithmException;
|
||||
|
||||
// String generateSalt();
|
||||
|
||||
// String computeHash(String password, String name);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,32 +1,35 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
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.OK)
|
||||
@HasSalt(value = SaltType.TEXT, length = 32)
|
||||
public class JOOMLA implements EncryptionMethod {
|
||||
|
||||
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));
|
||||
@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 HashUtils.generateSalt(32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
return getMD5(password + salt) + ":" + salt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
String salt = hash.split(":")[1];
|
||||
return hash.equals(getMD5(password + salt) + ":" + salt);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,26 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
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 MD5 implements EncryptionMethod {
|
||||
|
||||
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));
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return computeHash(password, null);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
return HashUtils.md5(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
return getMD5(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
return hash.equals(computeHash(password, "", ""));
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return hash.equals(computeHash(password, null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,34 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
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.OK)
|
||||
@HasSalt(value = SaltType.TEXT, length = 16)
|
||||
public class MD5VB implements EncryptionMethod {
|
||||
|
||||
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));
|
||||
@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 String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
return "$MD5vb$" + salt + "$" + getMD5(getMD5(password) + salt);
|
||||
}
|
||||
|
||||
@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("\\$");
|
||||
return hash.equals(computeHash(password, line[2], ""));
|
||||
return line.length == 4 && hash.equals(computeHash(password, line[2], ""));
|
||||
}
|
||||
|
||||
public String generateSalt() {
|
||||
return HashUtils.generateSalt(16);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,32 +1,31 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
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 {
|
||||
|
||||
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 computeHash(password, null);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
return HashUtils.sha1(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
return getSHA1(password);
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return hash.equals(computeHash(password, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
return hash.equals(computeHash(password, "", ""));
|
||||
public String generateSalt() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,11 +59,15 @@ package fr.xephi.authme.security.crypts;
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
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 {
|
||||
|
||||
/**
|
||||
@@ -383,8 +387,11 @@ public class WHIRLPOOL implements EncryptionMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
return computeHash(password, null);
|
||||
}
|
||||
|
||||
public String computeHash(String password, String name) {
|
||||
byte[] digest = new byte[DIGESTBYTES];
|
||||
NESSIEinit();
|
||||
NESSIEadd(password);
|
||||
@@ -393,8 +400,8 @@ public class WHIRLPOOL implements EncryptionMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String hash, String password,
|
||||
String playerName) throws NoSuchAlgorithmException {
|
||||
return hash.equals(computeHash(password, "", ""));
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
return hash.equals(computeHash(password, null, null));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
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;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
*/
|
||||
@Recommendation(Usage.OK)
|
||||
@HasSalt(value = SaltType.TEXT, length = 9)
|
||||
public class WORDPRESS implements EncryptionMethod {
|
||||
|
||||
private static final String itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
@@ -102,18 +107,25 @@ public class WORDPRESS implements EncryptionMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
byte random[] = new byte[6];
|
||||
this.randomGen.nextBytes(random);
|
||||
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) throws NoSuchAlgorithmException {
|
||||
public boolean comparePassword(String hash, String password, String playerName) {
|
||||
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,9 +1,13 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
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.RECOMMENDED)
|
||||
@HasSalt(value = SaltType.TEXT, length = 12)
|
||||
public class XAUTH implements EncryptionMethod {
|
||||
|
||||
public static String getWhirlpool(String message) {
|
||||
@@ -16,19 +20,25 @@ public class XAUTH implements EncryptionMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name)
|
||||
throws NoSuchAlgorithmException {
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
String hash = getWhirlpool(salt + password).toLowerCase();
|
||||
int saltPos = (password.length() >= hash.length() ? hash.length() - 1 : password.length());
|
||||
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 playerName) throws NoSuchAlgorithmException {
|
||||
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 HashUtils.generateSalt(12);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package fr.xephi.authme.security.crypts.description;
|
||||
|
||||
/**
|
||||
* Describes the type of salt the encryption algorithm uses. This is purely for documentation
|
||||
* purposes and is ignored by the code.
|
||||
*/
|
||||
public @interface HasSalt {
|
||||
|
||||
SaltType value();
|
||||
|
||||
int length() default 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package fr.xephi.authme.security.crypts.description;
|
||||
|
||||
/**
|
||||
* Annotation to mark a hash algorithm with the usage recommendation, see {@link Usage}.
|
||||
*/
|
||||
public @interface Recommendation {
|
||||
|
||||
Usage value();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package fr.xephi.authme.security.crypts.description;
|
||||
|
||||
/**
|
||||
* The type of salt used by an encryption algorithms.
|
||||
*/
|
||||
public enum SaltType {
|
||||
|
||||
/** Random, newly generated text. */
|
||||
TEXT,
|
||||
|
||||
/** The username, including variations or repetitions. */
|
||||
USERNAME,
|
||||
|
||||
/** No salt. */
|
||||
NONE
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package fr.xephi.authme.security.crypts.description;
|
||||
|
||||
/**
|
||||
* Usage recommendation that can be provided for a hash algorithm.
|
||||
*/
|
||||
public enum Usage {
|
||||
|
||||
/** The hash algorithm appears to be cryptographically secure and is one of the algorithms recommended by AuthMe. */
|
||||
RECOMMENDED,
|
||||
|
||||
/** There are safer algorithms that can be chosen but using the algorithm is generally OK. */
|
||||
OK,
|
||||
|
||||
/** Hash algorithm is not recommended to be used. Use only if required by another system. */
|
||||
DO_NOT_USE,
|
||||
|
||||
/** The algorithm does not work properly; do not use. */
|
||||
DOES_NOT_WORK
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user