How to encrypt() and decrypt() data in widget script?
▪️ Definition - What does Encryption Key mean?
An encryption key is a random string of bits created explicitly for scrambling and unscrambling data. Encryption keys are designed with algorithms intended to ensure that every key is unpredictable and unique.
The longer the key is built in this manner, the harder it is to crack the encryption code. An encryption key is used to encrypt, decrypt, or carry out both functions, based on the sort of encryption software used.
▪️ Definition - What is NaCl?
NaCl (pronounced "salt") is a new easy-to-use high-speed software library for network communication, encryption, decryption, signatures, etc. NaCl's goal is to provide all of the core operations needed to build higher-level cryptographic tools.
IMPORTANT: Python guidelines for generating an Encryption Key
- Generate a NACL encryption key
Install pynacl from your terminal. More info: https://pynacl.readthedocs.io/en/latest/
# generic python command
pip install pynacl
#In python 3.9:
python3 -m pip install pynacl
- Go in a Python console or Python IDLE and do the following:
In the IDLE shell:
>>> import nacl.utils
>>> from base64 import b64encode
>>> b64encode(nacl.utils.random(24)).decode()
# => '31LMNgROjKJVtZYfDoSfY0W4yTQDpzEdV/75UrSlmiU='
In a python script in VS Code (or any other text editor):
import nacl.utils
from base64 import b64encode
encode = b64encode(nacl.utils.random(24)).decode()
print(encode)
The output in the console should look like this:
'zDds1x+hGTUf4hZJj6T6GdEHLZ7sxTCW7QKwuZnVlmY='
OPTIONAL: generate an IV seed to randomize encryption. More info: https://nacl.cr.yp.to/
Install pycrypto
pip install pycrypto
#In python 3.9: (you might need to install C dependencies to install this package)
python3 -m pip install pycrypto
In the python console
>>> from base64 import b64encode
>>> from Crypto import Random
>>> b64encode(Random.new().read(24)).decode()
# => '4EpJWt4NaZi/Nr6GIAqKXSn07iJ8tdug'
STEP 0: Define the values that are required to be encrypted
To transmit data to the widget in a secure way you might need to encrypt it so that they are not accessible from the outside.
Values that need to be encrypted are all sensitive data such as:
- client information
- personal data
- user ids
- account numbers etc
STEP 1: Scope the encryption on both sides
-
First, you need to generate an encryption key. If needed, you can contact [email protected] to generate the encryption key on your behalf, otherwise, you might want to ask your Engineering team to generate the encryption process by following our guidelines.
-
Then you will need to define how the encrypted string will be passed.
How to generate an encryption key in IDLE or in the text editor of your choice?
Important
You will need to use the NaCl encryption software to be able to use the decryption method in the platform
Make sure you have dowloaded PyNaCl in your python environment.
Run the following script in your text editor to get the key:
# ---- ENCRYPTION KEY GENERATION ---- #
import nacl.utils
from base64 import b64encode
from Crypto import Random
encode = b64encode(nacl.utils.random(24)).decode()
print(encode)
#Terminal Output Example: "Odjts2S6KkfjnMPl3e0zPyjb3EAkKWf9"
STEP 2 : Encrypt your data using the Jinja encrypt()
function in the Parsing Helper
encrypt()
function in the Parsing HelperJinja template description
IMPORTANT: to_json
, encrypt()
, decrypt()
are custom Jinja functions and filters developed by ViaSay. You will not find them in the official Jinja documentation.
Variables and parameters description:
data
is the data you want to encrypt
to_json
is an optional filter. It is only needed if data
is a JSON
key
is the Encryption Key that will be shared between encrypt() and decrypt() functions. The key should not be longer than 32 bytes to be supported in this function. It is confidential so do not make it available everywhere. In your use case implementation, it is better to put it in as an input and not directly into your extraction.
'NACL'
: Please do no change this value. NaCL is the encryption library that we use a ViaSay. More information about NaCl : https://nacl.cr.yp.to/ and https://pynacl.readthedocs.io/en/latest/
You will then have two possible cases:
1 - If data
is a string, the Jinja expression will be:
{{ data | encrypt(key, null, 'NACL') }}
We recommend that you follow the same formatting for the encryption process as we use in the Parsing Helper:
{"user": "Chuck",
"key": " ",
"encrypted_data":" ",
"iv":" ",
"encrypted_data_unquoted": " "
}
- Data should be made available in your Jinja values and will be called by its variable name. Here it is "user".
- Key should be passed as a string
2 - If data
is a json, the Jinja expression will be:
{{ data | to_json | encrypt(key, null, 'NACL') }}
Back to our example with "Chuck":
We encrypt this user data in the parsing helper using the Jinja expression:
{{ data | encrypt(key, null, 'NACL') }}
// "user" is the data we want to encrypt in our example
{"user": "Chuck",
"key": "Odjts2S6KkfjnMPl3e0zPyjb3EAkKWf9",
"encrypted_data":" ",
"iv":" ",
"encrypted_data_unquoted": " "
}
Open your parsing helper and copy-paste the following expressions in the Jinja template. Make sure to keep the comments to keep your code clean :
## Jinja template expression
{{ data | encrypt(key, null, 'NACL') }}
{# Encryption: #}
{{ user | encrypt("Odjts2S6KkfjnMPl3e0zPyjb3EAkKWf9", null, 'NACL') }}
## The output result will look like this:
U0kFxO%2F5SJKiEAqWvZwGsW15ZRKY%2BQxq%3AxJICFuyE77I%2FVoTi2b2iuWRZvWqN
The implementation of the encrypt function in the platform will generate a string as follows:
iv:encrypted_data
This is the view in ViaSay's parsing helper:
In the same Template, comment the previous steps and add the quoted expression {{"quoted_result" | unquote}}
:
## Unquote the encrypted result
{# Unquote: #}
{{"U0kFxO%2F5SJKiEAqWvZwGsW15ZRKY%2BQxq%3AxJICFuyE77I%2FVoTi2b2iuWRZvWqN" | unquote}}
## The encrypted_data_unquoted output will look like this
U0kFxO/5SJKiEAqWvZwGsW15ZRKY+Qxq:xJICFuyE77I/VoTi2b2iuWRZvWqN
#You can clean your string and isolate the IV using this expression:
{# Replace #}
{{ "U0kFxO/5SJKiEAqWvZwGsW15ZRKY+Qxq:xJICFuyE77I/VoTi2b2iuWRZvWqN"|replace(":", " ") }}
Within this new encrypted string, extract the two values iv and encrypted_data and add them in your Jinja values as follows:
## The iv key within the encrypted_data_unquoted is:
U0kFxO/5SJKiEAqWvZwGsW15ZRKY+Qxq
## And the encrypted_data is:
xJICFuyE77I/VoTi2b2iuWRZvWqN
## NOTE: we have taken out the ":" sign with a replace() jinja filter before adding
## the values in our Jinja values. You can also do it manually
In the parsing helper:
Finally, in your Parsing Helper you will have a set of expressions that will trigger one after the other (don't forget to comment on the unused expressions as you go. The code will ignore them):
STEP 3 : Decrypt an encrypted string using the decrypt()
Jinja function
decrypt()
Jinja functionThe pattern of the function to decrypt is:
{{ encrypted_data | decrypt(key, iv, 'NACL') | safe}}
If the encrypted string is in the iv:encrypted_data
format then the Jinja function will be
{{ (encrypted_string | unquote).split(":")[1] | decrypt(key, (encrypted_string | unquote).split(":")[0], 'NACL') | safe}}
Let's see the process in action with our example:
Add the decrypt()
expression in your Parsing Helper template. With our example it will look like this:
{# Decryption: #}
{{ encrypted_data | decrypt("Odjts2S6KkfjnMPl3e0zPyjb3EAkKWf9", "U0kFxO/5SJKiEAqWvZwGsW15ZRKY+Qxq", 'NACL') | safe}}
Notice that we have replaced the key
and iv
values directly with the raw inputs as strings.
The output should be the decrypted data. In our case, it is the user name "Chuck":