Thread: PQunescapebytea not reverse of PQescapebytea?

PQunescapebytea not reverse of PQescapebytea?

From
Karthik Segpi
Date:
Hi -
I have a 'bytea' column in the database, onto which my custom C application is inserting encrypted data. Before inserting, I am calling 'PQescapebytea()' to escape the ciphertext. However, after SELECT, the data needs to be 'un-escaped' before attempting to decrypt. I am trying to 'un-escape' using 'PQunescapebytea'. However, I am finding that 'PQunescapebytea' is not  exact inverse of 'PQescapebytea'. I saw documentation and posts in the mailing lists alluding to this as well. As a result, the decryption always fails.

Is there another C method out there that does exact inverse of 'PQescapebytea'? If the answer is no, then what other options do I have? I could think of the following:

1. Write my own C method that does exactly the inverse of 'PQescapebytea'
2. Instead of using 'PQescapebytea', base64 encode ciphertext before inserting. Not sure how well this would work.
3.  Use 'text' data type for the column instead of 'byte a'.

Has anyone faced this scenario before? 

Thanks-
Karthik





Re: PQunescapebytea not reverse of PQescapebytea?

From
Florian Weimer
Date:
* Karthik Segpi:

> I have a 'bytea' column in the database, onto which my custom C application
> is inserting encrypted data. Before inserting, I am calling
> 'PQescapebytea()' to escape the ciphertext. However, after SELECT, the data
> needs to be 'un-escaped' before attempting to decrypt. I am trying to
> 'un-escape' using 'PQunescapebytea'. However, I am finding that
> 'PQunescapebytea' is not  exact inverse of 'PQescapebytea'. I saw
> documentation and posts in the mailing lists alluding to this as well. As a
> result, the decryption always fails.

Can you show us some example data that shows the inconsistency?
PQunescapebytea should give you back the blob you passed to
PQescapebytea, but the same blob can have different BYTEA
encodings—not everyone uses the \x hexadecimal encoding.



Re: PQunescapebytea not reverse of PQescapebytea?

From
Jeff Davis
Date:
On Wed, 2014-03-19 at 21:28 +0100, Florian Weimer wrote:
> * Karthik Segpi:
> 
> > I have a 'bytea' column in the database, onto which my custom C application
> > is inserting encrypted data. Before inserting, I am calling
> > 'PQescapebytea()' to escape the ciphertext. However, after SELECT, the data
> > needs to be 'un-escaped' before attempting to decrypt. I am trying to
> > 'un-escape' using 'PQunescapebytea'. However, I am finding that
> > 'PQunescapebytea' is not  exact inverse of 'PQescapebytea'. I saw
> > documentation and posts in the mailing lists alluding to this as well. As a
> > result, the decryption always fails.
> 
> Can you show us some example data that shows the inconsistency?
> PQunescapebytea should give you back the blob you passed to
> PQescapebytea, but the same blob can have different BYTEA
> encodings—not everyone uses the \x hexadecimal encoding.

Example:
 size_t len1, len2; char *str = "\\\\123";
 printf("%s\n", str); printf("%s\n", PQescapeBytea(str, strlen(str), &len1)); printf("%s\n", PQunescapeBytea(
                    PQescapeBytea(str, strlen(str), &len1),                                &len2));
 

The reason for this is that PQescapeBytea is designed to escape it to be
passed into the server via a SQL string (adding two levels of escaping,
one for the sql string and one for bytea); whereas PQunescapeBytea is
designed to unescape a result coming back from the server (which only
has one level of escaping to undo: the bytea escaping).

To be more consistent, PQ[un]escapeBytea might only [un]escape the bytea
portion, making them true inverses. That would mean that to put a bytea
in a sql string, you'd need to do something like: PQescapeString(PQescapeBytea(str, ...))
rather than just: PQescapeBytea(str, ...)

Both methods are a bit error-prone. The first is error-prone because you
have to remember to do both; the second because it's inconsistent.

The best thing to do is use parameterized input to reduce the room for
confusion. Specify bytea parameters as binary format, and you don't need
to escape them at all on input. When reading them back out of the
server, use binary format if you can; and if not, then you'll need to
use PQunescapeBytea.

Regards,Jeff Davis





Re: PQunescapebytea not reverse of PQescapebytea?

From
Florian Weimer
Date:
* Jeff Davis:

> On Wed, 2014-03-19 at 21:28 +0100, Florian Weimer wrote:
>> * Karthik Segpi:
>>
>> > I have a 'bytea' column in the database, onto which my custom C application
>> > is inserting encrypted data. Before inserting, I am calling
>> > 'PQescapebytea()' to escape the ciphertext. However, after SELECT, the data
>> > needs to be 'un-escaped' before attempting to decrypt. I am trying to
>> > 'un-escape' using 'PQunescapebytea'. However, I am finding that
>> > 'PQunescapebytea' is not  exact inverse of 'PQescapebytea'. I saw
>> > documentation and posts in the mailing lists alluding to this as well. As a
>> > result, the decryption always fails.
>>
>> Can you show us some example data that shows the inconsistency?
>> PQunescapebytea should give you back the blob you passed to
>> PQescapebytea, but the same blob can have different BYTEA
>> encodings—not everyone uses the \x hexadecimal encoding.
>
> Example:
>
>   size_t len1, len2;
>   char *str = "\\\\123";
>
>   printf("%s\n", str);
>   printf("%s\n", PQescapeBytea(str, strlen(str), &len1));
>   printf("%s\n", PQunescapeBytea(
>                                  PQescapeBytea(str, strlen(str), &len1),
>                                  &len2));
>
> The reason for this is that PQescapeBytea is designed to escape it to be
> passed into the server via a SQL string (adding two levels of escaping,
> one for the sql string and one for bytea); whereas PQunescapeBytea is
> designed to unescape a result coming back from the server (which only
> has one level of escaping to undo: the bytea escaping).

Ah, right, this is annoying.  I think a thin (one-level) escaping
function would make sense to add to libpq.