implement password-hashing (not fully integrated yet) (#67)
Co-authored-by: Michael Hoennig <michael@hoennig.de> Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/67 Reviewed-by: Timotheus Pokorra <timotheus.pokorra@hostsharing.net>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
package net.hostsharing.hsadminng.hash;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
import static net.hostsharing.hsadminng.hash.HashProcessor.Algorithm.SHA512;
|
||||
import static net.hostsharing.hsadminng.hash.HashProcessor.hashAlgorithm;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.catchThrowable;
|
||||
|
||||
class HashProcessorUnitTest {
|
||||
|
||||
final String OTHER_PASSWORD = "other password";
|
||||
final String GIVEN_PASSWORD = "given password";
|
||||
final String GIVEN_PASSWORD_HASH = "foKDNQP0oZo0pjFpss5vNl0kfHOs6MKMaJUUbpJTg6hqI1WY+KbU/PKQIg2xt/mwDMmW5WR0pdUZnTv8RPTfhjprZUNqTXJsUXczQnczYUxE";
|
||||
final String GIVEN_SALT = "given salt";
|
||||
|
||||
@Test
|
||||
void verifiesHashedPasswordWithRandomSalt() {
|
||||
final var hash = hashAlgorithm(SHA512).withRandomSalt().generate(GIVEN_PASSWORD);
|
||||
hashAlgorithm(SHA512).withHash(hash).verify(GIVEN_PASSWORD); // throws exception if wrong
|
||||
}
|
||||
|
||||
@Test
|
||||
void verifiesHashedPasswordWithGivenSalt() {
|
||||
final var hash = hashAlgorithm(SHA512).withSalt(GIVEN_SALT).generate(GIVEN_PASSWORD);
|
||||
|
||||
final var decoded = new String(Base64.getDecoder().decode(hash));
|
||||
assertThat(decoded).endsWith(":" + GIVEN_SALT);
|
||||
hashAlgorithm(SHA512).withHash(hash).verify(GIVEN_PASSWORD); // throws exception if wrong
|
||||
}
|
||||
|
||||
@Test
|
||||
void throwsExceptionForInvalidPassword() {
|
||||
final var throwable = catchThrowable(() ->
|
||||
hashAlgorithm(SHA512).withHash(GIVEN_PASSWORD_HASH).verify(OTHER_PASSWORD));
|
||||
|
||||
assertThat(throwable).hasMessage("invalid password");
|
||||
}
|
||||
}
|
@@ -125,7 +125,7 @@ class HsUnixUserHostingAssetValidatorUnitTest {
|
||||
"{type=enumeration, propertyName=shell, values=[/bin/false, /bin/bash, /bin/csh, /bin/dash, /usr/bin/tcsh, /usr/bin/zsh, /usr/bin/passwd], defaultValue=/bin/false}",
|
||||
"{type=string, propertyName=homedir, readOnly=true, computed=true}",
|
||||
"{type=string, propertyName=totpKey, matchesRegEx=^0x([0-9A-Fa-f]{2})+$, minLength=20, maxLength=256, writeOnly=true, undisclosed=true}",
|
||||
"{type=password, propertyName=password, minLength=8, maxLength=40, writeOnly=true, undisclosed=true}"
|
||||
"{type=password, propertyName=password, minLength=8, maxLength=40, writeOnly=true, hashedUsing=SHA512, undisclosed=true}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -6,13 +6,18 @@ import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.hostsharing.hsadminng.hash.HashProcessor.Algorithm.SHA512;
|
||||
import static net.hostsharing.hsadminng.hash.HashProcessor.hashAlgorithm;
|
||||
import static net.hostsharing.hsadminng.hs.validation.PasswordProperty.passwordProperty;
|
||||
import static net.hostsharing.hsadminng.mapper.PatchableMapWrapper.entry;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PasswordPropertyUnitTest {
|
||||
|
||||
private final ValidatableProperty<String> passwordProp = passwordProperty("password").minLength(8).maxLength(40).writeOnly();
|
||||
private final ValidatableProperty<PasswordProperty, String> passwordProp =
|
||||
passwordProperty("password").minLength(8).maxLength(40).hashedUsing(SHA512).writeOnly();
|
||||
private final List<String> violations = new ArrayList<>();
|
||||
|
||||
@ParameterizedTest
|
||||
@@ -89,4 +94,27 @@ class PasswordPropertyUnitTest {
|
||||
.contains("password' must not contain colon (':')")
|
||||
.doesNotContain(givenPassword);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldComputeHash() {
|
||||
|
||||
// when
|
||||
final var result = passwordProp.compute(new PropertiesProvider() {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> directProps() {
|
||||
return Map.ofEntries(
|
||||
entry(passwordProp.propertyName, "some password")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getContextValue(final String propName) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// then
|
||||
hashAlgorithm(SHA512).withHash(result).verify("some password"); // throws exception if wrong
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user