---
title: Security
slug: analysis/security
docTags: 
createdAt: 2025-02-25T14:08:30.064Z
---

# Data encryption

Klavi supports two methods: **plaintext&#x20;**&#x61;nd **AES 256 algorithm&#x20;**&#x66;or sensitive information. Partners can choose according to your actual situation in the [Console](https://console.klavi.ai). The decryption key for AES is the `secretKey` generated by Klavi for you.

AES 256 encryption example:

```python
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
import base64

def aes_encrypt(plain_text, key):
    iv = get_random_bytes(16)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    encrypted_data = cipher.encrypt(pad(plain_text.encode('utf-8'), AES.block_size))
    encrypted_message = base64.b64encode(iv + encrypted_data).decode('utf-8')    
    return encrypted_message
```

AES 256 decryption example:

```python
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
import base64

def aes_decrypt(encrypted_message, key):
    encrypted_bytes = base64.b64decode(encrypted_message)
    iv = encrypted_bytes[:16]
    ciphertext = encrypted_bytes[16:]
    cipher = AES.new(key, AES.MODE_CBC, iv)
    padded_plaintext = cipher.decrypt(ciphertext)
    plaintext = unpad(padded_plaintext, AES.block_size).decode('utf-8')
    return plaintext
```

***

# HMAC verification for events

Klavi defaults to using the `secretkey` and **SHA-256 HMAC** algorithm to sign the payload.

The following parameter will be included in the request **header** that Klavi `POST` to you, otherwise it will not be present.

```html
X-Klavi-Signature: 11fad26ccd04a59085a738b8e20be5f4e01887a3c5cdc88cd37bf431e843083e
X-Klavi-Timestamp: 1740716924
```

We recommend that you verify the signature of the webhook.

Tips for Best Practice:

::::WorkflowBlock
:::WorkflowBlockItem
Create a SHA-256 HMAC of the request body using your `secretKey` as the key
:::

:::WorkflowBlockItem
Compare it to the signature included on the `X-Klavi-Signature` header. If the two are equal then the request is valid, otherwise, it is spoofed.
:::

:::WorkflowBlockItem
Store the `eventId` and ignore webhooks with an ID that have already been processed to prevent replay attacks.
:::
::::

:::hint{type="info"}
The `X-Klavi-Signature` and `X-Klavi-Timestamp` header gets added to every event sent.
:::

***

# Allowed IP Addresses

To ensure webhook notifications reach your webhook listener server, you must add the following Klavi IP addresses to your firewall’s allowlist:

| **Environment** | **IP Address** |
| --------------- | -------------- |
| Sandbox         | 18.231.92.86   |
| Testing         | 18.231.92.86   |
| Production      | 18.230.43.17   |

:::hint{type="info"}
No matter how you receive shared data, the export IP addresses for Klavi's various environments are as shown above. If partners have stricter security requirements, you can only allow access to the above IP addresses.
:::

