Project: YugabyteDB (App Definition and Development / Database)
File: column-level-encryption.md

title: Column-level encryption headerTitle: Column-level encryption linkTitle: Column-level encryption description: Using column-level encryption in a YugabyteDB cluster. headcontent: Enable encryption at rest with a user-generated key menu: v2.18: identifier: column-level-encryption parent: secure weight: 745 type: docs <ul class="nav nav-tabs-alt nav-tabs-yb"> <li > <a href="../column-level-encryption/" class="nav-link active"> <i class="icon-postgres" aria-hidden="true"></i> YSQL </a> </li> </ul> YugabyteDB provides column-level encryption to restrict access to sensitive data like addresses and credit card details. YugabyteDB uses the PostgreSQL `pgcrypto` extension to enable column-level encryption, `PGPSYMENCRYPT` and `PGPSYMDECRYPT` functions of pgcrypto extension is used to encrypt and decrypt column data. Steps for enabling symmetric column encryption in YugabyteDB. Open the YSQL shell (ysqlsh), specifying the `yugabyte` user and prompting for the password. ```sh $ ./ysqlsh -U yugabyte -W ``` When prompted for the password, enter the `yugabyte` user password. You should be able to log in and see a response similar to the following: ```output ysqlsh (11.2-YB-2.5.0.0-b0) Type "help" for help. yugabyte=# ``` ```sql \c yugabyte yugabyte; ``` ```output You are now connected to database "yugabyte" as user "yugabyte". ``` Enable the `pgcrypto` extension on the YugabyteDB cluster: ```sql create extension if not exists pgcrypto; ``` Create the `employees` table, and insert data into the table using the `PGPSYMENCRYPT` function for columns that need to be encrypted. First, create the table: ```sql create table employees ( empno int, ename text, address text, salary int, account_number text ); ``` Next, encrypt account numbers in the `employees` table using the `PGPSYMENCRYPT` function: ```sql insert into employees values (1, 'joe', '56 grove st', 20000, PGPSYMENCRYPT('AC-22001', 'AES_KEY')); insert into employees values (2, 'mike', '129 81 st', 80000, PGPSYMENCRYPT('AC-48901', 'AES_KEY')); insert into employees values (3, 'julia', '1 finite loop', 40000, PGPSYMENCRYPT('AC-77051', 'AES_KEY')); ``` Review the encrypted `account_number` data, as shown below: ```sql select ename, account_number from employees limit 1; ``` ```output ename | account_number -+- joe | \xc30d04070302ee4c6d5f6656ace96ed23901f56c717d4e 162b6639429f516b5103acebc4bc91ec15df06c30e29e6841f4a5386 e7698bfebb49a8660f9ae4b3f34fede3f28c9c7bb245bd (1 rows) ``` Decrypt the account numbers using the `PGPSYMDECRYPT` function as shown here. In order to retrieve the encrypted column data, use `PGPSYMDECRYPT` function to decrypt the data. The Decryption function needs to be used in both SELECT and WHERE clause depending on the query. To allow the decryption, the field name is also cast to the binary data type with the syntax: `account_number::bytea`. ```sql select PGPSYMDECRYPT(accountnumber::bytea, 'AESKEY') as AccountNumber from employees; ``` ```output accountnumber AC-22001 AC-48901 AC-77051 (3 rows) ``` Asymmetric Encryption, also known as Public-Key cryptography can be used with YugabyteDB for enabling column-level encryption. YugabyteDB can be configured with generated public/private keys or corporate GPG keys for encrypting column

The example below walks through configuring YugabyteDB cluster with a new set of keys (public and private). Start by generating a new public and private RSA key pair using the `gpg` key generator: ```sh $ gpg --gen-key ``` After going through the configuration prompts, an RSA key gets generated: ```output public and secret key created and signed. pub rsa2048 2020-11-09 [SC] [expires: 2022-11-09] 043E14210E7628F93383D78EA2969FF91871CE06 uid ybadmin <ybadmin@yugabyte.com> sub rsa2048 2020-11-09 [E] [expires: 2022-11-09] ``` Next, export the public and private keys of the newly generated RSA key: Private Key ```sh $ gpg --export-secret-keys \ --armor 043E14210E7628F93383D78EA2969FF91871CE06 > ./private_key.txt ``` Public Key ```sh $ gpg --export --armor 043E14210E7628F93383D78EA2969FF91871CE06 > ./public_key.txt ``` Open the YSQL shell (ysqlsh), specifying the `yugabyte` user and prompting for the password. ```sh $ ./ysqlsh -U yugabyte -W ``` When prompted for the password, enter the `yugabyte` user password. Enable the `pgcrypto` extension on the YugabyteDB cluster: ```sql create extension if not exists pgcrypto; ``` Create the `employees` table and insert data into the table using the generated public key for encrypting column data ```sql create table employees ( empno int, ename text, address text, salary int, account_number text ); ``` In this example, account numbers of `employees` table are encrypted using the `pgppubencrypt` function and the generated Public key. ```sql insert into employees values (1, 'joe', '56 grove st', 20000, PGPPUBENCRYPT('AC-22001', dearmor('--BEGIN PGP PUBLIC KEY BLOCK-- XXXX --END PGP PUBLIC KEY BLOCK--'))); insert into employees values (2, 'mike', '129 81 st', 80000, PGPPUBENCRYPT('AC-48901', dearmor('--BEGIN PGP PUBLIC KEY BLOCK-- XXXX --END PGP PUBLIC KEY BLOCK--'))); insert into employees values (3, 'julia', '1 finite loop', 40000, PGPPUBENCRYPT('AC-77051', dearmor('--BEGIN PGP PUBLIC KEY BLOCK-- XXXX --END PGP PUBLIC KEY BLOCK--'))); ``` Verify that the data for the column `account_number` is encrypted as shown below. ```sql select ename, account_number from employees limit 1; ``` ```output ename | account_number -+ julia | \xc1c04c039bd2f02876cc14ae0107ff44e68e5a4bb35784b426f4aeb46 70976127d64e731cf8f70343b100ea0ed60b3de191fa19e245c4ce9b0289e44b53b 7d3c42b8187487b3b0bb8ebed518a248ca3c1d663174d1c9d6769f7840ddbd8508d d4b91dcf77183779ff15b003431a7d05a1aef4b09313b602bcc2491cc2e417d5c39 269230e032252547ce1fd51f27be0cc43c5fd75f35b21e0a72e8e (1 row) ``` Use `pgppubdecrypt` and the private key to decrypt column data. To retrieve the encrypted column data, use the `pgppubdecrypt` function to decrypt the data and wrap the PGP private key with the `dearmor` function to convert the private key into PGP ASCII-armor format. The Decryption function needs to be used in both SELECT and WHERE clauses, depending on the query. To allow the decryption, the field name is also cast to the binary data type with the syntax: `account_number::bytea`. ```sql select PGPPUBDECRYPT(account_number::bytea,dearmor('--BEGIN PGP PRIVATE KEY BLOCK-- XXXX --END PGP PRIVATE KEY BLOCK--'),'PRIVATE-KEY-PASSWORD') as AccountNumber from employees; ``` ```output accountnumber AC-22001 AC-48901 AC-77051 (3 rows) ```