diff --git a/src/main/kotlin/dev/usbharu/httpsignature/v2/Component.kt b/src/main/kotlin/dev/usbharu/httpsignature/v2/Component.kt index 72eb09c..3768573 100644 --- a/src/main/kotlin/dev/usbharu/httpsignature/v2/Component.kt +++ b/src/main/kotlin/dev/usbharu/httpsignature/v2/Component.kt @@ -3,7 +3,12 @@ package dev.usbharu.httpsignature.v2 interface Component { val componentName: String val componentIdentifier: String - get() = "\"$componentName\":$componentParameter" + get() { + if (componentParameter.isBlank()) { + return "\"$componentName\"" + } + return "\"$componentName\";$componentParameter" + } val componentParameter: String val componentValue: String } diff --git a/src/main/kotlin/dev/usbharu/httpsignature/v2/HttpMessageComponent.kt b/src/main/kotlin/dev/usbharu/httpsignature/v2/HttpMessageComponent.kt index bb181b8..16b0b19 100644 --- a/src/main/kotlin/dev/usbharu/httpsignature/v2/HttpMessageComponent.kt +++ b/src/main/kotlin/dev/usbharu/httpsignature/v2/HttpMessageComponent.kt @@ -1,7 +1,5 @@ package dev.usbharu.httpsignature.v2 -import com.sun.org.apache.xerces.internal.util.XMLChar.trim - class HttpMessageComponent(private val headerName: String, private val headerValues: List) : Component { override val componentName: String get() = headerName.lowercase() diff --git a/src/main/kotlin/dev/usbharu/httpsignature/v2/SignatureBase.kt b/src/main/kotlin/dev/usbharu/httpsignature/v2/SignatureBase.kt index d9acca9..b0da170 100644 --- a/src/main/kotlin/dev/usbharu/httpsignature/v2/SignatureBase.kt +++ b/src/main/kotlin/dev/usbharu/httpsignature/v2/SignatureBase.kt @@ -13,9 +13,9 @@ class SignatureBase() { fun generateSignatureBase(signatureParameter: SignatureParameter): String { val signatureBase = - list.values.joinToString(postfix = "\n") { component -> "${component.componentIdentifier}: ${component.componentValue}\n" } + list.values.joinToString(separator = "",postfix = "\n") { component -> "${component.componentIdentifier}: ${component.componentValue}" } - val signatureParams = "\"@signature-params\":" + generateSignatureParameterString(signatureParameter) + val signatureParams = "\"@signature-params\": " + generateSignatureParameterString(signatureParameter) return signatureBase + signatureParams } diff --git a/src/main/kotlin/dev/usbharu/httpsignature/v2/SignatureBaseBuilder.kt b/src/main/kotlin/dev/usbharu/httpsignature/v2/SignatureBaseBuilder.kt index c446920..db1c9a5 100644 --- a/src/main/kotlin/dev/usbharu/httpsignature/v2/SignatureBaseBuilder.kt +++ b/src/main/kotlin/dev/usbharu/httpsignature/v2/SignatureBaseBuilder.kt @@ -61,6 +61,10 @@ class SignatureBaseBuilder { return this } + fun header(headerName: String,headerValue:String): SignatureBaseBuilder { + return header(headerName, listOf(headerValue)) + } + companion object { fun fromHttpRequest(httpRequest: HttpRequest): SignatureBaseBuilder { val signatureBaseBuilder = SignatureBaseBuilder() diff --git a/src/main/kotlin/dev/usbharu/httpsignature/v2/SignatureParameter.kt b/src/main/kotlin/dev/usbharu/httpsignature/v2/SignatureParameter.kt index fb6d7d7..1597056 100644 --- a/src/main/kotlin/dev/usbharu/httpsignature/v2/SignatureParameter.kt +++ b/src/main/kotlin/dev/usbharu/httpsignature/v2/SignatureParameter.kt @@ -3,10 +3,10 @@ package dev.usbharu.httpsignature.v2 import java.time.Instant data class SignatureParameter( - val algorithm: SignatureAlgorithm?, - val keyId: String?, - val created: Instant?, - val expires: Instant?, - val nonce: String?, - val tag: String?, + val algorithm: SignatureAlgorithm? = null, + val keyId: String? = null, + val created: Instant? = null, + val expires: Instant? = null, + val nonce: String? = null, + val tag: String? = null, ) diff --git a/src/test/kotlin/dev/usbharu/httpsignature/v2/GenerateSignatureTest.kt b/src/test/kotlin/dev/usbharu/httpsignature/v2/GenerateSignatureTest.kt new file mode 100644 index 0000000..3b44b9f --- /dev/null +++ b/src/test/kotlin/dev/usbharu/httpsignature/v2/GenerateSignatureTest.kt @@ -0,0 +1,78 @@ +package dev.usbharu.httpsignature.v2 + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import java.security.KeyFactory +import java.security.interfaces.RSAPrivateKey +import java.security.spec.PKCS8EncodedKeySpec +import java.util.* + +class GenerateSignatureTest { + + val privateKey = Base64.getDecoder().decode( + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDH+8IRQdB9vhej" + + "eNQqwxlIutt4Xxjg3eZ5XYm7KgR4jAT/q7+cfsz2/fVTNwDOBpG2H1YJZRLUsrVI" + + "3Pia8k7oFyemYKEUN6kaKioO5C9hB0TaiTGlxAKI7syitvedH1YtHqf4zvqgtI2y" + + "Lv0NAXja3nUoWZWgZg8ZUHWAGhtHd/BpLiyvlwXAydFHl/eN5u8uCZhQD0bKI5KJ" + + "qi8Vcs59Q13+ZNHFdgvNjeD+Hc2AdOmbB5HrW2wREgd1sygBcZ77sSLyleeel8+d" + + "VkDsq/l4MQV5/0PeOn+PI8pJkyQUpqnExqzku354XW9ZE6XjREgBb9M0AEdyBLk5" + + "+YbZwiqrAgMBAAECggEAIDgmKB7xDDvYFcpIbytHo47B/+ldBL2Q0vTdqn3hLTAX" + + "OL80URj3b25dsVknPrToPO4HhTP3jgp3Z+nR/oS+Gb5r8O5DMBKs9+jbJdMK9G2g" + + "tjoW+ZypcTj9VynLSFEy0nTMndVwTlFIkvCRwcqpl07yk9xQXas+ZixZrJiIKeyW" + + "rCmBDJAjUSknljHDnULxAXvk6K7Y5uqPCv9DQ1362ZopY56H0++9ZMaJwr5PYJMT" + + "QoKVeZCGLvfY29rUrhV0/CvC7cfxrPbSuQ7Tr/WrpxFpz9H/Dnc8uePoUEmMP2GM" + + "ozjXaJDQrzOVMOpn/2uGinmrcR5/8ETsYruGG96kAQKBgQDoS4PyiZ93zTv5Yvo/" + + "aWX5IvieMO/w3kRvsdq0IM27Gd+Ck+0C7WBUqljuU4ql10mp67MFkj7ZmECWCAKa" + + "OfE3NtXKqnRgixDhM4Q7nfolhkN08CxRrYP3dBh7HJMDtb2YzPDdwV+PSbL6AM8o" + + "oOvxjABJQk6CaGdmL8sQwnHwgQKBgQDcZCJbwDyLPJo04dXkhPBWoH5hGjbtsAv9" + + "whhjY9IWFN/0KvJfzfoTWtgCkpYT3wgMYBVp0aTextbg1euim7X+iVL6TRq4QaVk" + + "Jv6dRnNZPrY7MlnXxIXE81z6syVjChrJBWi81s14SDKtGOpvghLiKUR29wvGjfER" + + "jY/X1MxFKwKBgAUyOz9fqLuLUb4gYqysdOV/zMPtIFDpB+rftZ615SQ8Te2j1Xdt" + + "S+xY6yhZog5XpIQyi4yiWtmPOFKi1zwP879icKHZ8kR+l+ARwPF8dS4FtNiWzsb8" + + "9KjCZhHK79bzZ8xVOUYcn0CbS2+gOQIVp3F9yjvZSdxM7ZMxmn9Dej0BAoGBAJuf" + + "ZZeOLfJPz8AJvCSKLr+swrDEdwbtqfn8xYXhJacMBHwAm3dFFhH2stNWOP09HwzG" + + "CDjZnWbl1zOaOrJu61saEurF6Vk0mZoX4vChn6/kFX/FdSVkEuVYx04LlBnUN8e8" + + "txGpSBtoN8h88IXevoDOjRbIKZuB/Tjc0jagf8FTAoGAWW8uXsWS4c2nBGNdodqL" + + "xJHcNZVMenHPqdkm7rHEYdf1sdbM7r7Q+oj0cifhbZwaRG9HiRGUAgJerLGEqe+x" + + "vNeYuKRF3A5xBFUTw/t+XFhUZ1sSyvOordp0uNahQqkAx1UQFWUBCEkG2k/X81fY" + + "trEnKP2IjOJDzoXGvc4TG0w=" + ) + + val pkcS8EncodedKeySpec = PKCS8EncodedKeySpec(privateKey) + val rsaPrivateKey = KeyFactory.getInstance("RSA").generatePrivate(pkcS8EncodedKeySpec) as RSAPrivateKey + + @Test + fun name() { + + + val signatureBase = SignatureBaseBuilder() + .header("Host", "example.com") + .build() + + val material = Material( + signatureBase, + rsaPrivateKey, + "label" + ) + + val signer = HttpMessageSignatureSigner() + + val sign = signer.sign(material, SignatureParameter(), RsaV1_5Sha256SignatureSigner()) + + val expectedSignatureBase = "\"host\": example.com\n" + + "\"@signature-params\": (\"host\")" + + val expectedSignatureValue = + "Qg8lYdN9pjOjHIOmw6rZoAVAThG5iKM/uqhxHmnGJiFLTN2jF+jJmOmfVhSjQQjkxcJPl1Zog2UTmcaXoHaDHXu9QqEm46t36kVSJsR5z+iKlJ9D4Iyx1HXtps0vbVxPLK83IEN9v684UNtbR8Sy9tKQO3o1n3i+nr51Bo8OUZspqmz84MpI7xl/hOU+n0UMTYCK5K6Op0j2uWLtpVqIj+amEoCcx9MRo5Ddsi1t634GLvU0nwes6ZYuUVPIek9c7ENEf4WX4rPKQ3qumBCb5A2lo15/V3x+e96nUrKB/5vmxE1lZHgjNaKMGYvjUGYlqb5YqE/3cAB94nY3ETAuig==" + + val expectedSignatureInput = "label=(\"host\")" + + assertEquals(expectedSignatureBase, signatureBase.generateSignatureBase(SignatureParameter())) + assertEquals(expectedSignatureValue, sign.signature) + assertEquals(expectedSignatureInput, sign.signatureInput) + + println(signatureBase.generateSignatureBase(SignatureParameter())) + println(sign.signature) + println(sign.signatureInput) + } +} \ No newline at end of file