Generating the signature (Example)

This page describes by example how you validate the signature of incoming requests

Algorithm

To allow you to validate incoming events, we are signing every request with a signature as part of the header field X-Monta-Signature.

The value has the following format: sha1={signature}

The signature is generated using this algorithm: HMAC-SHA1 with your webhookSecret as key (Bytes) and the request body as input.

Example

Given you have set the following secret for your Webhook config: top-secret

And assuming we are sending this (simplified) payload (Post Body): {"foo": "bar"}

We would generate this signature: sha1=ff401a885877ab7e4665f9e045f9ee2d5876fdb9 and deliver it in the header (X-Monta-Signature).

⚠️

Note: When a JsonNode is serialized back to a String, the resulting output is in compact (minified) JSON format.

Example: {"foo": "bar"} becomes {"foo":"bar"}

Generating the signature (Kotlin)

val secret = "top-secret"  
val payloadString = "{\"foo\": \"bar\"}"
val payload = jacksonObjectMapper().readTree(payloadString) as JsonNode // JSON
val payloadBytes = payload.toString().toByteArray() // Note: mapping from JSON to String will remove white spaces, etc (JSON minify)
val signature = SignRequest.generateSignature(secret, payloadBytes)  
val expectedSignature = "sha1=ff401a885877ab7e4665f9e045f9ee2d5876fdb9"  
expectThat(signature).describedAs("Signatures should match").isEqualTo(expectedSignature)

// Used Methods with outputs

SIGNATURE_ALGORITHM = "HmacSHA1"  
SIGNATURE_PREFIX = "sha-1"

// key = "top-secret", payload = [123, 34, 102, 111, 111, 34, 58, 32, 34, 98, 97, 114, 34, 125]  
fun generateSignature(key: String, payload: ByteArray): String {  
    val signingKey = SecretKeySpec(key.toByteArray(), SIGNATURE_ALGORITHM) // key.toByteArray = [116, 111, 112, 45, 115, 101, 99, 114, 101, 116]  
    val hmac = Mac.getInstance(SIGNATURE_ALGORITHM)  
    hmac.init(signingKey)  
    // hmac.doFinal(payload) = [-41, -9, -5, 0, -109, 71, 1, 67, -91, 123, -61, -102, 61, -97, 11, -74, 31, -90, 113, 49]  
    // hmac.doFinal(payload).toHexString() = "ff401a885877ab7e4665f9e045f9ee2d5876fdb9"  
    return SIGNATURE_PREFIX + hmac.doFinal(payload).toHexString() // "sha1=ff401a885877ab7e4665f9e045f9ee2d5876fdb9"  
}

// converts ByteArray to Hex String  
private fun ByteArray.toHexString(): String {  
    val formatter = Formatter()  
    for (b in this) {  
        formatter.format("%02x", b)  
    }  
    return formatter.toString()  
}

Verify yourself

You can use this endpoint to verify / comprehend how we generate signatures: Generate Signature Details