From b5a61817b096423bb4029186bc960dc9dfe657e1 Mon Sep 17 00:00:00 2001 From: Swordsteel Date: Wed, 1 Jan 2025 01:01:18 +0100 Subject: [PATCH] add PrivateKeyProvider --- .../ltd/hlaeja/jwt/util/PrivateKeyProvider.kt | 35 +++++++++++++ .../hlaeja/jwt/util/PrivateKeyProviderTest.kt | 51 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 src/main/kotlin/ltd/hlaeja/jwt/util/PrivateKeyProvider.kt create mode 100644 src/test/kotlin/ltd/hlaeja/jwt/util/PrivateKeyProviderTest.kt diff --git a/src/main/kotlin/ltd/hlaeja/jwt/util/PrivateKeyProvider.kt b/src/main/kotlin/ltd/hlaeja/jwt/util/PrivateKeyProvider.kt new file mode 100644 index 0000000..35f0c10 --- /dev/null +++ b/src/main/kotlin/ltd/hlaeja/jwt/util/PrivateKeyProvider.kt @@ -0,0 +1,35 @@ +package ltd.hlaeja.jwt.util + +import java.security.KeyException +import java.security.KeyFactory +import java.security.interfaces.RSAPrivateKey +import java.security.spec.PKCS8EncodedKeySpec +import java.util.Base64.getDecoder + +object PrivateKeyProvider { + + fun load( + pemFile: String, + ): RSAPrivateKey = readPrivatePemFile(pemFile) + .let(PrivateKeyProvider::makePrivateKey) + + private fun makePrivateKey( + privateKeyBytes: ByteArray, + ): RSAPrivateKey = KeyFactory.getInstance("RSA") + .generatePrivate(PKCS8EncodedKeySpec(privateKeyBytes)) as RSAPrivateKey + + private fun readPrivatePemFile( + privateKey: String, + ): ByteArray = javaClass.classLoader + ?.getResource(privateKey) + ?.readText() + ?.let(PrivateKeyProvider::getPrivateKeyByteArray) + ?: throw KeyException("Could not load private key") + + private fun getPrivateKeyByteArray( + keyText: String, + ): ByteArray = keyText.replace(Regex("[\r\n]+"), "") + .removePrefix("-----BEGIN PRIVATE KEY-----") + .removeSuffix("-----END PRIVATE KEY-----") + .let { getDecoder().decode(it) } +} diff --git a/src/test/kotlin/ltd/hlaeja/jwt/util/PrivateKeyProviderTest.kt b/src/test/kotlin/ltd/hlaeja/jwt/util/PrivateKeyProviderTest.kt new file mode 100644 index 0000000..ea4faed --- /dev/null +++ b/src/test/kotlin/ltd/hlaeja/jwt/util/PrivateKeyProviderTest.kt @@ -0,0 +1,51 @@ +package ltd.hlaeja.jwt.util + +import java.security.KeyException +import java.security.interfaces.RSAPrivateKey +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +class PrivateKeyProviderTest { + + @Test + fun `load private key - success`() { + // given + val pemFilePath = "cert/valid-private-key.pem" + + // when + val privateKey: RSAPrivateKey = PrivateKeyProvider.load(pemFilePath) + + // then + assertThat(privateKey).isNotNull + assertThat(privateKey.algorithm).isEqualTo("RSA") + } + + @Test + fun `load private key - file does not exist`() { + // given + val nonExistentPemFilePath = "cert/non-existent.pem" + + // when exception + val exception = assertThrows { + PrivateKeyProvider.load(nonExistentPemFilePath) + } + + // then + assertThat(exception.message).isEqualTo("Could not load private key") + } + + @Test + fun `load private key - file is invalid`() { + // given + val invalidPemFilePath = "cert/invalid-private-key.pem" + + // when exception + val exception = assertThrows { + PrivateKeyProvider.load(invalidPemFilePath) + } + + // then + assertThat(exception.message).contains("Input byte array has wrong 4-byte ending unit") + } +}