diff --git a/pom.xml b/pom.xml
index 4d1a8ee..059c43e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,14 +28,13 @@
commons-codec
commons-codec
1.6
-
-
+
- com.lambdaworks
- scrypt
- 1.4.0
-
-
+ commons-net
+ commons-net
+ 3.3
+
+
org.apache.logging.log4j
log4j-api
@@ -58,20 +57,24 @@
javaee-api
6.0
-
-
+
com.enterprisedt
edtFTPj
1.5.3
-
+
- commons-net
- commons-net
- 3.3
-
-
+ com.lambdaworks
+ scrypt
+ 1.4.0
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+ 1.52
+
+
de.muehlencord.shared
shared-util
diff --git a/security/pom.xml b/security/pom.xml
index 73f5997..c23b5a7 100644
--- a/security/pom.xml
+++ b/security/pom.xml
@@ -27,8 +27,7 @@
junit
junit
-
-
+
commons-codec
commons-codec
@@ -42,7 +41,10 @@
org.apache.logging.log4j
log4j-api
-
+
+ org.bouncycastle
+ bcprov-jdk15on
+
com.lambdaworks
scrypt
diff --git a/security/src/main/java/de/muehlencord/shared/security/OldPasswordUtil.java b/security/src/main/java/de/muehlencord/shared/security/OldPasswordUtil.java
new file mode 100644
index 0000000..4743bfb
--- /dev/null
+++ b/security/src/main/java/de/muehlencord/shared/security/OldPasswordUtil.java
@@ -0,0 +1,237 @@
+package de.muehlencord.shared.security;
+
+import static com.lambdaworks.crypto.SCryptUtil.check;
+import static com.lambdaworks.crypto.SCryptUtil.scrypt;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import org.apache.commons.codec.binary.Base64;
+/**
+ *
+ * @author joern@muehlencord.de
+ */
+public abstract class OldPasswordUtil {
+
+ /** logging object */
+ // private final static Logger LOGGER = Logger.getLogger(PasswordUtil.class);
+
+ /** SCrypt CPU cost parameter */
+ private final static int scryptCpuCostParameter = 16384;
+ /** SCrypt memory cost parameter */
+ private final static int scryptMemCostParameter = 8;
+ /** SCrypt paralelization parameter */
+ private final static int scryptParallelizationParameter = 1;
+
+
+ /**
+ * returns password (pos 0) and the salt (pos 1) of given plaintext password. Both strings are base64 encoded
+ *
+ * @param plainTextPassword he
+ * @param saltLength the length of the salt to use
+ * @return the password (pos 0) and the salt (pos 1) of given plaintext password. Both strings are base64 encoded
+ *
+ * @throws de.muehlencord.shared.security.SecurityException if any error occurs during the password generation
+ */
+ public static String[] getMD5Password(final String plainTextPassword, final int saltLength) throws SecurityException {
+ byte[] unHashedPassword = getBase64MD5HashedPassword(plainTextPassword);
+ byte[] salt = createSalt(saltLength);
+ byte[] hashedPassword = hashPasswordWithSalt(unHashedPassword, salt);
+
+ // test
+ String saltStr = base64Encode(salt);
+ byte[] salt2 = base64Decode(saltStr);
+ if (!Arrays.equals(salt, salt2)) {
+ throw new SecurityException("Salt conversion failed");
+ }
+
+
+ String[] returnValue = new String[2];
+ returnValue[0] = base64Encode(hashedPassword);
+ returnValue[1] = base64Encode(salt);
+
+ return returnValue;
+ }
+
+ /**
+ * Checks if the given password (plain text) matches the given crypted password. The crypted password is hashed with the given salt. Both strings, crypted
+ * password and salt, have to be base64 encoded
+ *
+ * @param plainTextPassword the plaintext password to compare to
+ * @param cryptedPasswordStr the crypted password to compare to
+ * @param saltStr the salt needed to hash the plaintext password with to get the correct crypted password if both passwords match
+ * @return true, if and only if the encryption of plainTextPassword (hashed with saltStr) equals to cryptedPasswordStr
+ *
+ * @throws de.muehlencord.shared.security.SecurityException if any error occures during the check
+ */
+ public static boolean checkPassword(String plainTextPassword, String cryptedPasswordStr, String saltStr) throws SecurityException {
+ byte[] salt = base64Decode(saltStr);
+ byte[] newPassword = getBase64MD5HashedPassword(plainTextPassword);
+ byte[] newHashedPassword = hashPasswordWithSalt(newPassword, salt);
+ byte[] crytepdPassword = base64Decode(cryptedPasswordStr);
+ return Arrays.equals(crytepdPassword, newHashedPassword);
+ }
+
+ /**
+ * returns a new salt as a string
+ *
+ * @param saltLength the length of the salt
+ * @return a new salt as a string (base64 encoded)
+ *
+ * @throws SecurityException if the creation of the salt fails
+ */
+ public static String createSaltString(int saltLength) throws SecurityException {
+ byte[] saltByteArray = createSalt(saltLength);
+ String saltString = base64Encode(saltByteArray);
+ if (saltString.length() > saltLength) {
+ return saltString.substring(0, saltLength);
+ } else {
+ return saltString;
+ }
+ }
+
+ /** returns a random string with total length starting with prefix string
+ *
+ * @param prefix the prefix to start the string with
+ * @param length the maximum length of the string (including prefix)
+ * @return a random string
+ *
+ * @throws SecurityException if the random string could not be computed
+ */
+ public static String getRandomString(final String prefix, int length) throws SecurityException {
+ String usedPrefix = (prefix == null ? "" : prefix);
+
+ int idLength = length - usedPrefix.length();
+ return usedPrefix + createSaltString(idLength);
+ }
+
+
+ /* *** private methods *** */
+ /**
+ * creates a salt and returns the value as byte[]
+ *
+ * @param saltLength the length the salt string should have
+ * @return the generated salt as byte[]
+ *
+ * @throws SecurityException if the salt creation fails
+ */
+ private static byte[] createSalt(int saltLength) throws SecurityException {
+ try {
+ SecureRandom sha1SecureRandom = SecureRandom.getInstance("SHA1PRNG");
+
+ byte salt[] = new byte[saltLength];
+ synchronized (sha1SecureRandom) {
+ sha1SecureRandom.nextBytes(salt);
+ }
+ return salt;
+ } catch (Exception ex) {
+ throw new SecurityException("Cannot created salt", ex);
+ }
+ }
+
+ /**
+ * hashes the given password (md5 hashed, base64 coded) with the given salt
+ *
+ * @param text the text to salt
+ * @param salt the salt to use
+ * @return the input text salted with password
+ *
+ * @throws SecurityException
+ */
+ private static byte[] hashPasswordWithSalt(byte text[], byte salt[]) throws SecurityException {
+ try {
+ MessageDigest sha1Algorithm = MessageDigest.getInstance("SHA-1");
+ byte[] digest;
+ synchronized (sha1Algorithm) {
+ sha1Algorithm.reset();
+ sha1Algorithm.update(salt);
+ digest = sha1Algorithm.digest(text);
+ }
+ return digest;
+ } catch (NoSuchAlgorithmException ex) {
+ throw new SecurityException("Cannot hash password with salt", ex);
+ }
+ }
+
+ /**
+ * returns the given password as md5 without appliying salt
+ *
+ * @param plainTextPassword the password to convert
+ * @return the given password as md5 without appliying salt
+ *
+ * @throws SecurityException if the passwor cannot be converted
+ */
+ private static byte[] getBase64MD5HashedPassword(final String plainTextPassword) throws SecurityException {
+ try {
+ MessageDigest algorithm = MessageDigest.getInstance("MD5");
+ algorithm.reset();
+ algorithm.update(plainTextPassword.getBytes());
+ byte[] messageDigest = algorithm.digest();
+ StringBuilder buf = new StringBuilder();
+ for (int i = 0; i < messageDigest.length; i++) {
+ int halfbyte = (messageDigest[i] >>> 4) & 0x0F;
+ int twoHalfs = 0;
+ do {
+ if ((0 <= halfbyte) && (halfbyte <= 9)) {
+ buf.append((char) ('0' + halfbyte));
+ } else {
+ buf.append((char) ('a' + (halfbyte - 10)));
+ }
+ halfbyte = messageDigest[i] & 0x0F;
+ } while (twoHalfs++ < 1);
+ }
+
+ // take password and hash with salt
+ byte[] unHashedPassword = base64Decode(buf.toString());
+
+ return unHashedPassword;
+ } catch (Exception ex) {
+ throw new SecurityException("Cannot created password", ex);
+ }
+ }
+
+ /**
+ * returns the plain byte[] as base64 coded string
+ *
+ * @param data the data to convert
+ * @return the plain byte[] as base64 coded string
+ */
+ private static String base64Encode(final byte[] data) {
+ Base64 encoder = new Base64();
+ byte[] result = encoder.encode(data);
+ return new String(result);
+ }
+
+ /**
+ * returns the given base64 coded string as decoded byte[]
+ *
+ * @param data the string to convert
+ * @return the given base64 coded string as decoded byte[]
+ */
+ private static byte[] base64Decode(final String data) {
+ Base64 decoder = new Base64();
+ return decoder.decode(data.getBytes());
+ }
+
+
+ /**
+ * returns the crypted parameter string for the given plain text password
+ *
+ * @param plainPassword the plain text password to crypt
+ * @return the crypted password string
+ */
+ public static String getScryptHash(String plainPassword) {
+ return scrypt(plainPassword, scryptCpuCostParameter, scryptMemCostParameter, scryptParallelizationParameter);
+ }
+
+ /**
+ * returns true, if the given plainPassword re-encrypted matches the given crypted password
+ *
+ * @param plainPassword the plain password to validate
+ * @param hashedPassword the encrypted password to validate against
+ * @return true, if the encrypted string of the given plain password matches the provided crypted password
+ */
+ public static boolean validateScryptHash(String plainPassword, String hashedPassword) {
+ return check(plainPassword, hashedPassword);
+ }
+}
diff --git a/security/src/main/java/de/muehlencord/shared/security/PasswordUtil.java b/security/src/main/java/de/muehlencord/shared/security/PasswordUtil.java
index aa37795..18b4c13 100644
--- a/security/src/main/java/de/muehlencord/shared/security/PasswordUtil.java
+++ b/security/src/main/java/de/muehlencord/shared/security/PasswordUtil.java
@@ -1,237 +1,69 @@
-package de.muehlencord.shared.security;
-
-import static com.lambdaworks.crypto.SCryptUtil.check;
-import static com.lambdaworks.crypto.SCryptUtil.scrypt;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.Arrays;
-import org.apache.commons.codec.binary.Base64;
-/**
- *
- * @author joern@muehlencord.de
- */
-public abstract class PasswordUtil {
-
- /** logging object */
- // private final static Logger LOGGER = Logger.getLogger(PasswordUtil.class);
-
- /** SCrypt CPU cost parameter */
- private final static int scryptCpuCostParameter = 16384;
- /** SCrypt memory cost parameter */
- private final static int scryptMemCostParameter = 8;
- /** SCrypt paralelization parameter */
- private final static int scryptParallelizationParameter = 1;
-
-
- /**
- * returns password (pos 0) and the salt (pos 1) of given plaintext password. Both strings are base64 encoded
- *
- * @param plainTextPassword he
- * @param saltLength the length of the salt to use
- * @return the password (pos 0) and the salt (pos 1) of given plaintext password. Both strings are base64 encoded
- *
- * @throws de.muehlencord.shared.security.SecurityException if any error occurs during the password generation
- */
- public static String[] getMD5Password(final String plainTextPassword, final int saltLength) throws SecurityException {
- byte[] unHashedPassword = getBase64MD5HashedPassword(plainTextPassword);
- byte[] salt = createSalt(saltLength);
- byte[] hashedPassword = hashPasswordWithSalt(unHashedPassword, salt);
-
- // test
- String saltStr = base64Encode(salt);
- byte[] salt2 = base64Decode(saltStr);
- if (!Arrays.equals(salt, salt2)) {
- throw new SecurityException("Salt conversion failed");
- }
-
-
- String[] returnValue = new String[2];
- returnValue[0] = base64Encode(hashedPassword);
- returnValue[1] = base64Encode(salt);
-
- return returnValue;
- }
-
- /**
- * Checks if the given password (plain text) matches the given crypted password. The crypted password is hashed with the given salt. Both strings, crypted
- * password and salt, have to be base64 encoded
- *
- * @param plainTextPassword the plaintext password to compare to
- * @param cryptedPasswordStr the crypted password to compare to
- * @param saltStr the salt needed to hash the plaintext password with to get the correct crypted password if both passwords match
- * @return true, if and only if the encryption of plainTextPassword (hashed with saltStr) equals to cryptedPasswordStr
- *
- * @throws de.muehlencord.shared.security.SecurityException if any error occures during the check
- */
- public static boolean checkPassword(String plainTextPassword, String cryptedPasswordStr, String saltStr) throws SecurityException {
- byte[] salt = base64Decode(saltStr);
- byte[] newPassword = getBase64MD5HashedPassword(plainTextPassword);
- byte[] newHashedPassword = hashPasswordWithSalt(newPassword, salt);
- byte[] crytepdPassword = base64Decode(cryptedPasswordStr);
- return Arrays.equals(crytepdPassword, newHashedPassword);
- }
-
- /**
- * returns a new salt as a string
- *
- * @param saltLength the length of the salt
- * @return a new salt as a string (base64 encoded)
- *
- * @throws SecurityException if the creation of the salt fails
- */
- public static String createSaltString(int saltLength) throws SecurityException {
- byte[] saltByteArray = createSalt(saltLength);
- String saltString = base64Encode(saltByteArray);
- if (saltString.length() > saltLength) {
- return saltString.substring(0, saltLength);
- } else {
- return saltString;
- }
- }
-
- /** returns a random string with total length starting with prefix string
- *
- * @param prefix the prefix to start the string with
- * @param length the maximum length of the string (including prefix)
- * @return a random string
- *
- * @throws SecurityException if the random string could not be computed
- */
- public static String getRandomString(final String prefix, int length) throws SecurityException {
- String usedPrefix = (prefix == null ? "" : prefix);
-
- int idLength = length - usedPrefix.length();
- return usedPrefix + createSaltString(idLength);
- }
-
-
- /* *** private methods *** */
- /**
- * creates a salt and returns the value as byte[]
- *
- * @param saltLength the length the salt string should have
- * @return the generated salt as byte[]
- *
- * @throws SecurityException if the salt creation fails
- */
- private static byte[] createSalt(int saltLength) throws SecurityException {
- try {
- SecureRandom sha1SecureRandom = SecureRandom.getInstance("SHA1PRNG");
-
- byte salt[] = new byte[saltLength];
- synchronized (sha1SecureRandom) {
- sha1SecureRandom.nextBytes(salt);
- }
- return salt;
- } catch (Exception ex) {
- throw new SecurityException("Cannot created salt", ex);
- }
- }
-
- /**
- * hashes the given password (md5 hashed, base64 coded) with the given salt
- *
- * @param text the text to salt
- * @param salt the salt to use
- * @return the input text salted with password
- *
- * @throws SecurityException
- */
- private static byte[] hashPasswordWithSalt(byte text[], byte salt[]) throws SecurityException {
- try {
- MessageDigest sha1Algorithm = MessageDigest.getInstance("SHA-1");
- byte[] digest;
- synchronized (sha1Algorithm) {
- sha1Algorithm.reset();
- sha1Algorithm.update(salt);
- digest = sha1Algorithm.digest(text);
- }
- return digest;
- } catch (NoSuchAlgorithmException ex) {
- throw new SecurityException("Cannot hash password with salt", ex);
- }
- }
-
- /**
- * returns the given password as md5 without appliying salt
- *
- * @param plainTextPassword the password to convert
- * @return the given password as md5 without appliying salt
- *
- * @throws SecurityException if the passwor cannot be converted
- */
- private static byte[] getBase64MD5HashedPassword(final String plainTextPassword) throws SecurityException {
- try {
- MessageDigest algorithm = MessageDigest.getInstance("MD5");
- algorithm.reset();
- algorithm.update(plainTextPassword.getBytes());
- byte[] messageDigest = algorithm.digest();
- StringBuilder buf = new StringBuilder();
- for (int i = 0; i < messageDigest.length; i++) {
- int halfbyte = (messageDigest[i] >>> 4) & 0x0F;
- int twoHalfs = 0;
- do {
- if ((0 <= halfbyte) && (halfbyte <= 9)) {
- buf.append((char) ('0' + halfbyte));
- } else {
- buf.append((char) ('a' + (halfbyte - 10)));
- }
- halfbyte = messageDigest[i] & 0x0F;
- } while (twoHalfs++ < 1);
- }
-
- // take password and hash with salt
- byte[] unHashedPassword = base64Decode(buf.toString());
-
- return unHashedPassword;
- } catch (Exception ex) {
- throw new SecurityException("Cannot created password", ex);
- }
- }
-
- /**
- * returns the plain byte[] as base64 coded string
- *
- * @param data the data to convert
- * @return the plain byte[] as base64 coded string
- */
- private static String base64Encode(final byte[] data) {
- Base64 encoder = new Base64();
- byte[] result = encoder.encode(data);
- return new String(result);
- }
-
- /**
- * returns the given base64 coded string as decoded byte[]
- *
- * @param data the string to convert
- * @return the given base64 coded string as decoded byte[]
- */
- private static byte[] base64Decode(final String data) {
- Base64 decoder = new Base64();
- return decoder.decode(data.getBytes());
- }
-
-
- /**
- * returns the crypted parameter string for the given plain text password
- *
- * @param plainPassword the plain text password to crypt
- * @return the crypted password string
- */
- public static String getScryptHash(String plainPassword) {
- return scrypt(plainPassword, scryptCpuCostParameter, scryptMemCostParameter, scryptParallelizationParameter);
- }
-
- /**
- * returns true, if the given plainPassword re-encrypted matches the given crypted password
- *
- * @param plainPassword the plain password to validate
- * @param hashedPassword the encrypted password to validate against
- * @return true, if the encrypted string of the given plain password matches the provided crypted password
- */
- public static boolean validateScryptHash(String plainPassword, String hashedPassword) {
- return check(plainPassword, hashedPassword);
- }
-}
+package de.muehlencord.shared.security;
+
+import java.security.SecureRandom;
+import org.bouncycastle.crypto.generators.SCrypt;
+import org.bouncycastle.util.encoders.Base64;
+
+/**
+ * TODO: migrate to shared library
+ *
+ * @author joern.muehlencord
+ */
+public class PasswordUtil {
+
+ private final static SecureRandom SECURERANDOM = new SecureRandom();
+
+ private final static int CPU_MEMORY_COST_PARAMETER = 16384;
+ private final static int BLOCK_SIZE = 8;
+ private final static int PARALLELIZATION = 1;
+ private final static int KEY_LENGTH = 32;
+
+ private final String SYSTEMSALT;
+
+ public PasswordUtil(String systemSaltBase64Coded) {
+ // TODO make some tests like lengths etc
+ this.SYSTEMSALT = systemSaltBase64Coded;
+ }
+
+ public String getHash(String clearPassword) {
+
+ // generate user salt
+ byte[] userSaltBytes = new byte[32];
+ SECURERANDOM.nextBytes(userSaltBytes);
+ String userSalt = new String(Base64.encode(userSaltBytes));
+
+ // create passwordhash with salt
+ String passwordHash = getPasswordHash(SYSTEMSALT, userSalt, clearPassword);
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(userSalt);
+ sb.append(":");
+ sb.append(passwordHash);
+
+ return sb.toString();
+ }
+
+ public boolean matches(String clearPassword, String passwordHashWithSalt) {
+ if (!passwordHashWithSalt.contains(":")) {
+ // TODO add exception handling
+ return false;
+ }
+
+ String userSalt = passwordHashWithSalt.substring(0, passwordHashWithSalt.indexOf(":"));
+ String passwordHash = passwordHashWithSalt.substring(passwordHashWithSalt.indexOf(":")+1);
+
+ String validationHash = getPasswordHash(SYSTEMSALT, userSalt, clearPassword);
+ return validationHash.equals(passwordHash);
+ }
+
+ private String getPasswordHash(String systemSaltBase64, String userSaltBase64, String clearPassword) {
+ byte[] systemSalt = systemSaltBase64.getBytes();
+ byte[] userSalt = userSaltBase64.getBytes();
+ byte[] salt = new byte[systemSalt.length + userSalt.length];
+
+ System.arraycopy(systemSalt, 0, salt, 0, systemSalt.length);
+ System.arraycopy(userSalt, 0, salt, systemSalt.length, userSalt.length);
+
+ return new String(Base64.encode(SCrypt.generate(clearPassword.getBytes(), salt, CPU_MEMORY_COST_PARAMETER, BLOCK_SIZE, PARALLELIZATION, KEY_LENGTH)));
+ }
+}
diff --git a/security/src/test/java/de/muehlencord/shared/security/OldPasswordUtilTest.java b/security/src/test/java/de/muehlencord/shared/security/OldPasswordUtilTest.java
new file mode 100644
index 0000000..4fd8128
--- /dev/null
+++ b/security/src/test/java/de/muehlencord/shared/security/OldPasswordUtilTest.java
@@ -0,0 +1,154 @@
+package de.muehlencord.shared.security;
+
+import static de.muehlencord.shared.security.OldPasswordUtil.getScryptHash;
+import static de.muehlencord.shared.security.OldPasswordUtil.validateScryptHash;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author jomu
+ */
+public class OldPasswordUtilTest {
+
+ /**
+ * Test of createSaltString method, of class PasswordUtil.
+ */
+ @Test
+ public void createSaltString() throws Exception {
+ System.out.println("createSaltString");
+ int saltLength = 40;
+ String result = OldPasswordUtil.createSaltString(saltLength);
+ assertNotNull(result);
+ }
+
+ /**
+ * Test of getMD5Password method, of class PasswordUtil.
+ */
+ @Test
+ public void getMD5Password() throws Exception {
+ System.out.println("getMD5Password");
+ String plainTextPassword = "";
+ int saltLength = 40;
+ String[] result1 = OldPasswordUtil.getMD5Password(plainTextPassword, saltLength);
+ String password1 = result1[0];
+ String salt1 = result1[1];
+ assertNotNull(result1);
+ assertNotNull(password1);
+ assertNotNull(salt1);
+
+ String[] result2 = OldPasswordUtil.getMD5Password(plainTextPassword, saltLength);
+ String password2 = result2[0];
+ String salt2 = result2[1];
+ assertNotNull(result2);
+ assertNotNull(password2);
+ assertNotNull(salt2);
+
+ assertNotSame(result1, result2);
+ assertNotSame(password1, password2);
+ assertNotSame(salt1, salt2);
+ }
+
+
+
+
+ /**
+ * Test of checkPassword method, of class PasswordUtil.
+ */
+ @Test
+ public void checkPassword() throws Exception {
+ System.out.println("checkPassword");
+ String plainTextPassword = "welcome";
+ String plainTextPassword2 = "this is not the correct password";
+
+ String[] data = OldPasswordUtil.getMD5Password(plainTextPassword, 40);
+ String cryptedPassword = data[0];
+ String salt = data[1];
+
+ String salt2 = OldPasswordUtil.createSaltString(40);
+ String salt3 = OldPasswordUtil.createSaltString(10);
+
+ boolean expResult = true;
+ boolean result = OldPasswordUtil.checkPassword(plainTextPassword, cryptedPassword, salt);
+ assertEquals(expResult, result);
+
+ expResult = false;
+ result = OldPasswordUtil.checkPassword(plainTextPassword2, cryptedPassword, salt);
+ assertEquals(expResult, result);
+
+ expResult = false;
+ result = OldPasswordUtil.checkPassword(plainTextPassword, cryptedPassword, salt2);
+ assertEquals(expResult, result);
+
+ expResult = false;
+ result = OldPasswordUtil.checkPassword(plainTextPassword, cryptedPassword, salt3);
+ assertEquals(expResult, result);
+ }
+
+ @Test
+ public void getRandomString() throws SecurityException {
+ System.out.println ("getRandomString");
+ String randomString = OldPasswordUtil.getRandomString("test-", 32);
+ System.out.println(randomString);
+ assertNotNull(randomString);
+ assertTrue("string must start with prefix", randomString.startsWith("test"));
+ assertEquals("string length check", 32, randomString.length());
+
+ String randomString2 = OldPasswordUtil.getRandomString("test-", 32);
+ System.out.println(randomString2);
+ assertNotNull(randomString2);
+ assertTrue("string must start with prefix", randomString2.startsWith("test"));
+ assertEquals("string length check", 32, randomString2.length());
+
+ assertNotSame(randomString, randomString2);
+ }
+
+ @Test
+ public void getRandomStringBlankPrefix() throws SecurityException {
+ System.out.println ("getRandomStringBlankPrefix");
+ String randomString = OldPasswordUtil.getRandomString("", 32);
+ System.out.println(randomString);
+ assertNotNull(randomString);
+ assertEquals("string length check", 32, randomString.length());
+ }
+
+ @Test
+ public void getRandomStringNullPrefix() throws SecurityException {
+ System.out.println ("getRandomStringNullPrefix");
+ String randomString = OldPasswordUtil.getRandomString(null, 32);
+ System.out.println(randomString);
+ assertNotNull(randomString);
+ assertEquals("string length check", 32, randomString.length());
+ }
+
+ /**
+ * test the hashPassword method
+ */
+ @Test
+ public void testGetScryptHash() {
+ String hash1 = getScryptHash("secret");
+ String hash2 = getScryptHash("secret");
+ System.out.println (hash1);
+ System.out.println (hash2);
+ assertNotNull (hash1);
+ assertNotNull (hash2);
+ // even if password is the same, the has must not be the same due to correct usage of salts
+ assertFalse (hash1.equals (hash2));
+
+ assertTrue (hash1.length() == 79);
+ assertTrue (hash2.length() == 79);
+ }
+
+ /**
+ * test for validating passwords
+ */
+ @Test
+ public void testValidateScryptHash() {
+ String hash1 = getScryptHash("secret");
+ String hash2 = getScryptHash("secret");
+ assertTrue ("hash must match if correct password is given",validateScryptHash("secret", hash1));
+ assertTrue ("hash must match if correct password is given", validateScryptHash("secret", hash2));
+ assertFalse ("hash must not match if wrong password is given", validateScryptHash("secret2", hash1));
+ }
+
+}
\ No newline at end of file
diff --git a/security/src/test/java/de/muehlencord/shared/security/PasswordUtilTest.java b/security/src/test/java/de/muehlencord/shared/security/PasswordUtilTest.java
index 3e097f3..d4dbc79 100644
--- a/security/src/test/java/de/muehlencord/shared/security/PasswordUtilTest.java
+++ b/security/src/test/java/de/muehlencord/shared/security/PasswordUtilTest.java
@@ -1,154 +1,45 @@
-package de.muehlencord.shared.security;
-
-import static de.muehlencord.shared.security.PasswordUtil.getScryptHash;
-import static de.muehlencord.shared.security.PasswordUtil.validateScryptHash;
-import org.junit.Test;
-import static org.junit.Assert.*;
-
-/**
- *
- * @author jomu
- */
-public class PasswordUtilTest {
-
- /**
- * Test of createSaltString method, of class PasswordUtil.
- */
- @Test
- public void createSaltString() throws Exception {
- System.out.println("createSaltString");
- int saltLength = 40;
- String result = PasswordUtil.createSaltString(saltLength);
- assertNotNull(result);
- }
-
- /**
- * Test of getMD5Password method, of class PasswordUtil.
- */
- @Test
- public void getMD5Password() throws Exception {
- System.out.println("getMD5Password");
- String plainTextPassword = "";
- int saltLength = 40;
- String[] result1 = PasswordUtil.getMD5Password(plainTextPassword, saltLength);
- String password1 = result1[0];
- String salt1 = result1[1];
- assertNotNull(result1);
- assertNotNull(password1);
- assertNotNull(salt1);
-
- String[] result2 = PasswordUtil.getMD5Password(plainTextPassword, saltLength);
- String password2 = result2[0];
- String salt2 = result2[1];
- assertNotNull(result2);
- assertNotNull(password2);
- assertNotNull(salt2);
-
- assertNotSame(result1, result2);
- assertNotSame(password1, password2);
- assertNotSame(salt1, salt2);
- }
-
-
-
-
- /**
- * Test of checkPassword method, of class PasswordUtil.
- */
- @Test
- public void checkPassword() throws Exception {
- System.out.println("checkPassword");
- String plainTextPassword = "welcome";
- String plainTextPassword2 = "this is not the correct password";
-
- String[] data = PasswordUtil.getMD5Password(plainTextPassword, 40);
- String cryptedPassword = data[0];
- String salt = data[1];
-
- String salt2 = PasswordUtil.createSaltString(40);
- String salt3 = PasswordUtil.createSaltString(10);
-
- boolean expResult = true;
- boolean result = PasswordUtil.checkPassword(plainTextPassword, cryptedPassword, salt);
- assertEquals(expResult, result);
-
- expResult = false;
- result = PasswordUtil.checkPassword(plainTextPassword2, cryptedPassword, salt);
- assertEquals(expResult, result);
-
- expResult = false;
- result = PasswordUtil.checkPassword(plainTextPassword, cryptedPassword, salt2);
- assertEquals(expResult, result);
-
- expResult = false;
- result = PasswordUtil.checkPassword(plainTextPassword, cryptedPassword, salt3);
- assertEquals(expResult, result);
- }
-
- @Test
- public void getRandomString() throws SecurityException {
- System.out.println ("getRandomString");
- String randomString = PasswordUtil.getRandomString("test-", 32);
- System.out.println(randomString);
- assertNotNull(randomString);
- assertTrue("string must start with prefix", randomString.startsWith("test"));
- assertEquals("string length check", 32, randomString.length());
-
- String randomString2 = PasswordUtil.getRandomString("test-", 32);
- System.out.println(randomString2);
- assertNotNull(randomString2);
- assertTrue("string must start with prefix", randomString2.startsWith("test"));
- assertEquals("string length check", 32, randomString2.length());
-
- assertNotSame(randomString, randomString2);
- }
-
- @Test
- public void getRandomStringBlankPrefix() throws SecurityException {
- System.out.println ("getRandomStringBlankPrefix");
- String randomString = PasswordUtil.getRandomString("", 32);
- System.out.println(randomString);
- assertNotNull(randomString);
- assertEquals("string length check", 32, randomString.length());
- }
-
- @Test
- public void getRandomStringNullPrefix() throws SecurityException {
- System.out.println ("getRandomStringNullPrefix");
- String randomString = PasswordUtil.getRandomString(null, 32);
- System.out.println(randomString);
- assertNotNull(randomString);
- assertEquals("string length check", 32, randomString.length());
- }
-
- /**
- * test the hashPassword method
- */
- @Test
- public void testGetScryptHash() {
- String hash1 = getScryptHash("secret");
- String hash2 = getScryptHash("secret");
- System.out.println (hash1);
- System.out.println (hash2);
- assertNotNull (hash1);
- assertNotNull (hash2);
- // even if password is the same, the has must not be the same due to correct usage of salts
- assertFalse (hash1.equals (hash2));
-
- assertTrue (hash1.length() == 79);
- assertTrue (hash2.length() == 79);
- }
-
- /**
- * test for validating passwords
- */
- @Test
- public void testValidateScryptHash() {
- String hash1 = getScryptHash("secret");
- String hash2 = getScryptHash("secret");
- assertTrue ("hash must match if correct password is given",validateScryptHash("secret", hash1));
- assertTrue ("hash must match if correct password is given", validateScryptHash("secret", hash2));
- assertFalse ("hash must not match if wrong password is given", validateScryptHash("secret2", hash1));
- }
-
-}
\ No newline at end of file
+package de.muehlencord.shared.security;
+
+import de.muehlencord.shared.security.PasswordUtil;
+import java.security.SecureRandom;
+import org.bouncycastle.util.encoders.Base64;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.junit.BeforeClass;
+
+/**
+ *
+ * @author joern.muehlencord
+ */
+public class PasswordUtilTest {
+
+ private static SecureRandom secureRandom;
+ private static String systemSalt64Coded;
+ private static byte[] systemSaltBytes;
+
+ @BeforeClass
+ public static void init() {
+ secureRandom = new SecureRandom();
+
+ systemSaltBytes = new byte[32];
+ secureRandom.nextBytes (systemSaltBytes);
+ systemSalt64Coded = new String(Base64.encode (systemSaltBytes));
+ }
+
+
+ @Test
+ public void testGetHash() {
+ PasswordUtil pwUtil = new PasswordUtil(systemSalt64Coded);
+
+ String password1 = pwUtil.getHash("password");
+ String password2 = pwUtil.getHash("password");
+
+ assertFalse (password1.equals(password2));
+ assertTrue (pwUtil.matches ("password", password1));
+ assertFalse (pwUtil.matches ("wrongpassword", password1));
+
+
+ }
+
+}