Encryption Key Rotation
Key rotation is recommended for security. This procedure shows how to encrypt data with an initial version of a key, then create a new key, encrypt all of the data with the new key, and drop the old key. This cycle of steps is a simple solution for rotating keys periodically.
For example, create a staff
table that contains employee ID and social security number (SSN) columns. Assume that the SSN values need to be encrypted and protected from decryption by some users. In this case, both the ID values and the SSN values are unique. If your encrypted table does not have a unique ID, you can generate one by using a sequence.
- Create the
staff
table:
premdb=# create table staff(id bigint, ssn varchar(100));
CREATE TABLE
- Insert some rows:
premdb=# insert into staff values(91234,'111-01-0987');
INSERT 0 1
premdb=# insert into staff values(85673, '222-99-4321');
INSERT 0 1
premdb=# select * from staff;
id | ssn
-------+-------------
91234 | 111-01-0987
85673 | 222-99-4321
(2 rows)
- Create a key:
premdb=# create key ssnkey0 secret '0f5689f32';
CREATE KEY
- Create
staff_ks
, an encrypted version of thestaff
table:
premdb=# create table staff_ks(id bigint, ssn varchar(100));
CREATE TABLE
Note: Make sure the column that will hold encrypted values is wide enough. When a social security number, for example, is encrypted, it will require a much wider column.
- Insert rows into the encrypted table,
premdb=# insert into staff_ks(ssn)
select concat('v0', '-', encrypt_ks(ssn, ssnkey0)) from staff;
INSERT 0 2
premdb=# select * from staff_ks; id | ssn
-------+--------------------
91234 | v0-w70ijTHGijjZrh0
85673 | v0-vBmijvHIizDX|p0
(2 rows)
Use a prefix of the form xy-
for the encrypted strings. In this example, v0-
is the prefix. The hyphen character is never used in encrypted strings, so a prefix that ends with -
is a good choice.
- Decrypt the encrypted values to verify that encryption and decryption are working.
premdb=# select decrypt_ks(substr(ssn,4),ssnkey0) from staff_ks;
decrypt_ks
-------------
111-01-0987
222-99-4321
(2 rows)
- Add some new rows to the
staff
table.
premdb=# truncate table staff;
TRUNCATE TABLE
premdb=# insert into staff values(13579, '451-90-3421');
INSERT 0 1
premdb=# insert into staff values(97684, '455-66-2356');
INSERT 0 1
premdb=# select * from staff;
id | ssn
-------+-------------
13579 | 451-90-3421
97684 | 455-66-2356
(2 rows)
- Create a new key:
premdb=# create key ssnkey1 secret '41f55e912f';
CREATE KEY
premdb=# select * from sys.key;
key_id | name | schema_id | owner_id | creation_time
--------+----------+-----------+----------+-------------------------------
16450 | ssnkey0 | 2200 | 16444 | 2019-11-12 11:52:51.871322-08
16516 | ssnkey1 | 2200 | 16444 | 2019-11-13 13:28:03.204117-08
(4 rows)
- Update the encrypted table, using the new key,
ssnkey1
, for the new rows.
premdb=# insert into staff_ks(id, ssn)
select id, concat('v1', '-', encrypt_ks(ssn, ssnkey1)) from staff;
INSERT 0 2
premdb=# select * from staff_ks;
id | ssn
-------+--------------------
13579 | v1-hHUpDsQqa1yDwA3
97684 | v1-hHUoDAwra5CCzM3
91234 | v0-w70ijTHGijjZrh0
85673 | v0-vBmijvHIizDX|p0
(4 rows)
- Decrypt the rows with a
CASE
expression that applies the appropriate key to thev0
andv1
rows.
premdb=# select id, case left(ssn,3)
when 'v0-' then decrypt_ks(substr(ssn,4), ssnkey0)
when 'v1-' then decrypt_ks(substr(ssn,4), ssnkey1)
else 'missing key'
end
from staff_ks;
id | case
-------+-------------
13579 | 451-90-3421
97684 | 455-66-2356
91234 | 111-01-0987
85673 | 222-99-4321
(4 rows)
- Update the
staff_ks
table so that the original old key,ssnkey0
, is no longer needed. The first update encrypts thev0-
values with the new key and removes thev0
prefix. The second statement removes thev1-
prefix from the rows that are already encrypted with the new key.
premdb=# update staff_ks
set ssn=encrypt_ks(decrypt_ks(substr(ssn,4),ssnkey0),ssnkey1)
where left(ssn,3)='v0-';
UPDATE 2
premdb=# select * from staff_ks;
id | ssn
-------+--------------------
91234 | k1UpDIAqaDiEmI3
85673 | jDkpDsAsaTCCwA3
13579 | v1-hHUpDsQqa1yDwA3
97684 | v1-hHUoDAwra5CCzM3
(4 rows)
premdb=# update staff_ks
set ssn=substr(ssn,4)
where left(ssn,3)='v1-';
UPDATE 2
premdb=# select * from staff_ks;
id | ssn
-------+-----------------
13579 | hHUpDsQqa1yDwA3
97684 | hHUoDAwra5CCzM3
91234 | k1UpDIAqaDiEmI3
85673 | jDkpDsAsaTCCwA3
(4 rows)
- Drop the old key.
premdb=# drop key ssnkey0 cascade;
DROP KEY
Parent topic:Encrypting Sensitive Data