#364 Add HashAlgorithm integration test, fix failing tests

- Create integration test for the HashAlgorithm enum
- Create AsciiRestricted annotation and make test aware of it
- Add option to skip "same hash for same salt" test (for wordpress)
- Change some EncryptionMethods to extend from a common superclass
This commit is contained in:
ljacqu
2015-12-29 13:29:26 +01:00
parent 531327dd9b
commit 922082f312
13 changed files with 123 additions and 76 deletions
@@ -1,8 +1,11 @@
package fr.xephi.authme.security.crypts;
import com.google.common.collect.ImmutableList;
import fr.xephi.authme.security.crypts.description.AsciiRestricted;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.hamcrest.Matchers.equalTo;
@@ -27,7 +30,8 @@ public abstract class AbstractEncryptionMethodTest {
* List of passwords that are hashed at runtime and then tested against; this verifies that hashes that are
* generated are valid.
*/
private static final String[] INTERNAL_PASSWORDS = {"test1234", "Ab_C73", "(!#&$~`_-Aa0", "Ûïé1&?+A"};
private static final List<String> INTERNAL_PASSWORDS =
ImmutableList.of("test1234", "Ab_C73", "(!#&$~`_-Aa0", "Ûïé1&?+A");
/** The encryption method to test. */
private EncryptionMethod method;
@@ -97,12 +101,19 @@ public abstract class AbstractEncryptionMethodTest {
@Test
public void testPasswordEquality() {
for (String password : INTERNAL_PASSWORDS) {
List<String> internalPasswords = method.getClass().isAnnotationPresent(AsciiRestricted.class)
? INTERNAL_PASSWORDS.subList(0, INTERNAL_PASSWORDS.size() - 1)
: INTERNAL_PASSWORDS;
for (String password : internalPasswords) {
final String salt = method.generateSalt();
final String hash = method.computeHash(password, salt, USERNAME);
// Check that the computeHash(password, salt, name) method has the same output for the returned salt
assertThat(hash, equalTo(method.computeHash(password, salt, USERNAME)));
if (testHashEqualityForSameSalt()) {
assertThat("Computing a hash with the same salt will generate the same hash",
hash, equalTo(method.computeHash(password, salt, USERNAME)));
}
assertTrue("Generated hash for '" + password + "' should match password (hash = '" + hash + "')",
method.comparePassword(hash, password, salt, USERNAME));
@@ -151,4 +162,16 @@ public abstract class AbstractEncryptionMethodTest {
System.out.println("\n}");
}
/**
* Return whether an encryption algorithm should be tested that it generates the same
* hash for the same salt. If {@code true}, we call {@link EncryptionMethod#computeHash(String, String)}
* and verify that {@link EncryptionMethod#computeHash(String, String, String)} generates
* the same hash for the salt returned in the first call.
*
* @return Whether or not to test that the hash is the same for the same salt
*/
protected boolean testHashEqualityForSameSalt() {
return true;
}
}
@@ -1,12 +1,8 @@
package fr.xephi.authme.security.crypts;
import org.junit.Ignore;
/**
* Test for {@link CryptPBKDF2Django}.
*/
@Ignore
// TODO ljacqu 20151220: testPasswordEquality fails - password matches hash for uppercase password...?
public class CryptPBKDF2DjangoTest extends AbstractEncryptionMethodTest {
public CryptPBKDF2DjangoTest() {
@@ -1,12 +1,8 @@
package fr.xephi.authme.security.crypts;
import org.junit.Ignore;
/**
* Test for {@link PHPFUSION}.
*/
@Ignore
// TODO #364: Need to skip lowercase/uppercase password test for the non-ASCII one
public class PHPFUSIONTest extends AbstractEncryptionMethodTest {
public PHPFUSIONTest() {
@@ -1,12 +1,8 @@
package fr.xephi.authme.security.crypts;
import org.junit.Ignore;
/**
* Test for {@link WORDPRESS}.
*/
@Ignore
// TODO #364: Need to skip an assertion due to the "internal salt" of Wordpress
public class WORDPRESSTest extends AbstractEncryptionMethodTest {
public WORDPRESSTest() {
@@ -16,4 +12,10 @@ public class WORDPRESSTest extends AbstractEncryptionMethodTest {
"$P$BjzPjjzPjrAOyB1V0WFdpisgCTFx.N/", // &^%te$t?Pw@_
"$P$BjzPjxxyjp2QdKcab/oTW8l/W0AgE21"); // âË_3(íù*
}
@Override
protected boolean testHashEqualityForSameSalt() {
// We need to skip the test because Wordpress uses an "internal salt" that is not exposed to the outside
return false;
}
}