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

Single quote in PGCRYPTO_KEY string causes syntax error #319

Open
khattori opened this issue Jan 25, 2021 · 2 comments · May be fixed by #321
Open

Single quote in PGCRYPTO_KEY string causes syntax error #319

khattori opened this issue Jan 25, 2021 · 2 comments · May be fixed by #321

Comments

@khattori
Copy link

syntax error at or near "j1" LINE 1: ...SET value = pgp_sym_encrypt('hogehoge', 'hogehoge'j1') WHERE...

It seems that proper escaping is needed when constructing SQL statements.

@peterfarrell
Copy link
Collaborator

PR welcome if you can figure out how to parameterize it or another solution could be to use Postgres dollar quoting.

khattori pushed a commit to khattori/django-pgcrypto-fields that referenced this issue Jan 27, 2021
marteinn added a commit to Frojd/django-pgcrypto-fields that referenced this issue Dec 15, 2022
@some1ataplace
Copy link

To avoid syntax errors caused by single quotes in the PGCRYPTO_KEY string when constructing SQL statements in django-pgcrypto-fields, you can use parameterized queries instead of concatenating strings. This will automatically escape any special characters in the input values, including single quotes.

For example, instead of using a query like this:

query = "SELECT pgp_sym_encrypt('hogehoge', '{}')".format(PGCRYPTO_KEY)

You can use a parameterized query like this:

query = "SELECT pgp_sym_encrypt('hogehoge', %s)"
params = [PGCRYPTO_KEY]
cursor.execute(query, params)

Alternatively, you can use Postgres dollar quoting to avoid the need for escaping special characters. This involves wrapping the SQL statement in a pair of dollar signs, and using a unique identifier to mark the beginning and end of the statement.

For example:

query = """
SELECT pgp_sym_encrypt('hogehoge', $$%s$$)
"""
params = [PGCRYPTO_KEY]
cursor.execute(query, params)

Using parameterized queries or dollar quoting can help prevent syntax errors and improve the security and reliability of your code.


Here is an example with Postgres dollar quoting:

from django.db import connection

key = '$pgcrypto$hogehoge'

with connection.cursor() as cursor:
    cursor.execute("UPDATE my_table SET value = pgp_sym_encrypt('hogehoge', {}) WHERE some_column = %s".format(key), ('some_value',))

Here we're using the string formatting capabilities of Python to insert the key value into the SQL statement. By wrapping our key value in the $pgcrypto$ tags, we're using Postgres dollar quoting, which allows the database to handle any issues with the string constant itself, such as single quotes. Note that we also have to escape the string placeholders in cursor.execute with double percent signs to avoid conflicts with the dollar quoting sytax.


Here's an example of how to modify the encrypt_value method in DjangoPGPSymmetricKeyField of django-pgcrypto-fields to use parameterized queries with Postgres dollar quoting.

def encrypt_value(self, value):
    conn = connections[self.db_alias]
    # Generate a unique key ID for this encryption operation.
    key_id = self.generate_new_key_id()
    # Construct the SQL query.
    sql_query = """
        UPDATE %s SET value = pgp_sym_encrypt($$%s$$, %s) WHERE id = %s;
        INSERT INTO %s(id, value) SELECT %s, pgp_sym_encrypt($$%s$$, %s) WHERE NOT EXISTS
            (SELECT id FROM %s WHERE id = %s);
    """ % (self.model._meta.db_table, value, key_id, self.pk, self.model._meta.db_table, self.pk, value, key_id,
           self.model._meta.db_table, self.pk)
    # Execute the SQL query.
    with conn.cursor() as cursor:
        cursor.execute(sql_query)

Note that the $$ syntax is used for Postgres dollar quoting, which allows us o embed single quotes within the SQL query without having to escape them. Using parameterized queries instead of string interpolation ensures that the query is safe from SQL injection attacks.

With these modifications, you can use the DjangoPGPSymmetricKeyField in the same way as before, with the added benefit of increased security and protection against SQL injection.


Here's an example of how you can use Postgres dollar quoting with the $pgcrypto$ tag to avoid syntax errors caused by single quotes in the PGCRYPTO_KEY string:

query = """
SELECT pgp_sym_encrypt('hogehoge', $pgcrypto$%s$pgcrypto$)
"""
params = [PGCRYPTO_KEY]
cursor.execute(query, params)

In this example, the PGCRYPTO_KEY value is passed as a parameter to the query, and is inserted into the SQL statement using the $pgcrypto$ tag. This allows Postgres to handle any issues with the string constants, including escaping any special characters like single quotes.

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

Successfully merging a pull request may close this issue.

3 participants