Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated value in secret column does not get encrypted #76

Closed
timreibe opened this issue Feb 9, 2023 · 5 comments
Closed

Updated value in secret column does not get encrypted #76

timreibe opened this issue Feb 9, 2023 · 5 comments

Comments

@timreibe
Copy link

timreibe commented Feb 9, 2023

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

@timreibe
Copy link
Author

timreibe commented Feb 9, 2023

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 named owner 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();

@ioguix
Copy link
Collaborator

ioguix commented Feb 10, 2023

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)

@timreibe
Copy link
Author

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?

@ioguix
Copy link
Collaborator

ioguix commented Feb 10, 2023

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.

@timreibe
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants