1
0

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:
Michael Hoennig
2024-06-28 11:00:15 +02:00
parent 6167ef2221
commit 3391ec6cc9
16 changed files with 281 additions and 62 deletions

View File

@@ -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");
}
}

View File

@@ -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}"
);
}
}

View File

@@ -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
}
}