parent
e85e5d10f9
commit
ebe864fd10
|
@ -1,14 +1,11 @@
|
|||
package dev.usbharu.httpsignature.v2
|
||||
|
||||
import dev.usbharu.httpsignature.common.HttpRequest
|
||||
import java.security.PrivateKey
|
||||
|
||||
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 =
|
||||
"${material.label}=" + material.signatureBase.generateSignatureParameterString(signatureParameter)
|
||||
"${material.label}=" + material.signatureBase.generateSignatureParameterString(signatureParameters)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
fun generateSignatureBase(signatureParameter: SignatureParameter): String {
|
||||
fun generateSignatureBase(signatureParameters: List<SignatureParameter>): String {
|
||||
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
|
||||
}
|
||||
|
||||
fun generateSignatureParameterString(signatureParameter: SignatureParameter): String {
|
||||
return listOfNotNull(
|
||||
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\"" },
|
||||
signatureParameter.tag?.let { tag -> "tag=\"$tag\"" },
|
||||
).joinToString(";")
|
||||
fun generateSignatureParameterString(signatureParameters: List<SignatureParameter>): String {
|
||||
return (listOf(
|
||||
list.keys.joinToString(
|
||||
" ",
|
||||
"(",
|
||||
")"
|
||||
)
|
||||
) + signatureParameters.map { "${it.name}=${it.value}" }).joinToString(";")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
package dev.usbharu.httpsignature.v2
|
||||
|
||||
import java.time.Instant
|
||||
|
||||
data class SignatureParameter(
|
||||
val algorithm: String? = null,
|
||||
val keyId: String? = null,
|
||||
val created: Instant? = null,
|
||||
val expires: Instant? = null,
|
||||
val nonce: String? = null,
|
||||
val tag: String? = null,
|
||||
)
|
||||
|
||||
interface SignatureParameter {
|
||||
val name: String
|
||||
val value: String
|
||||
}
|
|
@ -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.time.Instant
|
||||
import java.util.*
|
||||
import kotlin.math.sign
|
||||
|
||||
class GenerateSignatureTest {
|
||||
|
||||
|
@ -64,7 +63,7 @@ class GenerateSignatureTest {
|
|||
|
||||
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" +
|
||||
"\"@signature-params\": (\"host\")"
|
||||
|
@ -74,11 +73,14 @@ class GenerateSignatureTest {
|
|||
|
||||
val expectedSignatureInput = "label=(\"host\")"
|
||||
|
||||
assertEquals(expectedSignatureBase, signatureBase.generateSignatureBase(SignatureParameter()))
|
||||
assertEquals(
|
||||
expectedSignatureBase,
|
||||
signatureBase.generateSignatureBase(SignatureParameters().toParameterList())
|
||||
)
|
||||
assertEquals(expectedSignatureValue, sign.signature)
|
||||
assertEquals(expectedSignatureInput, sign.signatureInput)
|
||||
|
||||
println(signatureBase.generateSignatureBase(SignatureParameter()))
|
||||
println(signatureBase.generateSignatureBase(SignatureParameters().toParameterList()))
|
||||
println(sign.signature)
|
||||
println(sign.signatureInput)
|
||||
}
|
||||
|
@ -129,7 +131,7 @@ class GenerateSignatureTest {
|
|||
"sig"
|
||||
)
|
||||
|
||||
val signatureParameter = SignatureParameter(
|
||||
val signatureParameters = SignatureParameters(
|
||||
algorithm = "rsa-pss-sha512",
|
||||
keyId = "a",
|
||||
created = Instant.ofEpochSecond(1727076643),
|
||||
|
@ -139,7 +141,7 @@ class GenerateSignatureTest {
|
|||
)
|
||||
val sign = signer.sign(
|
||||
material,
|
||||
signatureParameter,
|
||||
signatureParameters.toParameterList(),
|
||||
RsaPssSha512SignatureSigner()
|
||||
)
|
||||
|
||||
|
@ -148,12 +150,12 @@ class GenerateSignatureTest {
|
|||
|
||||
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)
|
||||
|
||||
|
||||
println(sign.signature)
|
||||
println(signatureBase.generateSignatureBase(signatureParameter))
|
||||
println(signatureBase.generateSignatureBase(signatureParameters.toParameterList()))
|
||||
|
||||
|
||||
|
||||
|
@ -174,7 +176,7 @@ class GenerateSignatureTest {
|
|||
val signature = Signature.getInstance("RSASSA-PSS")
|
||||
signature.setParameter(PSSParameterSpec("SHA-512", "MGF1", MGF1ParameterSpec.SHA512, 64, PSSParameterSpec.TRAILER_FIELD_BC))
|
||||
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))
|
||||
|
||||
assertTrue(verify)
|
||||
|
|
Loading…
Reference in New Issue