Skip to content

Conversation & visitor data encryption

Overview

Chat conversation, visitor data and visitor file upload encryption is an extra feature in our service. If it is enabled you can toggle encryption for any room in your company.

When encryption is on, whenever a new chat session is created, an AES key is also generated and stored to two places. A plaintext version of the key is stored in cache with a 90-minute expiration time. Another copy of this key is encrypted with customer provided RSA public key and stored to our database.

During chat session this AES key is used to encrypt all message content. Every time a new chat log is saved to database, the cached AES key is given a new expiration time of 90 minutes. While the cached key exist, all chat logs are automatically decrypted.

Visitor API data values are also encrypted. The AES key used in encryption is different from the one used with chat sessions. This key is also cached but only for 30 minutes. The timer resets on every visitor pageload. An RSA encrypted version of this AES key is stored as an API data entry with name _encrypted_aes_key.

Symmetric AES encryption

Our implementation of AES encryption uses https://github.com/pyca/cryptography library maintained by Python Cryptographic Authority (PyCA). We use 256-bit AES keys and encryption is done in CBC mode.

Keys are stored in json format.

Example of an encryption key

1
2
3
4
5
6
7
8
9
{
    "hmacKey": {
        "hmacKeyString": "4PTHmiELMFxA_O8yYTtl6mhdkNBi01TYSUe8vsD6NV4",
        "size": 256
    },
    "aesKeyString": "gIhuVsdgLYnsko6h-3GTIe2PIkB3W0hyUtQYG0A2WUw",
    "mode": "CBC",
    "size": 256
}

Encrypted data is also signed with a HMAC key. The ciphertext resulting from encryption has following format:

  • First 5 bytes are metadata
  • next 16 bytes are the initialization vector
  • next bytes are the encrypted content
  • last 20 bytes are the signature, which is generated over all the preceding bytes

Please note that the signature is generated over already encrypted data. Before storing the ciphertext it is base64 encoded.

Asymmetric RSA encryption

After generating the AES key it is encrypted with customer's RSA public key and stored. Our implementation uses PyCryptodome's RSA module. RSA key has to be at least 2048-bits long. RSA encryption follows PKCS #1 OAEP standard

How to generate keys?

To generate RSA key pair you can use following openssl commands.

How to generate keys with OpenSSL

1
2
openssl genrsa -des3 -out private.pem 2048
openssl rsa -in private.pem -outform PEM -pubout -out public.pem

These will generate you a RSA key pair and save them to files private.pem and public.pem. Public key from public.pem can be pasted to our public key settings interface as is.

How to decrypt?

While the AES key exists in our cache chat logs are decrypted automatically. After that decryption has to be done by customer.

One way to decrypt your data is to install Giosg Crypter python package and follow the guide it provides. Familiarity with python and our HTTP API and Public HTTP API documentations are recommended.

First install the required dependencies and either use the installed command line tool or create your own script with the python library.

Installing dependencies

1
pip install git+https://github.com/giosg/giosg_crypter.git#egg=giosg.crypter==0.0.1

Command line tool

1
decrypt path/to/your/private/key/file https://url/to/the/chat/<chat_session_id> -t <your_user_api_token>

Create your own script

1
2
3
4
5
6
7
import subprocess
from giosg.crypter import AESKey, asymmetric_decrypt, symmetric_decrypt

private_key = subprocess.check_output(['openssl', 'rsa', '-in', 'path/to/your/private/key/file'])
aes_key = asymmetric_decrypt(private_key, encrypted_key_from_chat_session)
key = AESKey.from_json(aes_key)
decrypted_message = symmetric_decrypt(key, message_field_to_be_decrypted])

Decryption before & after

In case you want or need to implement your own decryption app, here are inputs and outputs to test its functionality

Example input

If you implement your own decryption you can use these keys and inputs to verify that the your decryption code works

Decryption process:

  • Use RSA Private Key (example data 1) to decrypt RSA encrypted AES key (example data 2)
  • If the encryption was successful then the result should be Decrypted AES Key (example data 3)
  • Use Decrypted AES Key (example data 3) to decrypt the AES encrypted message content (example data 4)
  • If the encryption was successful then the result should be AES decrypted message content (example data 5)

