Encrypting a field via select/update from another field

29 Views Asked by At

I am having a problem with encrypting a field. Have tried different methods but seem to be hitting a wall. New to postgres psql, so probably really stupid logical mistake, but... Either run into: HINT: No function matches the given name and argument types. You might need to add explicit type casts. or: ERROR: function encrypt(text, unknown, unknown) does not exist

Lets create a table:

create table test_table (t_unencrypted text, t_encrypted bytea);

insert data into it:

insert into test_table (t_unencrypted) values ('Brown fox hopped over the blue fence');

Now lets see if we can get value from one column and encrypt it into another column:

update test_table set t_encrypted = encrypt(t_unencrypted,'A0000000000000000000000000000001','AES');

Nope:

ERROR:  function encrypt(text, unknown, unknown) does not exist
LINE 1: update test_table set t_encrypted = encrypt(t_unencrypted,'A...
                                            ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

Allright, this did not work, lets try another way:

DO $$
 declare
   unenctxt text;
   enctxt bytea;
 BEGIN
      select t_unencrypted from test_table into unenctxt;
      select into enctxt (select (encrypt(unenctxt, 'A0000000000000000000000000000001', 'AES')));
      insert into test_table (t_encrypted) values (enctxt);
END; $$;

Nope, still no luck:

ERROR: function encrypt(text, unknown, unknown) does not exist

Okay, I give up, lets make sure that it actually works and make it into a procedure and a trigger.

test=# select (encrypt('Brown fox hopped over the blue fence', 'A0000000000000000000000000000001', 'AES'));
                                              encrypt
----------------------------------------------------------------------------------------------------
 \xb5b6bfc073f1cc4a1be4133866c9b8acacb859f192077ff3bbf70927963726026ced37091cbc16786d56e630b32108b4
(1 row)

Yay! So, lets create a trigger and procedure as follows:

test=# CREATE FUNCTION encrypt_txt()
  RETURNS TRIGGER AS
$func$
BEGIN
 NEW.t_encrypted := encrypt(NEW.t_encrypted, 'A0000000000000000000000000000001', 'AES');
 RETURN NEW;
END
$func$ LANGUAGE plpgsql;
CREATE FUNCTION
test=# CREATE OR REPLACE TRIGGER encrypt_data
BEFORE INSERT ON test_table
FOR EACH ROW
EXECUTE PROCEDURE encrypt_txt();
CREATE TRIGGER
test=# insert into test_table (t_unencrypted,t_encrypted) values ('Brown fox hopped over the blue fence','Brown fox hopped over the blue fence');
INSERT 0 1
test=# select * from test_table;
            t_unencrypted             |                                            t_encrypted
--------------------------------------+----------------------------------------------------------------------------------------------------
 Brown fox hopped over the blue fence |
 Brown fox hopped over the blue fence | \xb5b6bfc073f1cc4a1be4133866c9b8acacb859f192077ff3bbf70927963726026ced37091cbc16786d56e630b32108b4

Cool, it works! Now lets insert data via help of a trigger:

test=# insert into test_table (t_encrypted) select t_unencrypted from test_table where t_encrypted is null;
ERROR:  column "t_encrypted" is of type bytea but expression is of type text
LINE 1: insert into test_table (t_encrypted) select t_unencrypted fr...
                                                    ^
HINT:  You will need to rewrite or cast the expression.

Well, crap.

And yes I have tried casting a type via ::, but it makes no actual difference. It seems that when inserting via select the trigger actually does not fire ?

Have also tried trigger for update and different tactics and loops but this post is long already. And there seems to be some logical error on my part.

And yes, I am intentionally using low level encrypt instead of pgp_sym or pgp_pub.

Help ?:)

0

There are 0 best solutions below