LoginSystem/src/test/java/fr/xephi/authme/security/HashAlgorithmIntegrationTest.java

110 lines
4.8 KiB
Java

package fr.xephi.authme.security;
import ch.jalu.injector.Injector;
import ch.jalu.injector.InjectorBuilder;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.security.crypts.Argon2;
import fr.xephi.authme.security.crypts.EncryptionMethod;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.StringUtils;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Integration test for {@link HashAlgorithm}.
*/
public class HashAlgorithmIntegrationTest {
private static Injector injector;
@BeforeClass
public static void setUpConfigAndInjector() {
Settings settings = mock(Settings.class);
given(settings.getProperty(HooksSettings.BCRYPT_LOG2_ROUND)).willReturn(8);
given(settings.getProperty(SecuritySettings.DOUBLE_MD5_SALT_LENGTH)).willReturn(16);
given(settings.getProperty(SecuritySettings.PBKDF2_NUMBER_OF_ROUNDS)).willReturn(10_000);
injector = new InjectorBuilder().addDefaultHandlers("fr.xephi.authme").create();
injector.register(Settings.class, settings);
TestHelper.setupLogger();
}
@Test
public void shouldHaveUniqueClassForEntries() {
// given
Set<Class<? extends EncryptionMethod>> classes = new HashSet<>();
// when / then
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
if (!HashAlgorithm.CUSTOM.equals(algorithm)) {
if (!classes.add(algorithm.getClazz())) {
fail("Found class '" + algorithm.getClazz() + "' twice!");
}
}
}
}
@Test
public void shouldBeAbleToInstantiateEncryptionAlgorithms() {
// given / when / then
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
if (!HashAlgorithm.CUSTOM.equals(algorithm) && !HashAlgorithm.PLAINTEXT.equals(algorithm)) {
if (HashAlgorithm.ARGON2.equals(algorithm) && !Argon2.isLibraryLoaded()) {
System.out.println("[WARNING] Cannot find argon2 library, skipping integration test");
continue;
}
EncryptionMethod method = injector.createIfHasDependencies(algorithm.getClazz());
if (method == null) {
fail("Could not create '" + algorithm.getClazz() + "' - forgot to provide some class?");
}
HashedPassword hashedPassword = method.computeHash("pwd", "name");
assertThat("Salt should not be null if method.hasSeparateSalt(), and vice versa. Method: '"
+ method + "'", StringUtils.isEmpty(hashedPassword.getSalt()), equalTo(!method.hasSeparateSalt()));
assertThat("Hash should not be empty for method '" + method + "'",
StringUtils.isEmpty(hashedPassword.getHash()), equalTo(false));
}
}
}
@Test
public void shouldBeDeprecatedIfEncryptionClassIsDeprecated() throws NoSuchFieldException {
// given
List<String> failedEntries = new LinkedList<>();
// when
for (HashAlgorithm hashAlgorithm : HashAlgorithm.values()) {
if (hashAlgorithm != HashAlgorithm.CUSTOM && hashAlgorithm != HashAlgorithm.PLAINTEXT) {
boolean isEnumDeprecated = HashAlgorithm.class.getDeclaredField(hashAlgorithm.name())
.isAnnotationPresent(Deprecated.class);
boolean isDeprecatedClass = hashAlgorithm.getClazz().isAnnotationPresent(Deprecated.class);
Recommendation recommendation = hashAlgorithm.getClazz().getAnnotation(Recommendation.class);
boolean hasDeprecatedUsage = recommendation != null && recommendation.value() == Usage.DEPRECATED;
if (isEnumDeprecated != isDeprecatedClass || isEnumDeprecated != hasDeprecatedUsage) {
failedEntries.add(hashAlgorithm + ": enum @Deprecated = " + isEnumDeprecated
+ ", @Deprecated class = " + isDeprecatedClass + ", usage Deprecated = " + hasDeprecatedUsage);
}
}
}
// then
if (!failedEntries.isEmpty()) {
fail("Found inconsistencies:\n" + String.join("\n", failedEntries));
}
}
}