From 600c70ad9f8277a07181ea5b4181ffe439dd252c Mon Sep 17 00:00:00 2001 From: DNx5 Date: Tue, 9 Feb 2016 04:48:12 +0700 Subject: [PATCH 1/3] Create new class for IPB4 encryption method. --- .../security/crypts/description/IPB4.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/main/java/fr/xephi/authme/security/crypts/description/IPB4.java diff --git a/src/main/java/fr/xephi/authme/security/crypts/description/IPB4.java b/src/main/java/fr/xephi/authme/security/crypts/description/IPB4.java new file mode 100644 index 000000000..c5b707a56 --- /dev/null +++ b/src/main/java/fr/xephi/authme/security/crypts/description/IPB4.java @@ -0,0 +1,35 @@ +package fr.xephi.authme.security.crypts.description; + +import fr.xephi.authme.security.crypts.EncryptionMethod; +import fr.xephi.authme.security.crypts.HashedPassword; + + +@Recommendation(Usage.DOES_NOT_WORK) +@HasSalt(value = SaltType.TEXT) +public class IPB4 implements EncryptionMethod { + + @Override + public String computeHash(String password, String salt, String name) { + return null; + } + + @Override + public HashedPassword computeHash(String password, String name) { + return null; + } + + @Override + public boolean comparePassword(String password, HashedPassword hash, String name) { + return false; + } + + @Override + public String generateSalt() { + return null; + } + + @Override + public boolean hasSeparateSalt() { + return false; + } +} From 9959c0f7d5b7ba30795d278bd13d5bb42c1397dc Mon Sep 17 00:00:00 2001 From: DNx5 Date: Tue, 9 Feb 2016 05:04:29 +0700 Subject: [PATCH 2/3] Cleanup BCryptService class --- .../authme/security/crypts/BCryptService.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/main/java/fr/xephi/authme/security/crypts/BCryptService.java b/src/main/java/fr/xephi/authme/security/crypts/BCryptService.java index 94ed32c3c..194ea7b63 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/BCryptService.java +++ b/src/main/java/fr/xephi/authme/security/crypts/BCryptService.java @@ -388,7 +388,7 @@ public class BCryptService { private static String encode_base64(byte d[], int len) throws IllegalArgumentException { int off = 0; - StringBuffer rs = new StringBuffer(); + StringBuilder rs = new StringBuilder(); int c1, c2; if (len <= 0 || len > d.length) @@ -441,7 +441,7 @@ public class BCryptService { */ private static byte[] decode_base64(String s, int maxolen) throws IllegalArgumentException { - StringBuffer rs = new StringBuffer(); + StringBuilder rs = new StringBuilder(); int off = 0, slen = s.length(), olen = 0; byte ret[]; byte c1, c2, c3, c4, o; @@ -486,7 +486,7 @@ public class BCryptService { * @param lr an array containing the two 32-bit half blocks * @param off the position in the array of the blocks */ - private final void encipher(int lr[], int off) { + private void encipher(int lr[], int off) { int i, n, l = lr[off], r = lr[off + 1]; l ^= P[0]; @@ -534,8 +534,8 @@ public class BCryptService { * Initialise the Blowfish key schedule */ private void init_key() { - P = (int[])P_orig.clone(); - S = (int[])S_orig.clone(); + P = P_orig.clone(); + S = S_orig.clone(); } /** @@ -653,8 +653,8 @@ public class BCryptService { String real_salt; byte passwordb[], saltb[], hashed[]; char minor = (char)0; - int rounds, off = 0; - StringBuffer rs = new StringBuffer(); + int rounds, off; + StringBuilder rs = new StringBuilder(); if (salt.charAt(0) != '$' || salt.charAt(1) != '2') throw new IllegalArgumentException ("Invalid salt version"); @@ -684,8 +684,7 @@ public class BCryptService { saltb = decode_base64(real_salt, BCRYPT_SALT_LEN); B = new BCryptService(); - hashed = B.crypt_raw(passwordb, saltb, rounds, - (int[])bf_crypt_ciphertext.clone()); + hashed = B.crypt_raw(passwordb, saltb, rounds, bf_crypt_ciphertext.clone()); rs.append("$2"); if (minor >= 'a') @@ -714,7 +713,7 @@ public class BCryptService { * @return an encoded salt value */ public static String gensalt(int log_rounds, SecureRandom random) { - StringBuffer rs = new StringBuffer(); + StringBuilder rs = new StringBuilder(); byte rnd[] = new byte[BCRYPT_SALT_LEN]; random.nextBytes(rnd); From 8e38384a0d7b382fad5864e228f4fbb7df5f2696 Mon Sep 17 00:00:00 2001 From: DNx5 Date: Tue, 9 Feb 2016 05:58:59 +0700 Subject: [PATCH 3/3] Implement the encryption method and test unit. --- .../security/crypts/description/IPB4.java | 29 ++++++++++++++++--- .../authme/security/crypts/IPB4Test.java | 22 ++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 src/test/java/fr/xephi/authme/security/crypts/IPB4Test.java diff --git a/src/main/java/fr/xephi/authme/security/crypts/description/IPB4.java b/src/main/java/fr/xephi/authme/security/crypts/description/IPB4.java index c5b707a56..267d5e090 100644 --- a/src/main/java/fr/xephi/authme/security/crypts/description/IPB4.java +++ b/src/main/java/fr/xephi/authme/security/crypts/description/IPB4.java @@ -1,35 +1,56 @@ package fr.xephi.authme.security.crypts.description; +import fr.xephi.authme.ConsoleLogger; +import fr.xephi.authme.security.crypts.BCryptService; import fr.xephi.authme.security.crypts.EncryptionMethod; import fr.xephi.authme.security.crypts.HashedPassword; +import fr.xephi.authme.util.StringUtils; + +import java.security.SecureRandom; @Recommendation(Usage.DOES_NOT_WORK) @HasSalt(value = SaltType.TEXT) public class IPB4 implements EncryptionMethod { + SecureRandom random = new SecureRandom(); @Override public String computeHash(String password, String salt, String name) { - return null; + return BCryptService.hashpw(password, "$2a$13$" + salt); } @Override public HashedPassword computeHash(String password, String name) { - return null; + String salt = generateSalt(); + return new HashedPassword(computeHash(password, salt, name), salt); } @Override public boolean comparePassword(String password, HashedPassword hash, String name) { + try { + return hash.getHash().length() > 3 && BCryptService.checkpw(password, hash.getHash()); + } catch (IllegalArgumentException e) { + ConsoleLogger.showError("Bcrypt checkpw() returned " + StringUtils.formatException(e)); + } return false; } @Override public String generateSalt() { - return null; + StringBuilder sb = new StringBuilder(22); + for (int i = 0; i < 22; i++) { + char chr; + do { + chr = (char) (random.nextInt((122 - 48) + 1) + 48); + } + while ((chr >= 58 && chr <= 64) || (chr >= 91 && chr <= 96)); + sb.append(chr); + } + return sb.toString(); } @Override public boolean hasSeparateSalt() { - return false; + return true; } } diff --git a/src/test/java/fr/xephi/authme/security/crypts/IPB4Test.java b/src/test/java/fr/xephi/authme/security/crypts/IPB4Test.java new file mode 100644 index 000000000..fc9f9f923 --- /dev/null +++ b/src/test/java/fr/xephi/authme/security/crypts/IPB4Test.java @@ -0,0 +1,22 @@ +package fr.xephi.authme.security.crypts; + +import fr.xephi.authme.security.crypts.description.IPB4; +import fr.xephi.authme.util.WrapperMock; +import org.junit.BeforeClass; + +public class IPB4Test extends AbstractEncryptionMethodTest { + + @BeforeClass + public static void setUpSettings() { + WrapperMock.createInstance(); + } + + public IPB4Test() { + super(new IPB4(), + new HashedPassword("$2a$13$leEvXu77OIwPwNvtZIJvaeAx8EItGHuR3nIlq8416g0gXeJaQdrr2", "leEvXu77OIwPwNvtZIJval"), //password + new HashedPassword("$2a$13$xyTTP9zhQQtRRKIJPv5AuuOGJ6Ni9FLbDhcuIAcPjt3XzCxIWe3Uu", "xyTTP9zhQQtRRKIJPv5Au3"), //PassWord1 + new HashedPassword("$2a$13$rGBrqErm9DZyzbxIGHlgf.xfA15/4d5Ay/TK.3y9lG3AljcoG9Lsi", "rGBrqErm9DZyzbxIGHlgfN"), //&^%te$t?Pw@_ + new HashedPassword("$2a$13$18dKXZLoGpeHHL81edM9HuipiUcMjn5VDJHlxwRUMRXfJ1b.ZQrJ.", "18dKXZLoGpeHHL81edM9H6")); //âË_3(íù* + } + +}