[HACKERS] Functions + plpgsql + contrib/pgcrypto = ??

2005-03-24 Thread Moran.Michael
Hello there,
 
What's the preferred and most efficient way to obtain PGCrypto encrypted
data from a plpgsql function?
 
1. Imagine the following simple table:
 
CREATE TABLE crypto (
pid SERIAL PRIMARY KEY,
title  VARCHAR(50),
crypted_content  BYTEA
);
 
 
2. Now insert the following 3 rows of data:
INSERT INTO crypto VALUES (1, 'test1', encrypt( 'ABCD', 'password',
'aes'));
INSERT INTO crypto VALUES (2, 'test2', encrypt( 'BCDE', 'password',
'aes'));
INSERT INTO crypto VALUES (3, 'test3', encrypt( 'CDEF', 'password',
'aes'));
 
 
3. Using the psql tool, selecting * from the crypto table yields the
following:
 
# select * from crypto;
 id | title |crypted_content
+---+
  1 | test1 | \307\266xI\235\210a\363=\201\222\247\2660\215
  2 | test2 | D\211\256E\372^Y\0259\341\215\271\030]\234\017
  3 | test3 | 4\263\251y\006_N\343\0270I\207;\370\270\266

 
Pretty straight forward, right? 
 
Now how about doing this in a simple plpgsql Function. That's where we
encounter problems. I want to get DECRYPTED data based on an input ID. So...
 
 
4. Imagine the following simple plpgsql function (note I'm trying to decrypt
the table's encrypted BYTEA column into a decrypted VARCHAR upon return):
 
 
CREATE OR REPLACE FUNCTION selectFromCrypto(INTEGER)
RETURNS VARCHAR
AS '
DECLARE
crypto_cursor   CURSOR (input INTEGER) FOR SELECT
encode(decrypt(crypted_content, decode(''password''::text,
''escape''::text), ''aes''::text), ''escape''::text) FROM crypto WHERE id =
input;
crypto  crypto.crypted_content%TYPE;
tid ALIAS FOR $1;
 
BEGIN
OPEN crypto_cursor( tid );
LOOP
FETCH crypto_cursor INTO crypto;
EXIT WHEN NOT FOUND;
END LOOP;
CLOSE crypto_cursor;
RETURN ( encode(crypto, ''escape''::text)::VARCHAR );
END;
' LANGUAGE 'plpgsql';

 
5. When I use the above function (in the tool, psql) to get the decrypted
contents for ID = 2, it says I get 1 row returned, but the contents are
blank:
 
# select * from selectFromCrypto(1);
 selectfromcrypto1
---
 
 
(1 row)

 
Notice the blank row returned... So what am I doing wrong?
 
I suspect it has something to do with
converting/encoding/decoding/decrypting the BYTEA column for return... but
what is the problem with the above Function?
 
I'm using PostgreSQL 7.4.6, on a Fedora Core 1 system.
 
 
Best regards and thank you very much in advance,
Michael Moran
 

---(end of broadcast)---
TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]


[HACKERS] Calling Functions from Delete Rule (+ contrib/pgcrypto) = madness ??

2005-03-24 Thread Moran.Michael
Hello there,
 
I have a View with a Delete rule and I would like the Delete rule to call a
function (and pass-in a few of the the underlying View's/Table's column
values). How do you do this?
 
When I do it, I keep getting the following error:
ERROR:  function expression in FROM may not refer to other relations of same
query level
 
This is my new Delete View that attempts to call a Function but yields the
above-mentioned error:
 
CREATE RULE crypto_view_delete_rule
AS ON DELETE
TO crypto_view
DO INSTEAD
--Original (working) code:
--  DELETE FROM crypto
-- WHERE id = OLD.id;

--NEW (non-working) code:
select * from func_delFromCrypto( crypto.id, encode( decrypt(
crypto.crypted_content, decode ('password'::text, 'escape'::text),
'aes'::text), 'escape'::text) );

 
The above may seem complicated, but the crypto portion DOES work (as you'll
see below), and I've broken down the steps below so that it's easy to see
what's going on:
 
 
1. Imagine the following simple table:
 
CREATE TABLE crypto (
id SERIAL PRIMARY KEY,
title VARCHAR(50),
crypted_content BYTEA
);
 
 
2. Imagine the following simple working View:
 
CREATE VIEW crypto_view AS
  SELECT
id,
title,
--Decrypt the BYTEA column and convert result to TEXT type:
encode(decrypt(crypted_content, decode('password','escape'::text),
'aes'::text), 'escape'::text) as crypted_content
  FROM
crypto;
 
 
3. Imagine my original, simple Delete Rule (that works -- it was my original
version prior to changing it to call the Function):
 
CREATE RULE crypto_view_delete_rule
AS ON DELETE
TO crypto_view
DO INSTEAD
DELETE FROM crypto
WHERE id = OLD.id;
 
 
4. Let's load (and encrypt) some test data into the above-mentioned table:
 
insert into crypto VALUES (1, 'test1', encrypt('', 'password',
'aes') );
insert into crypto VALUES (2, 'test2', encrypt('', 'password',
'aes') );
insert into crypto VALUES (3, 'test3', encrypt('', 'password',
'aes') );
insert into crypto VALUES (4, 'test4', encrypt('', 'password',
'aes') );
insert into crypto VALUES (5, 'test5', encrypt('', 'password',
'aes') );

 
5. Let's SELECT from the table to see its contents (note the encrypted
values):
 
select * from crypto;
 id | title |  crypted_content
