diff options
| author | Paul-Christian Volkmer | 2026-10-05 09:32:16 +0200 |
|---|---|---|
| committer | GitHub | 2026-10-05 07:32:16 +0000 |
| commit | 3e49d70ff69b5382e0ad62d8f321aa0c15b1f85b (patch) | |
| tree | 812359ba361f290a5980eb8de9d3239587b16edc /src/main/kotlin/dev/dnpm/etl/processor | |
| parent | d9961a9baccaff511662b1aa1de18bdd02f94f5e (diff) | |
feat: add SHA256-HMAC for use in build-in pseudonym generator (#324)
Diffstat (limited to 'src/main/kotlin/dev/dnpm/etl/processor')
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) } + } +} |
