Descriptors encryption

To prevent malicious use of descriptors stolen from api or db descriptor encryption feature can be enabled. If enabled, only encrypted descriptor data will be kept in the database. Descriptors that are passed to save without encryption will be encrypted.

Encrypted descriptors are stored and received in following format: <encrypted_descriptor><tag><nonce><hash>

Descriptors that have already been encrypted before saving must correspond with this format. Only descriptors that were encrypted with the current key and algorithm can be received from the database. When updating face descriptors, all descriptors with different key or algorithm will be deleted. It is assumed that all descriptors can be encrypted with only one key + algorithm pair at once.

Configuring encryption

Encryption can be enabled through the DESCRIPTOR_ENCRYPTION setting.
  • enabled - whether descriptors encryption is enabled or not.

  • algorithm - name of the encryption algorithm used.

  • params - encryption params to specify the encryption key source.

Supported algorithms: aes256-gcm

Encryption params contain the following fields:
  • source - name of encryption key source.

  • key - encryption key or credentials for receiving it

Supported source types: raw, vaultKV

For both raw, vaultKV sources key must be encoded in base64 string

If you use Hashicorp Vault Key/Value storage as your key source, key must contain the following fields:
  • url - url for receiving encryption key

  • token - authentication token

    {
        "enabled": true,
        "algorithm": "aes256-gcm",
        "params": {
            "source": "vaultKV",
            "key": {
                "url": "https://vault.example.com/v1/secret/data/encryption_key",
                "token": "s.XYZ12345"
            }
        }
    }
    

The contents of vault Key/Value storage are expected to be in the following format:

{
"key": "...",
"algorithm": "..."
}

Encryption migration script

To update the existing descriptors in the database you need to run the script called descriptors_encryption.py. It has three options:

Note

The script requires three environment variables to be set regardless of the option you choose:

  • OLD_ENCRYPTION_KEY (might be set to an empty string)

  • NEW_ENCRYPTION_KEY (might be set to an empty string)

  • ENCRYPTION_ALGORITHM (is always mandatory and can not be empty)

1. To encrypt the original descriptors. This option allows you to encrypt all the descriptors in the database if they were not encrypted previously. Already encrypted descriptors will be ignored, so the script may be run several times. If you choose this option, you need to fill in the NEW_ENCRYPTION_KEY variable and leave the OLD_ENCRYPTION_KEY variable empty.

2. To switch to a new encryption key. This option assumes that encryption has already been performed and you possess the existing encryption key which you want to refresh. Already encrypted descriptors will be ignored, so the script might be ran several times. You must specify both OLD_ENCRYPTION_KEY and NEW_ENCRYPTION_KEY.

3. To decrypt the encrypted descriptors. This options will turn the descriptors back to their original state. It will only will only process the encrypted descriptors and leave the original ones unchanged. To run this version of the script, you need to specify the OLD_ENCRYPTION_KEY variable and leave the NEW_ENCRYPTION_KEY variable empty.

Warning

PLEASE MAKE SURE YOU MADE THE DB’s BACKUP BEFORE RUNNING SCRIPT.

Also please note that all three options cause temporary attributes to be cleaned up.

To run the script you need to specify the way to get DB configs from

The default option is to pull settings from the configuration file.

To run the script:

export ENCRYPTION_ALGORITHM=aes256-gcm
export OLD_ENCRYPTION_KEY=B9pFvUkmaN7RFrr3HEC3U/VTHQcOaKTZ5flQyXwP5qo=
export NEW_ENCRYPTION_KEY=3gDyT4o+YlKLV4NZRjP/wznuhgxMI0mNNJWqc782Z9M=
python ./base_scripts/descriptors_encryption.py --config=./configs/myconfig.conf --LUNA_ATTRIBUTES_DB=ATTRIBUTES_DB

OR

python ./base_scripts/descriptors_encryption.py --luna-config=http://127.0.0.1:5070/1 --LUNA_FACES_DB=FACES_DB
 --DATABASE_NUMBER=DATABASE_NUMBER --LUNA_ATTRIBUTES_DB=ATTRIBUTES_DB

Encryption alternatives

When it is not possible to use Luna Platform configure encryption for some reason, an encryption at the database level can be used. Define the descriptor encryption trigger function inside the service database:

CREATE EXTENSION IF NOT EXISTS pgcrypto;

CREATE OR REPLACE FUNCTION vlencrypt()
RETURNS TRIGGER AS $$
BEGIN
    NEW.descriptor := pgp_sym_encrypt_bytea(NEW.descriptor, 'my-secret-key'::text);
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER encrypt_trigger
BEFORE INSERT OR UPDATE ON descriptor
FOR EACH ROW
EXECUTE FUNCTION vlencrypt();

Define the decryption converter function inside the service database:

CREATE OR REPLACE FUNCTION vlconvert(d bytea) RETURNS bytea
LANGUAGE SQL
IMMUTABLE
PARALLEL SAFE
RETURN pgp_sym_decrypt_bytea(d, 'my-secret-key'::text);

As function & trigger creation have completed, make sure the service is restarted to work correctly.

Note

The above alternative encryption approach can be used for face attributes, but not for temporaty attributes.