Updated value in secret column does not get encrypted
timreibe opened this issue · comments
Hi everyone,
following my setup in #73, I have a secret value stored in secret_column
, which is encrypted at insert.
Now, when updating the value, I expect it to be encrypted again, but it won't. Edit: It is stored as clear text.
Is this behavior expected, or is this, again, an issue I have with supabase?
Kind regards
Tim
edit: I added the database setup scripts in my comment below
As a workaround, I created an update trigger, which sets a new key_id
and nonce
and encryptes the secret value again with both.
- Setup Database
In this case, I have a column namedowner
which references to my (supabase) users table.
CREATE TABLE table_name1 (
id uuid PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
owner uuid NOT NULL REFERENCES auth.users (id),
key_id uuid NOT NULL REFERENCES pgsodium.key(id) DEFAULT (pgsodium.create_key()).id,
nonce bytea NOT NULL DEFAULT pgsodium.crypto_aead_det_noncegen(),
secret_column text NOT NULL DEFAULT 'undefined'::text
);
SECURITY LABEL FOR pgsodium
ON COLUMN table_name1.secret_column
IS 'ENCRYPT WITH KEY COLUMN key_id NONCE nonce ASSOCIATED owner';
CREATE VIEW decrypted_table_name1 AS
SELECT id,
convert_from(pgsodium.crypto_aead_det_decrypt(
pg_catalog.decode(secret_column, 'base64'),
pg_catalog.convert_to(owner::text, 'utf8'),
key_id::uuid,
nonce
), 'utf8') AS secret_column
FROM table_name1;
- Create Trigger
create or replace function set_table_name1_pgsodium_values()
returns trigger
as
$$
begin
new.key_id := (pgsodium.create_key()).id;
new.nonce := pgsodium.crypto_aead_det_noncegen();
new.secret_column := pg_catalog.encode(
pgsodium.crypto_aead_det_encrypt(
pg_catalog.convert_to(new.secret_column, 'utf8'),
pg_catalog.convert_to(old.owner::text, 'utf8'),
new.key_id,
new.nonce
),
'base64');
return new;
end ;
$$
language plpgsql;
create trigger trg_set_table_name1_pgsodium_values
before update
on table_name1
for each row
execute procedure set_table_name1_pgsodium_values();
Now, when updating the value, I expect it to be encrypted again, but it won't.
What do you mean "it won't"? Does the updated data is written in clear text/bytea?
Here is a similar Q+A if it could help: #61 (comment)
Hi @ioguix, the updated data is written in clear text and not encrypted.
Thanks for the Q&A, so to trigger the encryption correctly, I have to update the value via the decrypted view, correct? Is there any advantage/disadvantage over having a trigger that encrypts the value on an update call?
Another thing is: I'd like to update the key_id
and nonce
on every change of the secret column, can I somehow integrate this in an alternative way than using an update trigger?
Hi,
I have to update the value via the decrypted view, correct?
Not necessarily if you don't build the new value with the old one.
I have no idea why your trigger does not fire:
76=# select secret_column, decrypted_secret_column from decrypted_table_name1 ;
secret_column | decrypted_secret_column
--------------------------------------------------+-------------------------
ke6mSPa146SZZFdMa+8bJzN8bHjg/sC45oGEUk3UzNRsX21/ | chut
(1 row)
76=# update table_name1 set secret_column = 'chuuuuuut';
UPDATE 1
76=# select secret_column, decrypted_secret_column from decrypted_table_name1 ;
secret_column | decrypted_secret_column
----------------------------------------------------------+-------------------------
9ubE1JtNuXWxtslVDdzv68vFKUaiu7bponbkMaIcWmRujdv+mSZjD5g= | chuuuuuut
(1 row)
I don't understand either why you create the decrypted_table_name1
view yourself as pgsodium is supposed to build it for you.
That the decrypted view is not generated dynamically seems to be related with my supabase setup again. Some others had the same issue: supabase/supabase#11209. This might be an issue with the supabase version my project is built with. On a new project, pgsodium just works flawlessly - also the value update! Now I have to figure out how I can upgrade my project.
Thank you @ioguix