summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorPaul-Christian Volkmer2026-10-05 09:32:16 +0200
committerGitHub2026-10-05 07:32:16 +0000
commit3e49d70ff69b5382e0ad62d8f321aa0c15b1f85b (patch)
tree812359ba361f290a5980eb8de9d3239587b16edc /src/main
parentd9961a9baccaff511662b1aa1de18bdd02f94f5e (diff)
feat: add SHA256-HMAC for use in build-in pseudonym generator (#324)
Diffstat (limited to 'src/main')
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt1
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt6
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt2
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingHmacGenerator.kt52
4 files changed, 58 insertions, 3 deletions
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt
index fb93618..f0766a4 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt
@@ -41,6 +41,7 @@ data class AppConfigProperties(
data class PseudonymizeConfigProperties(
var generator: PseudonymGenerator = PseudonymGenerator.BUILDIN,
val prefix: String = "UNKNOWN",
+ val hmacKey: String? = null,
) {
companion object {
const val NAME = "app.pseudonymize"
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt
index d780642..54f4c6f 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt
@@ -155,7 +155,11 @@ class AppConfiguration {
matchIfMissing = true,
)
@Bean
- fun buildinPseudonymGenerator(): Generator {
+ fun buildinPseudonymGenerator(pseudonymizeConfigProperties: PseudonymizeConfigProperties): Generator {
+ if (null != pseudonymizeConfigProperties.hmacKey) {
+ logger.info("Selected 'BUILDIN Pseudonym Generator' using HMAC")
+ return AnonymizingHmacGenerator(pseudonymizeConfigProperties)
+ }
logger.info("Selected 'BUILDIN Pseudonym Generator'")
return AnonymizingGenerator()
}
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt
index b3c80e2..5e97568 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt
@@ -25,8 +25,6 @@ import org.apache.commons.codec.digest.DigestUtils
import java.security.SecureRandom
class AnonymizingGenerator : Generator {
- companion object
-
fun getSecureRandom(): SecureRandom = SecureRandom()
override fun generate(id: String): String = Base32().encodeAsString(DigestUtils.sha256(id)).substring(0..41).lowercase()
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingHmacGenerator.kt b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingHmacGenerator.kt
new file mode 100644
index 0000000..646f6d3
--- /dev/null
+++ b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingHmacGenerator.kt
@@ -0,0 +1,52 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
+ * Copyright (c) 2023-2026 Paul-Christian Volkmer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package dev.dnpm.etl.processor.pseudonym
+
+import dev.dnpm.etl.processor.config.AppConfigProperties
+import dev.dnpm.etl.processor.config.PseudonymizeConfigProperties
+import org.apache.commons.codec.binary.Base32
+import org.apache.commons.codec.digest.DigestUtils
+import org.apache.commons.codec.digest.HmacAlgorithms
+import org.apache.commons.codec.digest.HmacUtils
+import java.security.SecureRandom
+
+/**
+ * Variant of AnonymizingGenerator that uses app.pseudonymize.prefix as HMAC-SHA256 key
+ */
+class AnonymizingHmacGenerator(
+ private val pseudonymizeConfigProperties: PseudonymizeConfigProperties,
+) : Generator {
+ fun getSecureRandom(): SecureRandom = SecureRandom()
+
+ override fun generate(id: String): String =
+ Base32()
+ .encodeAsString(HmacUtils(HmacAlgorithms.HMAC_SHA_256, pseudonymizeConfigProperties.hmacKey).hmac(id))
+ .substring(0..41)
+ .lowercase()
+
+ @OptIn(ExperimentalStdlibApi::class)
+ override fun generateGenomDeTan(id: String): String {
+ val bytes = ByteArray(64 / 2)
+ getSecureRandom().nextBytes(bytes)
+
+ return bytes.joinToString("") { "%02x".format(it) }
+ }
+}