Example data 1: Example RSA private key (do not use in production)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAw3XH/gCi6AvM19+lMxl1/AqRWq5PxJyWSBT/UMpjrIUlE/ET
e/aZ2skB8YqT+CPVpNY/2+xUnKhnqwZzoDlkw/vsGeEJLaMCsN3eWzO4IdK9cV6s
gf/XfiJIYgd6QCVAtww7hzn83aoKUyL7fWFvN8s0Bi9OsVLXEyEk3ZqeBeoSPv3b
PZsPjmi3cTxdsSRRsYXItrjxNIu8CD6SxHwrswTwknFzldCQ/GgsTMRblJYb80UM
dZLIJeQuXt948jVwU+OttSmld9jExXDIESjeyH0mUidTjg/w4rKi6DXqdfxevSxq
G/pD1101Zmun8WdtlTPD93V5ZGKRM3H3OiqQUwIDAQABAoIBAQCpJiVzuANCwut7
qcxiA1eqTU7q5cycPlKDgMBOn0dQxkyHDGqrLYaJ4sfuytkwtXou00aiQMwcYlSM
meG4N9LvE/WHk8qIlvg+LVM/I+vmQWS2VpL9UXWgb3SqeQQfvN1bS5e8d79P6NZU
igKPx6Ei7JRSAeCc7i64HEe2CxdTz26cSYjyfPDaS952af1VwVBVBCcb8TIyx5mc
iQBt8PWpw+wTlBxdNeU29ofx49beEQpkmNUKDLCRrP24uGtBo/pRnco6rFCX70lU
CYM1hWqdq85C+s50fRZm5e3bc8UP7RotXjj1s653tCGYCCkfIdb7Q7kMvKgX0EVE
ObmuTQfRAoGBAPkxBwU3drXwBTkrg+VMPSFb3yR27XrWV7pQ/v7VIJQ5W5Od0u/a
xE54dWra+SoFIx+X38pVo6qSOeLM/uyRW90FZKynMBZY5EMWZcVOTjFeOd9LAEI1
6ksYyAYJGW1Vy/g9ocAZVdcI16tkbqrV7vWcOsG2qwlN/c07bYkRo4FZAoGBAMjM
7cMiNru0+0CxoBjPpsWizZcwuxlm5KOLOh7wCHjPS3DT2SKxDHTeEmb8ceu6UlXc
2/fh4SyUOz62GYfXeK/btIr/p5UyA002w7t4V5ZLhsXGvYv4JSpF9EA3EHYxpKcb
SK4QZb7klRZ4zS/Yd8uqujPRKCiYiKUzVnEg1l2LAoGAGHunq+yKHlAJw1cyK0o1
S1zCbMu+g24hym2A0DrSa53DEJrWCbjdxrPxHWGMT4OXstfyJegKH40kYNMxTL7v
XqTUAl6ey+NJ8gl2UE9kQVd3qietS9QOQ/iYVnd4ZxSh6K7tgHk8xNbakb1ZXjGM
u9bwsu2mmlBuWka3eVshTGkCgYEAt+7/3D764/ZkMF6EyDVuDpuSt2tr91jJFwXx
t2UoXYGFGVT1EVIclvDU6oFT2RpTUVN+KxI9sRgXLNqhiE1Xv78BIlIMsB2f6JrB
sHgLwyBr07644f3sDU0G78uAyMOwj2HusYNTsAiyiGMfkTQ4h9dbuRteLdGLWcgs
5nOt6QECgYEAjFEXz78FC9di3jBCbdVHehyzF9aIzEa9+5eqBza2FqFpeAX29wuE
yG245fwb5DmMPl8V33+SdZWpa38W8ruG265Q+cOXkHVhO+h03tQnmiJAzUDE8OpS
hqk8XHdtcOmpX3Zn5i6ewuDewTmfJu6jPcdTsboGPFD0YGf2NpvL7j0=
-----END RSA PRIVATE KEY-----

Example data 2: RSA encrypted AES key

1
2
3
4
5
MyBY7CGGixwKYM88/CBvGT2cN7v3yzldk+YkYjwB92Nyk41cQyFf0eGFZ9DmVXQ0NbACan4v71+z
ulothiDQVQ8I94xTgJmRK16Vu0FhFYfW15grYmVMnnPG9pp0PUFIMd3VWZHKMkkBVmX9l02Irzne
MunalUjKQTCO5HZaJTDIbAIsRiFKAw0bQZyvv5X5WDY1s888WRYXQikJRwqjKYxKqncd6F9dy+6a
0pzNe+ZUNOKST6dc4phWCoxxGXgWcZNG1eTagzM9WScLvJPwkYawQi385oENPzjLU3P477pVjFDm
Hd3KZvEHjJ6IFUgm6FNxee6XsxiYXITSPVxJ0g==

Example data 3: Output RSA decrypted AES key

1
2
3
4
5
6
7
8
9
{
    "hmacKey": {
        "hmacKeyString": "Wf7oZEWQTpspt0g1ZISN0SNFS21w5DdVOp579RqBg20",
        "size": 256
    },
    "aesKeyString": "dIz4N3wn4V3RfRjyteWRS5_fkXzuo8fFP1ZLMgck_wg",
    "mode": "CBC",
    "size": 256
}

Example data 4: AES encrypted message content

1
2
AJxNkp3ZS9McVTYPDyckR7ub7ri5oIObzl0a45t13owvG8ouGfAdfZiosw4hxCgc1iYg88v1xZRL
Ff0/UJr/CcqfCzJjSA4ZWg==

Example data 5: AES decrypted message content

1
The Line is Open!

The other way

Using the giosg Crypter package is recommended as this allows you store the decrypted chats directly on your side / storage which also makes it possible to use shorter data retention time in giosg. If needed, the giosg Decrypt app can be used in cases where you wish to look up chats occasionally, a few chats at the time.