mirror of
https://github.com/usbharu/Hideout.git
synced 2026-09-27 15:31:17 +00:00
chore: 不要になった依存と実装を削除
This commit is contained in:
@@ -1,20 +1,16 @@
|
||||
package dev.usbharu.hideout.config
|
||||
|
||||
import dev.usbharu.hideout.plugins.KtorKeyMap
|
||||
import dev.usbharu.hideout.query.UserQueryService
|
||||
import dev.usbharu.hideout.service.core.Transaction
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.engine.cio.*
|
||||
import io.ktor.client.plugins.cache.*
|
||||
import io.ktor.client.plugins.logging.*
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import tech.barbero.http.message.signing.KeyMap
|
||||
|
||||
@Configuration
|
||||
class HttpClientConfig {
|
||||
@Bean
|
||||
fun httpClient(keyMap: KeyMap): HttpClient = HttpClient(CIO).config {
|
||||
fun httpClient(): HttpClient = HttpClient(CIO).config {
|
||||
install(Logging) {
|
||||
logger = Logger.DEFAULT
|
||||
level = LogLevel.INFO
|
||||
@@ -24,16 +20,4 @@ class HttpClientConfig {
|
||||
expectSuccess = true
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun keyMap(
|
||||
userQueryService: UserQueryService,
|
||||
transaction: Transaction,
|
||||
applicationConfig: ApplicationConfig
|
||||
): KtorKeyMap {
|
||||
return KtorKeyMap(
|
||||
userQueryService,
|
||||
transaction,
|
||||
applicationConfig
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
package dev.usbharu.hideout.plugins
|
||||
|
||||
import dev.usbharu.hideout.config.ApplicationConfig
|
||||
import dev.usbharu.hideout.query.UserQueryService
|
||||
import dev.usbharu.hideout.service.core.Transaction
|
||||
import dev.usbharu.hideout.service.user.UserAuthServiceImpl
|
||||
import io.ktor.client.plugins.api.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.http.*
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import tech.barbero.http.message.signing.HttpMessage
|
||||
import tech.barbero.http.message.signing.HttpMessageSigner
|
||||
import tech.barbero.http.message.signing.HttpRequest
|
||||
import tech.barbero.http.message.signing.KeyMap
|
||||
import java.net.URI
|
||||
import java.security.KeyFactory
|
||||
import java.security.PrivateKey
|
||||
import java.security.PublicKey
|
||||
import java.security.spec.PKCS8EncodedKeySpec
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import javax.crypto.SecretKey
|
||||
|
||||
class HttpSignaturePluginConfig {
|
||||
lateinit var keyMap: KeyMap
|
||||
}
|
||||
|
||||
val httpSignaturePlugin: ClientPlugin<HttpSignaturePluginConfig> = createClientPlugin(
|
||||
"HttpSign",
|
||||
::HttpSignaturePluginConfig
|
||||
) {
|
||||
val keyMap = pluginConfig.keyMap
|
||||
val format = SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US)
|
||||
format.timeZone = TimeZone.getTimeZone("GMT")
|
||||
onRequest { request, body ->
|
||||
|
||||
request.header("Date", format.format(Date()))
|
||||
request.header("Host", request.url.host)
|
||||
if (request.bodyType?.type == String::class) {
|
||||
body as String
|
||||
|
||||
// UserAuthService.sha256.reset()
|
||||
val digest =
|
||||
Base64.getEncoder().encodeToString(UserAuthServiceImpl.sha256.digest(body.toByteArray(Charsets.UTF_8)))
|
||||
request.headers.append("Digest", "sha-256=$digest")
|
||||
}
|
||||
|
||||
if (request.headers.contains("Signature")) {
|
||||
val all = request.headers.getAll("Signature").orEmpty()
|
||||
val parameters = mutableListOf<String>()
|
||||
for (s in all) {
|
||||
s.split(",").forEach { parameters.add(it) }
|
||||
}
|
||||
|
||||
val keyId = parameters.find { it.startsWith("keyId") }
|
||||
.orEmpty()
|
||||
.split("=")[1]
|
||||
.replace("\"", "")
|
||||
val algorithm =
|
||||
parameters.find { it.startsWith("algorithm") }
|
||||
.orEmpty()
|
||||
.split("=")[1]
|
||||
.replace("\"", "")
|
||||
val headers = parameters.find { it.startsWith("headers") }
|
||||
.orEmpty()
|
||||
.split("=")[1]
|
||||
.replace("\"", "")
|
||||
.split(" ")
|
||||
.toMutableList()
|
||||
|
||||
val algorithmType = when (algorithm) {
|
||||
"rsa-sha256" -> {
|
||||
HttpMessageSigner.Algorithm.RSA_SHA256
|
||||
}
|
||||
|
||||
else -> {
|
||||
TODO()
|
||||
}
|
||||
}
|
||||
|
||||
headers.map {
|
||||
when (it) {
|
||||
"(request-target)" -> {
|
||||
HttpMessageSigner.REQUEST_TARGET
|
||||
}
|
||||
|
||||
"digest" -> {
|
||||
"Digest"
|
||||
}
|
||||
|
||||
"date" -> {
|
||||
"Date"
|
||||
}
|
||||
|
||||
"host" -> {
|
||||
"Host"
|
||||
}
|
||||
|
||||
else -> {
|
||||
it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val builder = HttpMessageSigner.builder().algorithm(algorithmType).keyId(keyId).keyMap(keyMap)
|
||||
var tmp = builder
|
||||
headers.forEach {
|
||||
tmp = tmp.addHeaderToSign(it)
|
||||
}
|
||||
val signer = tmp.build()
|
||||
|
||||
request.headers.remove("Signature")
|
||||
|
||||
(signer ?: return@onRequest).sign(object : HttpMessage, HttpRequest {
|
||||
override fun headerValues(name: String?): MutableList<String> =
|
||||
name?.let { request.headers.getAll(it) }?.toMutableList() ?: mutableListOf()
|
||||
|
||||
override fun addHeader(name: String?, value: String?) {
|
||||
val split = value?.split("=").orEmpty()
|
||||
name?.let { request.header(it, split[0] + "=\"" + split[1].trim('"') + "\"") }
|
||||
}
|
||||
|
||||
override fun method(): String = request.method.value
|
||||
|
||||
override fun uri(): URI = request.url.build().toURI()
|
||||
})
|
||||
|
||||
val signatureHeader = request.headers.getAll("Signature").orEmpty()
|
||||
request.headers.remove("Signature")
|
||||
signatureHeader.joinToString(",") { it.replace("; ", ",").replace(";", ",") }
|
||||
.let { request.header("Signature", it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KtorKeyMap(
|
||||
private val userQueryService: UserQueryService,
|
||||
private val transaction: Transaction,
|
||||
private val applicationConfig: ApplicationConfig
|
||||
) : KeyMap {
|
||||
override fun getPublicKey(keyId: String?): PublicKey = runBlocking {
|
||||
val username = (keyId ?: throw IllegalArgumentException("keyId is null")).substringBeforeLast("#pubkey")
|
||||
.substringAfterLast("/")
|
||||
val publicBytes = Base64.getDecoder().decode(
|
||||
transaction.transaction {
|
||||
userQueryService.findByNameAndDomain(
|
||||
username,
|
||||
applicationConfig.url.host
|
||||
).run {
|
||||
publicKey
|
||||
.replace("-----BEGIN PUBLIC KEY-----", "")
|
||||
.replace("-----END PUBLIC KEY-----", "")
|
||||
.replace("\n", "")
|
||||
}
|
||||
}
|
||||
)
|
||||
val x509EncodedKeySpec = X509EncodedKeySpec(publicBytes)
|
||||
return@runBlocking KeyFactory.getInstance("RSA").generatePublic(x509EncodedKeySpec)
|
||||
}
|
||||
|
||||
override fun getPrivateKey(keyId: String?): PrivateKey = runBlocking {
|
||||
val username = (keyId ?: throw IllegalArgumentException("keyId is null")).substringBeforeLast("#pubkey")
|
||||
.substringAfterLast("/")
|
||||
val publicBytes = Base64.getDecoder().decode(
|
||||
transaction.transaction {
|
||||
userQueryService.findByNameAndDomain(
|
||||
username,
|
||||
applicationConfig.url.host
|
||||
).privateKey?.run {
|
||||
replace("-----BEGIN PRIVATE KEY-----", "")
|
||||
.replace("-----END PRIVATE KEY-----", "")
|
||||
.replace("\n", "")
|
||||
}
|
||||
}
|
||||
)
|
||||
val x509EncodedKeySpec = PKCS8EncodedKeySpec(publicBytes)
|
||||
return@runBlocking KeyFactory.getInstance("RSA").generatePrivate(x509EncodedKeySpec)
|
||||
}
|
||||
|
||||
@Suppress("NotImplementedDeclaration")
|
||||
override fun getSecretKey(keyId: String?): SecretKey = TODO("Not yet implemented")
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package dev.usbharu.hideout.service.auth
|
||||
|
||||
import dev.usbharu.hideout.config.ApplicationConfig
|
||||
import dev.usbharu.hideout.plugins.KtorKeyMap
|
||||
import dev.usbharu.hideout.query.UserQueryService
|
||||
import dev.usbharu.hideout.service.core.Transaction
|
||||
import io.ktor.http.*
|
||||
import org.springframework.stereotype.Service
|
||||
import tech.barbero.http.message.signing.SignatureHeaderVerifier
|
||||
|
||||
@Service
|
||||
interface HttpSignatureVerifyService {
|
||||
fun verify(headers: Headers): Boolean
|
||||
}
|
||||
|
||||
@Service
|
||||
class HttpSignatureVerifyServiceImpl(
|
||||
private val userQueryService: UserQueryService,
|
||||
private val transaction: Transaction,
|
||||
private val applicationConfig: ApplicationConfig
|
||||
) : HttpSignatureVerifyService {
|
||||
override fun verify(headers: Headers): Boolean {
|
||||
val build =
|
||||
SignatureHeaderVerifier.builder().keyMap(KtorKeyMap(userQueryService, transaction, applicationConfig))
|
||||
.build()
|
||||
return true
|
||||
// build.verify(object : HttpMessage {
|
||||
// override fun headerValues(name: String?): MutableList<String> {
|
||||
// return name?.let { headers.getAll(it) }?.toMutableList() ?: mutableListOf()
|
||||
// }
|
||||
//
|
||||
// override fun addHeader(name: String?, value: String?) {
|
||||
// TODO()
|
||||
// }
|
||||
//
|
||||
// })
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package dev.usbharu.hideout.service.signature
|
||||
|
||||
import io.ktor.http.*
|
||||
|
||||
interface HttpSignatureSigner {
|
||||
@Suppress("LongParameterList")
|
||||
suspend fun sign(
|
||||
url: String,
|
||||
method: HttpMethod,
|
||||
headers: Headers,
|
||||
requestBody: String,
|
||||
keyPair: Key,
|
||||
signHeaders: List<String>
|
||||
): SignedRequest
|
||||
|
||||
suspend fun signRaw(signString: String, keyPair: Key, signHeaders: List<String>): Sign
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package dev.usbharu.hideout.service.signature
|
||||
|
||||
import dev.usbharu.hideout.util.Base64Util
|
||||
import io.ktor.http.*
|
||||
import io.ktor.util.*
|
||||
import org.springframework.stereotype.Component
|
||||
import java.net.URL
|
||||
import java.security.Signature
|
||||
|
||||
@Component
|
||||
class HttpSignatureSignerImpl : HttpSignatureSigner {
|
||||
override suspend fun sign(
|
||||
url: String,
|
||||
method: HttpMethod,
|
||||
headers: Headers,
|
||||
requestBody: String,
|
||||
keyPair: Key,
|
||||
signHeaders: List<String>
|
||||
): SignedRequest {
|
||||
val sign = signRaw(
|
||||
signString = buildSignString(
|
||||
url = URL(url),
|
||||
method = method,
|
||||
headers = headers,
|
||||
signHeaders = signHeaders
|
||||
),
|
||||
keyPair = keyPair,
|
||||
signHeaders = signHeaders
|
||||
)
|
||||
val signedHeaders = headers {
|
||||
appendAll(headers)
|
||||
set("Signature", sign.signatureHeader)
|
||||
}
|
||||
return SignedRequest(
|
||||
url = url,
|
||||
method = method,
|
||||
headers = signedHeaders,
|
||||
requestBody = requestBody,
|
||||
sign = sign
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun signRaw(signString: String, keyPair: Key, signHeaders: List<String>): Sign {
|
||||
val signer = Signature.getInstance("SHA256withRSA")
|
||||
signer.initSign(keyPair.privateKey)
|
||||
signer.update(signString.toByteArray())
|
||||
val sign = signer.sign()
|
||||
val signature = Base64Util.encode(sign)
|
||||
return Sign(
|
||||
signature,
|
||||
"""keyId="${keyPair.keyId}",algorithm="rsa-sha256",headers="${
|
||||
signHeaders.joinToString(
|
||||
" "
|
||||
)
|
||||
}",signature="$signature""""
|
||||
)
|
||||
}
|
||||
|
||||
private fun buildSignString(
|
||||
url: URL,
|
||||
method: HttpMethod,
|
||||
headers: Headers,
|
||||
signHeaders: List<String>
|
||||
): String {
|
||||
headers.toMap().map { it.key.lowercase() to it.value }.toMap()
|
||||
val result = signHeaders.joinToString("\n") {
|
||||
if (it.startsWith("(")) {
|
||||
specialHeader(it, url, method)
|
||||
} else {
|
||||
generalHeader(it, headers.get(it)!!)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun specialHeader(fieldName: String, url: URL, method: HttpMethod): String {
|
||||
if (fieldName != "(request-target)") {
|
||||
throw IllegalArgumentException(fieldName + "is unsupported type")
|
||||
}
|
||||
return "(request-target): ${method.value.lowercase()} ${url.path}"
|
||||
}
|
||||
|
||||
private fun generalHeader(fieldName: String, value: String): String = "$fieldName: $value"
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package dev.usbharu.hideout.service.signature
|
||||
|
||||
import java.security.PrivateKey
|
||||
import java.security.PublicKey
|
||||
|
||||
data class Key(
|
||||
val keyId: String,
|
||||
val privateKey: PrivateKey,
|
||||
val publicKey: PublicKey
|
||||
)
|
||||
@@ -1,6 +0,0 @@
|
||||
package dev.usbharu.hideout.service.signature
|
||||
|
||||
data class Sign(
|
||||
val signature: String,
|
||||
val signatureHeader: String
|
||||
)
|
||||
@@ -1,23 +0,0 @@
|
||||
package dev.usbharu.hideout.service.signature
|
||||
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.http.*
|
||||
|
||||
data class SignedRequest(
|
||||
val url: String,
|
||||
val method: HttpMethod,
|
||||
val headers: Headers,
|
||||
val requestBody: String,
|
||||
val sign: Sign
|
||||
) {
|
||||
fun toRequestBuilder(): HttpRequestBuilder {
|
||||
val httpRequestBuilder = HttpRequestBuilder()
|
||||
httpRequestBuilder.url(this.url)
|
||||
httpRequestBuilder.method = this.method
|
||||
httpRequestBuilder.headers {
|
||||
this.appendAll(headers)
|
||||
}
|
||||
httpRequestBuilder.setBody(requestBody)
|
||||
return httpRequestBuilder
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user