Skip to content

Commit

Permalink
feat: add validation
Browse files Browse the repository at this point in the history
  • Loading branch information
aripiprazole committed Aug 8, 2023
1 parent 91b0964 commit 4826b8a
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
63 changes: 63 additions & 0 deletions src/main/kotlin/Validate.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
@file:JvmName("OpenSSL")

package br.com.openpix.sdk

import io.ktor.util.*
import java.security.KeyFactory
import java.security.PublicKey
import java.security.Signature
import java.security.spec.X509EncodedKeySpec

/**
* The public key used to verify the signature of the webhook.
*
* @see verify
*/
@Suppress("MaxLineLength")
public const val PUBLIC_KEY: String =
"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlHZk1BMEdDU3FHU0liM0RRRUJBUVVBQTRHTkFEQ0JpUUtCZ1FDLytOdElranpldnZxRCtJM01NdjNiTFhEdApwdnhCalk0QnNSclNkY2EzcnRBd01jUllZdnhTbmQ3amFnVkxwY3RNaU94UU84aWVVQ0tMU1dIcHNNQWpPL3paCldNS2Jxb0c4TU5waS91M2ZwNnp6MG1jSENPU3FZc1BVVUcxOWJ1VzhiaXM1WloySVpnQk9iV1NwVHZKMGNuajYKSEtCQUE4MkpsbitsR3dTMU13SURBUUFCCi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo="

/**
* The certificate used to verify the signature of the webhook.
*
* @see verify
*/
private val publicKey: PublicKey = run {
val base64 = PUBLIC_KEY.decodeBase64String()
.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("\\n", "")
.replace("\n", "")
.replace("-----END PUBLIC KEY-----","")
.decodeBase64Bytes()

KeyFactory
.getInstance("RSA")
.generatePublic(X509EncodedKeySpec(base64))
}

/**
* Verifies the signature of the webhook.
*
* ```java
* String payload;
* String signature;
*
* OpenSSL.verify(payload, signature);
* ```
*
* @param payload The payload of the webhook.
* @param signature The signature of the webhook.
* @return `true` if the signature is valid, `false` otherwise.
*/
public fun verify(payload: String, signature: String): Boolean {
runCatching {
return Signature.getInstance("SHA256withRSA").run {
initVerify(publicKey)
update(payload.toByteArray())

verify(signature.decodeBase64Bytes())
}
}.getOrElse {
return false
}
}
31 changes: 31 additions & 0 deletions src/test/kotlin/ValidateTests.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package br.com.openpix.sdk

import org.assertj.core.api.Assertions.*
import org.junit.jupiter.api.Test

class ValidateTests {
companion object {
@Suppress("MaxLineLength")
const val PAYLOAD: String =
"""{ "pixQrCode": null, "charge": { "status": "COMPLETED", "customer": { "name": "Antonio Victor", "taxID": { "taxID": "12345678976", "type": "BR:CPF" }, "email": "antoniocliente@example.com", "correlationID": "4979ceba-2132-4292-bd90-bee7fb2125e4" }, "value": 1000, "comment": "Pagamento OpenPix", "transactionID": "ea83401ed4834b3ea6f1f283b389af29", "correlationID": "417bae21-3d08-4cdb-9c2d-fee63c89e9e4", "paymentLinkID": "34697ed2-3790-4b60-8512-e7465b142d84", "createdAt": "2021-03-12T12:43:54.528Z", "updatedAt": "2021-03-12T12:44:09.360Z", "brCode": "https://api.openpix.com.br/openpix/openpix/testing?transactionID=ea83401ed4834b3ea6f1f283b389af29" }, "pix": { "charge": { "status": "COMPLETED", "customer": { "name": "Antonio Victor", "taxID": { "taxID": "12345678976", "type": "BR:CPF" }, "email": "antoniocliente@example.com", "correlationID": "4979ceba-2132-4292-bd90-bee7fb2125e4" }, "value": 1000, "comment": "Pagamento OpenPix", "transactionID": "ea83401ed4834b3ea6f1f283b389af29", "correlationID": "417bae21-3d08-4cdb-9c2d-fee63c89e9e4", "paymentLinkID": "34697ed2-3790-4b60-8512-e7465b142d84", "createdAt": "2021-03-12T12:43:54.528Z", "updatedAt": "2021-03-12T12:44:09.360Z" }, "customer": { "correlationID": "9134e286-6f71-427a-bf00-241681624586", "email": "email1@example.com", "name": "Loma", "phone": "+5511999999999", "taxID": { "taxID": "47043622050", "type": "BR:CPF" } }, "payer": { "correlationID": "9134e286-6f71-427a-bf00-241681624586", "email": "email1@example.com", "name": "Loma", "phone": "+5511999999999", "taxID": { "taxID": "47043622050", "type": "BR:CPF" } }, "time": "2021-03-12T12:44:09.269Z", "value": 1, "transactionID": "ea83401ed4834b3ea6f1f283b389af29", "infoPagador": "OpenPix testing" }, "company": { "id": "624f46f9e93f9f521c8308d7", "name": "Pizzaria do José", "taxID": "4722767300014" }, "account": { "clientId": "ZOJ64B9B-ZM1W-89MI-4UCI-OP2LVIU6NY75" } }"""

@Suppress("MaxLineLength")
const val SIGNATURE: String =
"lL2nnXgmLFGgxJ8+jCDguqouU4ucrIxYJcU5SPrJFaNcJajTJHYVldqc/z4YFIjAjtPEALe699WosgPY08W7CLpidvtm06Qwa4YMB0l/DcTS93O91NdSH/adjugEKiOb76Zj/0jB8mqOmWCFYbweOBa17bssuEkd5Lw7Q5L314Y="
}

@Test
fun `verify true`() {
assertThat(verify(PAYLOAD, SIGNATURE)).isTrue()
}

@Test
fun `verify false with payload`() {
assertThat(verify("{ \"payload\": \"invalid\" }", SIGNATURE)).isFalse()
}

@Test
fun `verify false with signature`() {
assertThat(verify(PAYLOAD, "no")).isFalse()
}
}

0 comments on commit 4826b8a

Please sign in to comment.