+---+
  1 | test1 | \026\206I93\327\315\376t\243\006~J\177{\301
  2 | test2 | \257\212\260\321\217\274c\210d \361\225\212\327\317\206
  3 | test3 | 6\345:\224dp\002\206\007k\344\302\347V\214
  4 | test4 | VH)\023\303\0239\363\323\362\22734\204R\357
  5 | test5 | \216Np\235\026\362\277\246\026\027\221\266\021\361\224\256
(5 rows)
 
 
6. Let's run the View (which nicely decrypts the encrypted columns):
 
# select * from crypto_view;
 id | title | crypted_content
+---+-
  1 | test1 | 
  2 | test2 | 
  3 | test3 | 
  4 | test4 | 
  5 | test5 | 
(5 rows)
 
 
7. Let's test the old DELETE RULE (the one that doesn't call a function,
hence works):
 
delete from crypto_view where crypted_content = ;
DELETE 1
 
 
Check that the DELETE RULE worked (there is one less row of data now):
# select * from crypto_view;
 id | title | crypted_content
+---+-
  1 | test1 | 
  2 | test2 | 
  3 | test3 | 
  4 | test4 | 
(4 rows)

 
It works! Pretty straight forward, right?
 
Now let's make things a little more interesting...
 
 
8. Now here is the following (working) function that I want my rule to call:
 
CREATE OR REPLACE FUNCTION func_delFromCrypto(INTEGER, VARCHAR)
RETURNS INTEGER
AS '
DECLARE
_id ALIAS FOR $1;
_crypto_dataALIAS FOR $2;
ret INTEGER:=0;
BEGIN
DELETE FROM crypto WHERE id = _id AND encode( decrypt( crypted_content,
decode(''password''::text, ''escape''::text), ''aes''::text),
''escape''::text) = _crypto_data;
GET DIAGNOSTICS ret = ROW_COUNT;
RETURN ret;
END;
' LANGUAGE 'plpgsql';
 
 
9. The function works, stand-alone, as you can see below:
 
# select * from func_delFromCrypto(4, '');
 func_delfromcrypto

  1
(1 row)
 
 
Check the output (there is one less row now):
 
# select * from crypto_view;
 id | title | crypted_content
+---+-
  1 | test1 | 
  2 | test2 | 
  3 | test3 | 
(3 rows)
 
 
 
So the function works, stand-alone. But how can I get my Delete Rule to call
it?
 
I want my Delete Rule to pass in the underlying ID (the primary key) and the
crypted_content into the Function (like you can when calling the Function
stand-alone).
 
 
Once again, here is my new DELETE RULE that calls the function (and fails):
 
CREATE RULE crypto_view_delete_rule
AS ON DELETE
TO crypto_view
DO INSTEAD
--Original (working) code:
--  DELETE FROM crypto
-- WHERE id = OLD.id;

--NEW (non-working) code:

[HACKERS] contrib/pgcrypto

2005-03-16 Thread Moran.Michael
Hello,

How do you encrypt()  decrypt() data of types INT4 or DATE?

The PGCrypto methods encrypt() and decrypt() each take BYTEA as input:

i.e.,
encrypt( data::bytea, key::bytea, type::text)
decrypt( data::bytea, key::bytea, type::text)

So how do you convert INT4 and DATE data into BYTEA so that they can be
passed as input into the PGCrypto methods encrypt()  decrypt()?

Thank you,
Michael Moran




---(end of broadcast)---
TIP 6: Have you searched our list archives?

   http://archives.postgresql.org


[HACKERS] How to cast VARCHAR to BYTEA and vice-versa?

2005-03-08 Thread Moran.Michael
Hello all,
 
I have a table with a VARCHAR column that I need to convert to a BYTEA.
 
How do I cast VARCHAR to BYTEA?
 
The following doesn't seem to work as it yields the 'cannot cast varchar to
bytea' error message:
 
varchar_data::bytea
 
On the same topic, how do I do the reverse, that is, how to I cast from
BYTEA back to VARCHAR?
 
Thanks,
-Michael Moran
 

---(end of broadcast)---
TIP 3: if posting/reading through Usenet, please send an appropriate
  subscribe-nomail command to [EMAIL PROTECTED] so that your
  message can get through to the mailing list cleanly


Re: [HACKERS] How to cast VARCHAR to BYTEA and vice-versa?

2005-03-08 Thread Moran.Michael
Thank you, Tom.
 
Yes, the exact bytes in the varchar datum (without encoding) is what I would
like to become the bytes in the BYTEA.
 
So, how do I create a cast WITHOUT FUNCTION as you mention below? I assume
plpgsql is required, right?
 
Is there anyway this can be done in a VIEW without having to use plpgsql in
a Function (a.k.a. stored procedure)?
 
Is there no simple cast or conversion method I can call that does this for
me?
 
Best Regards,
Michael Moran
 

  _  

From: Tom Lane [mailto:[EMAIL PROTECTED]
Sent: Tue 3/8/2005 9:18 AM
To: Moran.Michael
Cc: pgsql-hackers@postgresql.org
Subject: Re: [HACKERS] How to cast VARCHAR to BYTEA and vice-versa? 



Moran.Michael [EMAIL PROTECTED] writes: 
 How do I cast VARCHAR to BYTEA? 

I think it would work to create a cast WITHOUT FUNCTION, assuming that 
the semantics you want is that the exact bytes in the varchar datum 
become the bytes in the bytea (no encoding or backslashing conversions). 

regards, tom lane 


---(end of broadcast)---
TIP 5: Have you checked our extensive FAQ?

   http://www.postgresql.org/docs/faq