From fd6e7790a67ca6585967d116ba465f2bfb322c49 Mon Sep 17 00:00:00 2001 From: Jorge Bornhausen Date: Fri, 18 Oct 2024 23:00:46 +0200 Subject: [PATCH] added message digest module --- pom.xml | 1 + quarkus-message-digest-service/pom.xml | 16 ++++ .../digest/MessageDigestConfiguration.java | 12 +++ .../commons/digest/MessageDigestService.java | 66 +++++++++++++++ .../digest/MessageDigestServiceImpl.java | 55 +++++++++++++ .../digest/MessageDigestServiceImplTest.java | 81 +++++++++++++++++++ 6 files changed, 231 insertions(+) create mode 100644 quarkus-message-digest-service/pom.xml create mode 100644 quarkus-message-digest-service/src/main/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestConfiguration.java create mode 100644 quarkus-message-digest-service/src/main/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestService.java create mode 100644 quarkus-message-digest-service/src/main/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestServiceImpl.java create mode 100644 quarkus-message-digest-service/src/test/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestServiceImplTest.java diff --git a/pom.xml b/pom.xml index 521e405..10c2e5a 100644 --- a/pom.xml +++ b/pom.xml @@ -10,6 +10,7 @@ quarkus-clock-service + quarkus-message-digest-service quarkus-random-number-generator quarkus-uuid-generator diff --git a/quarkus-message-digest-service/pom.xml b/quarkus-message-digest-service/pom.xml new file mode 100644 index 0000000..540a21b --- /dev/null +++ b/quarkus-message-digest-service/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + + ch.phoenixtechnologies.quarkus + quarkus-commons + 0.1.0-SNAPSHOT + + + quarkus-message-digest-service + jar + + diff --git a/quarkus-message-digest-service/src/main/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestConfiguration.java b/quarkus-message-digest-service/src/main/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestConfiguration.java new file mode 100644 index 0000000..6720b90 --- /dev/null +++ b/quarkus-message-digest-service/src/main/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestConfiguration.java @@ -0,0 +1,12 @@ +package ch.phoenixtechnologies.quarkus.commons.digest; + +import io.smallrye.config.ConfigMapping; +import io.smallrye.config.WithDefault; + +@ConfigMapping(prefix = "phoenix.message-digest") +public interface MessageDigestConfiguration { + + @WithDefault("SHA-256") + String defaultAlgorithm(); + +} diff --git a/quarkus-message-digest-service/src/main/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestService.java b/quarkus-message-digest-service/src/main/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestService.java new file mode 100644 index 0000000..de1f2a5 --- /dev/null +++ b/quarkus-message-digest-service/src/main/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestService.java @@ -0,0 +1,66 @@ +package ch.phoenixtechnologies.quarkus.commons.digest; + +import java.nio.charset.Charset; +import java.security.MessageDigest; + +/** + * Service for creating and using MessageDigest instances. + *

+ * To configure the default algorithm, see {@link MessageDigestConfiguration}. + */ +public interface MessageDigestService { + + /** + * Get a new MessageDigest instance using the configured algorithm. + * + * @return The MessageDigest instance + */ + MessageDigest getInstance(); + + /** + * Get a new MessageDigest instance using the specified algorithm. + * + * @param algorithm the algorithm to use + * @return The MessageDigest instance + */ + MessageDigest getInstance(String algorithm); + + /** + * Digests the input using the default charset (UTF-8) and + * the configured algorithm. + * + * @param input the input to digest + * @return the digest + */ + byte[] digest(String input); + + /** + * Digests the input using the specified charset and + * the configured algorithm. + * + * @param input the input to digest + * @param charset the charset to use + * @return the digest + */ + byte[] digest(String input, Charset charset); + + /** + * Digests the input using the specified charset and algorithm. + * + * @param input the input to digest + * @param charset the charset to use + * @param algorithm the algorithm to use + * @return the digest + */ + byte[] digest(String input, Charset charset, String algorithm); + + /** + * Digests the input using the specified charset and message digest. + * + * @param input the input to digest + * @param charset the charset to use + * @param messageDigest the message digest to use + * @return the digest + */ + byte[] digest(String input, Charset charset, MessageDigest messageDigest); +} diff --git a/quarkus-message-digest-service/src/main/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestServiceImpl.java b/quarkus-message-digest-service/src/main/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestServiceImpl.java new file mode 100644 index 0000000..eb3e749 --- /dev/null +++ b/quarkus-message-digest-service/src/main/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestServiceImpl.java @@ -0,0 +1,55 @@ +package ch.phoenixtechnologies.quarkus.commons.digest; + +import io.quarkus.arc.DefaultBean; +import jakarta.enterprise.context.ApplicationScoped; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +@DefaultBean +@ApplicationScoped +class MessageDigestServiceImpl implements MessageDigestService { + + private final MessageDigestConfiguration configuration; + + MessageDigestServiceImpl(MessageDigestConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public MessageDigest getInstance() { + return getInstance(configuration.defaultAlgorithm()); + } + + @Override + public MessageDigest getInstance(String algorithm) { + try { + return MessageDigest.getInstance(algorithm); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Unknown algorithm: " + algorithm, e); + } + } + + @Override + public byte[] digest(String input) { + return digest(input, StandardCharsets.UTF_8); + } + + @Override + public byte[] digest(String input, Charset charset) { + return digest(input, charset, configuration.defaultAlgorithm()); + } + + @Override + public byte[] digest(String input, Charset charset, String algorithm) { + return digest(input, charset, getInstance(algorithm)); + } + + @Override + public byte[] digest(String input, Charset charset, MessageDigest messageDigest) { + var bytes = input.getBytes(StandardCharsets.UTF_8); + return messageDigest.digest(bytes); + } +} diff --git a/quarkus-message-digest-service/src/test/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestServiceImplTest.java b/quarkus-message-digest-service/src/test/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestServiceImplTest.java new file mode 100644 index 0000000..42647b5 --- /dev/null +++ b/quarkus-message-digest-service/src/test/java/ch/phoenixtechnologies/quarkus/commons/digest/MessageDigestServiceImplTest.java @@ -0,0 +1,81 @@ +package ch.phoenixtechnologies.quarkus.commons.digest; + +import io.quarkus.test.junit.QuarkusTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +@QuarkusTest +class MessageDigestServiceImplTest { + + public static final String INPUT = "test"; + public static final byte[] EXPECTED_SHA256_DIGEST = {-97, -122, -48, -127, -120, 76, 125, 101, -102, 47, -22, -96, -59, 90, -48, 21, -93, -65, 79, 27, 43, 11, -126, 44, -47, 93, 108, 21, -80, -16, 10, 8}; + + @Inject + MessageDigestServiceImpl service; + + @Test + void getInstance() { + assertThat(service.getInstance()) + .isInstanceOf(MessageDigest.class); + } + + @ParameterizedTest + @ValueSource(strings = {"SHA-256", "SHA-512", "MD5"}) + void getInstanceWithAlgorithm(String algorithm) { + assertThat(service.getInstance(algorithm)) + .isInstanceOf(MessageDigest.class); + } + + @ParameterizedTest + @ValueSource(strings = {"ADBC", "acvb", "null"}) + void getInstanceWhenUnknownAlgorithm(String algorithm) { + assertThatThrownBy(() -> service.getInstance(algorithm)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Unknown algorithm: " + algorithm); + } + + @Test + void getInstanceWhenAlgorithmIsNull() { + assertThatThrownBy(() -> service.getInstance(null)) + .isInstanceOf(NullPointerException.class) + .hasMessageContaining("null algorithm name"); + } + + @Test + void digest() { + assertThat(service.digest(INPUT)) + .as("Digest should match expected value") + .isEqualTo(EXPECTED_SHA256_DIGEST); + } + + @Test + void digestWithCharset() { + assertThat(service.digest(INPUT, StandardCharsets.UTF_8)) + .as("Digest should match expected value") + .isEqualTo(EXPECTED_SHA256_DIGEST); + + } + + @Test + void digestWithCharsetAndAlgorithm() { + assertThat(service.digest(INPUT, StandardCharsets.UTF_8, "SHA-256")) + .as("Digest should match expected value") + .isEqualTo(EXPECTED_SHA256_DIGEST); + } + + @Test + void digestWithCharsetAndMessageDigestInstance() { + var messageDigest = service.getInstance(); + assertThat(service.digest(INPUT, StandardCharsets.UTF_8, messageDigest)) + .as("Digest should match expected value") + .isEqualTo(EXPECTED_SHA256_DIGEST); + } +} \ No newline at end of file