Encrypt files for securely uploading in TVB Web GUI

Before uploading your data - which might include personal information even when pseudo-anonymized, because a person's brain scan can be seen as a fingerprint - on a TVB shared web installation (like this one at HBP: https://thevirtualbrain.apps.hbp.eu/user/), you might consider to encrypt data upfront.

In TVB we recommend a public-private key encryption (RSA), where TVB shares the public key with everyone, but keeps the private key securely, so that only TVB knows to decrypt that data.

Unfortunately, RSA by itself is not enough because it can only encrypt limited amounts of data, and TVB input files could grow easily. To solve this problem, the files are encrypted using a symmetric-key encryption algorithm, namely AES, and the password which is used for generating the symmetric key is encrypted using the public key of TVB.

You can find our current public key here: https://www.thevirtualbrain.org/tvb/bin/upload_encryption_public_key

Bellow we describe the encryption algorithm that you should run locally, to be compatible with the way we decrypt data on TVB servers. It is expected that you already have tvb-framework installed (from Pypi or Gihub) in the local Python env used for running this code:

In [1]:
%pylab inline

import pyAesCrypt
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
from tvb.basic.profile import TvbProfile
from tvb.core.adapters.abcuploader import ABCUploader
from tvb.core.services.encryption_handler import EncryptionHandler
Populating the interactive namespace from numpy and matplotlib
In [2]:
# here EDIT you local path to where you downloaded TVB public key (link above)
path_to_public_key = '/Users/me/tvb_data/public_key.pem' 

with open(path_to_public_key, "rb") as key_file:
    public_key = serialization.load_pem_public_key(key_file.read(), backend=default_backend())

First we generate a random password for your files:

In [3]:
pass_size = TvbProfile.current.hpc.CRYPT_PASS_SIZE
password = EncryptionHandler.generate_random_password(pass_size)

The next step is to encrypt the file(s) using the password generated at the previous step ! A single import in TVB which requires more files at uploading (e.g. Connectivity from CSV files) will need to have all files encrypted using the same password.

The encrypted content is saved at the location of the original data.

In [7]:
# EDIT paths to data files here inside the list
paths_to_files = ['/Users/me/tvb_data/connectivity/connectivity_76.zip']

buffer_size = TvbProfile.current.hpc.CRYPT_BUFFER_SIZE

for path in paths_to_files:
  encrypted_file_path = ABCUploader.get_path_to_encrypt(path)
  pyAesCrypt.encryptFile(path, encrypted_file_path, password, buffer_size)

Asynchronously encrypt the password used at the previous step for the symmetric encryption and save it as a file to be uploaded in TVB web GUI:

In [8]:
password_bytes = str.encode(password)
encrypted_password = ABCUploader.encrypt_password(public_key, password_bytes)

# EDIT path for saving the encrypted password
encrypted_password_path = '/Users/me/tvb_data/connectivity/'

ABCUploader.save_encrypted_password(encrypted_password, encrypted_password_path)


Finally, upload both the encrypted data files and the encrypted password file in TVB web GUI:

  • connectivity_76_encrypted.zip
  • encrypted_password.pem
In [ ]: