parent
e85e5d10f9
commit
ebe864fd10
|
@ -1,14 +1,11 @@
|
||||||
package dev.usbharu.httpsignature.v2
|
package dev.usbharu.httpsignature.v2
|
||||||
|
|
||||||
import dev.usbharu.httpsignature.common.HttpRequest
|
|
||||||
import java.security.PrivateKey
|
|
||||||
|
|
||||||
class HttpMessageSignatureSigner {
|
class HttpMessageSignatureSigner {
|
||||||
fun sign(material: Material, signatureParameter: SignatureParameter, signer: SignatureSigner): Signatures {
|
fun sign(material: Material, signatureParameters: List<SignatureParameter>, signer: SignatureSigner): Signatures {
|
||||||
|
|
||||||
val signatureBase = material.signatureBase.generateSignatureBase(signatureParameter)
|
val signatureBase = material.signatureBase.generateSignatureBase(signatureParameters)
|
||||||
val signatureInput =
|
val signatureInput =
|
||||||
"${material.label}=" + material.signatureBase.generateSignatureParameterString(signatureParameter)
|
"${material.label}=" + material.signatureBase.generateSignatureParameterString(signatureParameters)
|
||||||
|
|
||||||
val signature = signer.sign(signatureBase.toByteArray(Charsets.UTF_8), material.privateKey)
|
val signature = signer.sign(signatureBase.toByteArray(Charsets.UTF_8), material.privateKey)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package dev.usbharu.httpsignature.v2
|
||||||
|
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
class InstantSignatureParameter(private val instantName: String, val instant: Instant) : SignatureParameter {
|
||||||
|
override val name: String
|
||||||
|
get() = instantName
|
||||||
|
override val value: String
|
||||||
|
get() = instant.epochSecond.toString()
|
||||||
|
}
|
|
@ -11,24 +11,25 @@ class SignatureBase() {
|
||||||
list[component.componentIdentifier] = component
|
list[component.componentIdentifier] = component
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateSignatureBase(signatureParameter: SignatureParameter): String {
|
fun generateSignatureBase(signatureParameters: List<SignatureParameter>): String {
|
||||||
val signatureBase =
|
val signatureBase =
|
||||||
list.values.joinToString(separator = "",postfix = "\n") { component -> "${component.componentIdentifier}: ${component.componentValue}" }
|
list.values.joinToString(
|
||||||
|
separator = "",
|
||||||
|
postfix = "\n"
|
||||||
|
) { component -> "${component.componentIdentifier}: ${component.componentValue}" }
|
||||||
|
|
||||||
val signatureParams = "\"@signature-params\": " + generateSignatureParameterString(signatureParameter)
|
val signatureParams = "\"@signature-params\": " + generateSignatureParameterString(signatureParameters)
|
||||||
|
|
||||||
return signatureBase + signatureParams
|
return signatureBase + signatureParams
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateSignatureParameterString(signatureParameter: SignatureParameter): String {
|
fun generateSignatureParameterString(signatureParameters: List<SignatureParameter>): String {
|
||||||
return listOfNotNull(
|
return (listOf(
|
||||||
list.keys.joinToString(" ", "(", ")"),
|
list.keys.joinToString(
|
||||||
signatureParameter.algorithm?.let { algorithm -> "alg=\"${algorithm}\"" },
|
" ",
|
||||||
signatureParameter.keyId?.let { keyId -> "keyid=\"$keyId\"" },
|
"(",
|
||||||
signatureParameter.created?.let { created -> "created=${created.epochSecond}" },
|
")"
|
||||||
signatureParameter.expires?.let { expires -> "expires=${expires.epochSecond}" },
|
)
|
||||||
signatureParameter.nonce?.let { nonce -> "nonce=\"$nonce\"" },
|
) + signatureParameters.map { "${it.name}=${it.value}" }).joinToString(";")
|
||||||
signatureParameter.tag?.let { tag -> "tag=\"$tag\"" },
|
|
||||||
).joinToString(";")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,6 @@
|
||||||
package dev.usbharu.httpsignature.v2
|
package dev.usbharu.httpsignature.v2
|
||||||
|
|
||||||
import java.time.Instant
|
interface SignatureParameter {
|
||||||
|
val name: String
|
||||||
data class SignatureParameter(
|
val value: String
|
||||||
val algorithm: String? = null,
|
}
|
||||||
val keyId: String? = null,
|
|
||||||
val created: Instant? = null,
|
|
||||||
val expires: Instant? = null,
|
|
||||||
val nonce: String? = null,
|
|
||||||
val tag: String? = null,
|
|
||||||
)
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package dev.usbharu.httpsignature.v2
|
||||||
|
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
data class SignatureParameters(
|
||||||
|
val algorithm: String? = null,
|
||||||
|
val keyId: String? = null,
|
||||||
|
val created: Instant? = null,
|
||||||
|
val expires: Instant? = null,
|
||||||
|
val nonce: String? = null,
|
||||||
|
val tag: String? = null,
|
||||||
|
) {
|
||||||
|
fun toParameterList(): List<SignatureParameter> {
|
||||||
|
return listOfNotNull(
|
||||||
|
this.algorithm?.let { algorithm -> StringSignatureParameter("alg", algorithm) },
|
||||||
|
this.keyId?.let { keyId -> StringSignatureParameter("keyid", keyId) },
|
||||||
|
this.created?.let { created -> InstantSignatureParameter("created", created) },
|
||||||
|
this.expires?.let { expires -> InstantSignatureParameter("expires", expires) },
|
||||||
|
this.nonce?.let { nonce -> StringSignatureParameter("nonce", nonce) },
|
||||||
|
this.tag?.let { tag -> StringSignatureParameter("tag", tag) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package dev.usbharu.httpsignature.v2
|
||||||
|
|
||||||
|
class StringSignatureParameter(private val stringName: String, private val stringValue: String) : SignatureParameter {
|
||||||
|
override val name: String
|
||||||
|
get() = stringName
|
||||||
|
override val value: String
|
||||||
|
get() = "\"$stringValue\""
|
||||||
|
}
|
|
@ -12,7 +12,6 @@ import java.security.spec.PSSParameterSpec
|
||||||
import java.security.spec.X509EncodedKeySpec
|
import java.security.spec.X509EncodedKeySpec
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.sign
|
|
||||||
|
|
||||||
class GenerateSignatureTest {
|
class GenerateSignatureTest {
|
||||||
|
|
||||||
|
@ -64,7 +63,7 @@ class GenerateSignatureTest {
|
||||||
|
|
||||||
val signer = HttpMessageSignatureSigner()
|
val signer = HttpMessageSignatureSigner()
|
||||||
|
|
||||||
val sign = signer.sign(material, SignatureParameter(), RsaV1_5Sha256SignatureSigner())
|
val sign = signer.sign(material, SignatureParameters().toParameterList(), RsaV1_5Sha256SignatureSigner())
|
||||||
|
|
||||||
val expectedSignatureBase = "\"host\": example.com\n" +
|
val expectedSignatureBase = "\"host\": example.com\n" +
|
||||||
"\"@signature-params\": (\"host\")"
|
"\"@signature-params\": (\"host\")"
|
||||||
|
@ -74,11 +73,14 @@ class GenerateSignatureTest {
|
||||||
|
|
||||||
val expectedSignatureInput = "label=(\"host\")"
|
val expectedSignatureInput = "label=(\"host\")"
|
||||||
|
|
||||||
assertEquals(expectedSignatureBase, signatureBase.generateSignatureBase(SignatureParameter()))
|
assertEquals(
|
||||||
|
expectedSignatureBase,
|
||||||
|
signatureBase.generateSignatureBase(SignatureParameters().toParameterList())
|
||||||
|
)
|
||||||
assertEquals(expectedSignatureValue, sign.signature)
|
assertEquals(expectedSignatureValue, sign.signature)
|
||||||
assertEquals(expectedSignatureInput, sign.signatureInput)
|
assertEquals(expectedSignatureInput, sign.signatureInput)
|
||||||
|
|
||||||
println(signatureBase.generateSignatureBase(SignatureParameter()))
|
println(signatureBase.generateSignatureBase(SignatureParameters().toParameterList()))
|
||||||
println(sign.signature)
|
println(sign.signature)
|
||||||
println(sign.signatureInput)
|
println(sign.signatureInput)
|
||||||
}
|
}
|
||||||
|
@ -129,7 +131,7 @@ class GenerateSignatureTest {
|
||||||
"sig"
|
"sig"
|
||||||
)
|
)
|
||||||
|
|
||||||
val signatureParameter = SignatureParameter(
|
val signatureParameters = SignatureParameters(
|
||||||
algorithm = "rsa-pss-sha512",
|
algorithm = "rsa-pss-sha512",
|
||||||
keyId = "a",
|
keyId = "a",
|
||||||
created = Instant.ofEpochSecond(1727076643),
|
created = Instant.ofEpochSecond(1727076643),
|
||||||
|
@ -139,7 +141,7 @@ class GenerateSignatureTest {
|
||||||
)
|
)
|
||||||
val sign = signer.sign(
|
val sign = signer.sign(
|
||||||
material,
|
material,
|
||||||
signatureParameter,
|
signatureParameters.toParameterList(),
|
||||||
RsaPssSha512SignatureSigner()
|
RsaPssSha512SignatureSigner()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -148,12 +150,12 @@ class GenerateSignatureTest {
|
||||||
|
|
||||||
val expectedSignatureInput = "sig=(\"host\");alg=\"rsa-pss-sha512\";keyid=\"a\";created=1727076643;nonce=\"a\";tag=\"a\""
|
val expectedSignatureInput = "sig=(\"host\");alg=\"rsa-pss-sha512\";keyid=\"a\";created=1727076643;nonce=\"a\";tag=\"a\""
|
||||||
|
|
||||||
assertEquals(expectedSignatureBase, signatureBase.generateSignatureBase(signatureParameter))
|
assertEquals(expectedSignatureBase, signatureBase.generateSignatureBase(signatureParameters.toParameterList()))
|
||||||
assertEquals(expectedSignatureInput, sign.signatureInput)
|
assertEquals(expectedSignatureInput, sign.signatureInput)
|
||||||
|
|
||||||
|
|
||||||
println(sign.signature)
|
println(sign.signature)
|
||||||
println(signatureBase.generateSignatureBase(signatureParameter))
|
println(signatureBase.generateSignatureBase(signatureParameters.toParameterList()))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -174,7 +176,7 @@ class GenerateSignatureTest {
|
||||||
val signature = Signature.getInstance("RSASSA-PSS")
|
val signature = Signature.getInstance("RSASSA-PSS")
|
||||||
signature.setParameter(PSSParameterSpec("SHA-512", "MGF1", MGF1ParameterSpec.SHA512, 64, PSSParameterSpec.TRAILER_FIELD_BC))
|
signature.setParameter(PSSParameterSpec("SHA-512", "MGF1", MGF1ParameterSpec.SHA512, 64, PSSParameterSpec.TRAILER_FIELD_BC))
|
||||||
signature.initVerify(publicKey)
|
signature.initVerify(publicKey)
|
||||||
signature.update(signatureBase.generateSignatureBase(signatureParameter).toByteArray())
|
signature.update(signatureBase.generateSignatureBase(signatureParameters.toParameterList()).toByteArray())
|
||||||
val verify = signature.verify(Base64.getDecoder().decode(sign.signature))
|
val verify = signature.verify(Base64.getDecoder().decode(sign.signature))
|
||||||
|
|
||||||
assertTrue(verify)
|
assertTrue(verify)
|
||||||
|
|
Loading…
Reference in New Issue