Joe
Joe

Reputation: 11

Postgresql Encryption

I'm learning how to encrypt columns in postgresql and this is my code but i am getting an error when i try to insert values into the table, also i would like to make the function encrypt the data after insert. i dont know why is the reason that this error is coming up. if you guys could help me, i will really appreciate it. its for a school project that im putting together

-- dummy table
CREATE TABLE public.users
(
    id_num smallint NOT NULL,
    username Varchar (50)  NOT NULL,
    password Varchar (50)  ,
    test1 Varchar (50)  ,
    test2 Varchar (50)   ,
    test3 Varchar (50)  ,
    CONSTRAINT users_pkey PRIMARY KEY (id_num)
);

---encryption function 
--postgresql trigger function
CREATE FUNCTION encrypt_solution_testing_function2() 
RETURNS TRIGGER AS
$func$
DECLARE
BEGIN
new.username := PGP_SYM_ENCRYPT(new.username, 'sha1') ;
new.password := PGP_SYM_ENCRYPT(new.password , 'sha1');
new.test1 := PGP_SYM_ENCRYPT(new.test1  , 'sha1')  ;
new.test2:= PGP_SYM_ENCRYPT(new.test2  , 'sha1')  ;
new.test3 := PGP_SYM_ENCRYPT(new.test3 , 'sha1') ;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;  

--before insert trigger but would like to make it, after insert

CREATE TRIGGER encrypt_audit_log_testing2 
BEFORE INSERT ON public.users 
FOR EACH ROW EXECUTE PROCEDURE  encrypt_solution_testing_function2();

error message:

ERROR:  value too long for type character varying(50)
CONTEXT:  PL/pgSQL function encrypt_solution_testing_function2() line 5 at assignment
SQL state: 22001

Upvotes: 1

Views: 1915

Answers (1)

Laurenz Albe
Laurenz Albe

Reputation: 246033

The result of the pgp_sym_encrypt function is not a string, but a binary string (bytea). So if you store the result in a string column, it will be cast to varchar on assignment.

Now the encrypted string can be longer than the clear text, and its string representation is more than double that size:

SELECT octet_length(pgp_sym_encrypt('some string', 'sha1'));

 octet_length 
══════════════
           77
(1 row)

SELECT pgp_sym_encrypt('some string', 'sha1');

                                                                       pgp_sym_encrypt                                                                        
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
 \xc30d040703020df0c213a136973962d23c014bb8a3d8e55a31ad3b64e5a389a2ae5212be75ccc570881f5d191e3f3528f0f98058bde3e30921b87a385b1ce56240e6bad20410eef10ac5a68511
(1 row)

So you should not use varchar(50), but bytea to store the encrypted data.

Also note that the second argument to pgp_sym_encrypt is not a hashing algorithm, but a password:

SELECT pgp_sym_decrypt('\xc30d040703020df0c213a136973962d23c014bb8a3d8e55a31ad3b64e5a389a2ae5212be75ccc570881f5d191e3f3528f0f98058bde3e30921b87a385b1ce56240e6bad20410eef10ac5a68511'::bytea, 'sha1');

 pgp_sym_decrypt 
═════════════════
 some string
(1 row)

Everybody who knows that password can decrypt the data.

Upvotes: 1

Related Questions