feat: 自動で鍵を作成するように

This commit is contained in:
usbharu 2023-05-01 07:09:26 +09:00
parent f0383e3a95
commit aebf0862e0
5 changed files with 88 additions and 20 deletions

View File

@ -0,0 +1,5 @@
package dev.usbharu.hideout.domain.model.hideout.entity
import java.util.*
data class Jwt(val kid: UUID, val privateKey: String, val publicKey: String)

View File

@ -7,7 +7,10 @@ import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import dev.usbharu.hideout.domain.model.hideout.form.UserLogin
import dev.usbharu.hideout.property
import dev.usbharu.hideout.repository.IMetaRepository
import dev.usbharu.hideout.service.IUserAuthService
import dev.usbharu.hideout.util.JsonWebKeyUtil
import dev.usbharu.hideout.util.RsaUtil
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
@ -15,19 +18,27 @@ import io.ktor.server.auth.jwt.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.coroutines.runBlocking
import java.security.KeyFactory
import java.security.interfaces.RSAPrivateKey
import java.security.interfaces.RSAPublicKey
import java.security.spec.PKCS8EncodedKeySpec
import java.util.*
import java.util.concurrent.TimeUnit
const val TOKEN_AUTH = "jwt-auth"
fun Application.configureSecurity(userAuthService: IUserAuthService) {
fun Application.configureSecurity(userAuthService: IUserAuthService, metaRepository: IMetaRepository) {
val privateKeyString = property("jwt.privateKey")
val issuer = property("jwt.issuer")
val privateKeyString = runBlocking {
requireNotNull(metaRepository.get()).jwt.privateKey
}
val publicKey = runBlocking {
val publicKey = requireNotNull(metaRepository.get()).jwt.publicKey
println(publicKey)
RsaUtil.decodeRsaPublicKey(Base64.getDecoder().decode(publicKey))
}
println(privateKeyString)
val issuer = property("hideout.url")
// val audience = property("jwt.audience")
val myRealm = property("jwt.realm")
val jwkProvider = JwkProviderBuilder(issuer)
@ -57,8 +68,6 @@ fun Application.configureSecurity(userAuthService: IUserAuthService) {
if (check.not()) {
return@post call.respond(HttpStatusCode.Unauthorized)
}
val publicKey = jwkProvider.get("6f8856ed-9189-488f-9011-0ff4b6c08edc").publicKey
val keySpecPKCS8 = PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyString))
val privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpecPKCS8)
val token = JWT.create()
@ -66,22 +75,16 @@ fun Application.configureSecurity(userAuthService: IUserAuthService) {
// .withIssuer(issuer)
.withClaim("username", user.username)
.withExpiresAt(Date(System.currentTimeMillis() + 60000))
.sign(Algorithm.RSA256(publicKey as RSAPublicKey, privateKey as RSAPrivateKey))
.sign(Algorithm.RSA256(publicKey, privateKey as RSAPrivateKey))
return@post call.respond(hashSetOf("token" to token))
}
get("/.well-known/jwks.json"){
get("/.well-known/jwks.json") {
//language=JSON
call.respondText(contentType = ContentType.Application.Json,text = """{
"keys": [
{
"kty": "RSA",
"e": "AQAB",
"kid": "6f8856ed-9189-488f-9011-0ff4b6c08edc",
"n":"tfJaLrzXILUg1U3N1KV8yJr92GHn5OtYZR7qWk1Mc4cy4JGjklYup7weMjBD9f3bBVoIsiUVX6xNcYIr0Ie0AQ"
}
]
}""")
call.respondText(
contentType = ContentType.Application.Json,
text = JsonWebKeyUtil.publicKeyToJwk(requireNotNull(metaRepository.get()).jwt.publicKey)
)
}
}
}

View File

@ -43,8 +43,8 @@ class ServerInitialiseServiceImpl(private val metaRepository: IMetaRepository) :
val generateKeyPair = keyPairGenerator.generateKeyPair()
val jwt = Jwt(
UUID.randomUUID(),
Base64.getEncoder().encodeToString(generateKeyPair.public.encoded),
Base64.getEncoder().encodeToString(generateKeyPair.private.encoded)
Base64.getEncoder().encodeToString(generateKeyPair.private.encoded),
Base64.getEncoder().encodeToString(generateKeyPair.public.encoded)
)
val meta = Meta(implementationVersion, jwt)
metaRepository.save(meta)

View File

@ -0,0 +1,41 @@
package dev.usbharu.hideout.util
import java.math.BigInteger
import java.security.KeyFactory
import java.security.interfaces.RSAPublicKey
import java.security.spec.X509EncodedKeySpec
import java.util.*
object JsonWebKeyUtil {
fun publicKeyToJwk(publicKey: String): String {
val x509EncodedKeySpec = X509EncodedKeySpec(Base64.getDecoder().decode(publicKey))
val generatePublic = KeyFactory.getInstance("RSA").generatePublic(x509EncodedKeySpec)
return publicKeyToJwk(generatePublic as RSAPublicKey)
}
fun publicKeyToJwk(publicKey: RSAPublicKey): String {
val e = encodeBase64UInt(publicKey.publicExponent)
val n = encodeBase64UInt(publicKey.modulus)
return """{"e":"$e","n":"$n","use":"sig","kty":"RSA"}"""
}
private fun encodeBase64UInt(bigInteger: BigInteger, minLength: Int = -1): String {
if(bigInteger.signum() < 0){
throw IllegalArgumentException("Cannot encode negative numbers")
}
var bytes = bigInteger.toByteArray()
if (bigInteger.bitLength() % 8 == 0 && (bytes[0] == 0.toByte()) && bytes.size > 1){
bytes = Arrays.copyOfRange(bytes, 1, bytes.size)
}
if (minLength != -1){
if (bytes.size < minLength){
val array = ByteArray(minLength)
System.arraycopy(bytes, 0, array, minLength - bytes.size, bytes.size)
bytes = array
}
}
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes)
}
}

View File

@ -0,0 +1,19 @@
package dev.usbharu.hideout.util
import java.security.KeyFactory
import java.security.interfaces.RSAPrivateKey
import java.security.interfaces.RSAPublicKey
import java.security.spec.PKCS8EncodedKeySpec
import java.security.spec.X509EncodedKeySpec
object RsaUtil {
fun decodeRsaPublicKey(byteArray: ByteArray):RSAPublicKey{
val x509EncodedKeySpec = X509EncodedKeySpec(byteArray)
return KeyFactory.getInstance("RSA").generatePublic(x509EncodedKeySpec) as RSAPublicKey
}
fun decodeRsaPrivateKey(byteArray: ByteArray):RSAPrivateKey{
val pkcS8EncodedKeySpec = PKCS8EncodedKeySpec(byteArray)
return KeyFactory.getInstance("RSA").generatePrivate(pkcS8EncodedKeySpec) as RSAPrivateKey
}
}