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

Pass options to pgp_sym_encrypt #135

Open
SiddharthPant opened this issue May 30, 2019 · 5 comments
Open

Pass options to pgp_sym_encrypt #135

SiddharthPant opened this issue May 30, 2019 · 5 comments

Comments

@SiddharthPant
Copy link

SiddharthPant commented May 30, 2019

pgp_sym_encrypt function supports certain options. For example by default it uses AES128 algorithm to encrypt but you can customize pgp_sym_encrypt(data, psw, 'compress-algo=1, cipher-algo=aes256'). Is there a way I can provide the cipher-algo option with value AES256 when I create CharPGPSymmetricKeyField or maybe in the settings file? If there is not then could there please be an enhancement that can be made for this?

@peterfarrell
Copy link
Collaborator

@SiddharthPant It's currently not configurable in this package but a PR would be welcome.

@peterfarrell
Copy link
Collaborator

This is also related to #89

@9mido
Copy link

9mido commented Dec 18, 2021

@peterfarrell

What if you did something like this:

>>> ("pgp_sym_encrypt(%s, '{}', '{}')::%s" % ("foo", "bar")).format(2, 3)
"pgp_sym_encrypt(foo, '2', '3')::bar"

.format picks up the {}, % picks up the %s

@some1ataplace
Copy link

To implement the custom encryption options for django-pgcrypto-fields, you can modify the existing implementation by adding an optional keyword argument for the cipher algorithm when creating a CharPGPSymmetricKeyField. This will allow you to pass in the desired cipher algorithm as an option when calling pgp_sym_encrypt function. Here's how you can achieve it:

  1. First, you should create a new file named encrypt_options.py within the django-pgcrypto-fields package directory. This file should contain a function to build a cipher algorithm string from the provided options, like so:
def build_cipher_options(cipher_algo='aes128'):
    if cipher_algo not in {'aes128', 'aes256'}:
        raise ValueError("Unsupported cipher algorithm")
    
    options = f"compress-algo=1, cipher-algo={cipher_algo}"
    return options
  1. Next, modify the PGPSymmetricKeyFieldMixin class definition in the fields.py file to pass the optional keyword arguments for the cipher algorithm when creating a field instance:
from .encrypt_options import build_cipher_options

class PGPSymmetricKeyFieldMixin:

    def __init__(self, *args, cipher_algo='aes128', **kwargs):
        self.cipher_algo = cipher_algo
        super().__init__(*args, **kwargs)

  1. Modify the _encrypt() method in the same PGPSymmetricKeyFieldMixin class to build the cipher algorithm string using the provided options:
    def _encrypt(self, text, cipher_algo=None):
        if cipher_algo is None:
            cipher_algo = self.cipher_algo
        
        if text is None:
            return None

        options = build_cipher_options(cipher_algo)  # Build the cipher options string
        query = "SELECT pgp_sym_encrypt(%s, %s, %s)"
        
        # Pass the options string to the `pgp_sym_encrypt` function
        result = self.objects.raw(query, [str(text), self.key, options])[0]
        return result.pgp_sym_encrypt

Now you can create a `CharPGPSymmetricKeyField instance with custom cipher algorithm options like this:

encrypted_field = CharPGPSymmetricKeyField(max_length=1000, cipher_algo='aes256')

You may also introduce a settings.py variable to configure the default cipher algorithm. To achieve this, in the fields.py file, replace the following line:

cipher_algo='aes128',

With

cipher_algo=getattr(settings, 'PGCRYPTO_DEFAULT_CIPHER_ALGO', 'aes128'),

Don't forget to import the settings module at the top of the fields.py file:

from django.conf import settings

Now, you can set the default cipher algorithm in your project's settings.py` file:

PGCRYPTO_DEFAULT_CIPHER_ALGO = 'aes256'

This should provide you with customizable cipher algorithm options for the django-pgcrypto-fields package.


To pass options to pgp_sym_encrypt and customize the cipher algorithm used for encryption in CharPGPSymmetricKeyField, you can modify the encrypt method of the PGPTextField class in pgcrypto_fields/fields.py.

Here's an example implementation:

from django.db import models
from pgcrypto_fields import PGPTextField

class CharPGPSymmetricKeyField(PGPTextField):
    def encrypt(self, plaintext):
        if not self.key:
            raise ValueError("No key specified for encryption")

        options = "compress-algo=1, cipher-algo=aes256"
        ciphertext = self.connection.ops.pgp_sym_encrypt(plaintext, self.key, options=options)
        return ciphertext

In this example, we've added an options parameter to the pgp_sym_encrypt method call, which allows you to customize the cipher algorithm used for encryption. We've also renamed the class to CharPGPSymmetricKeyField to avoid confusion with the existing PGPSymmetricKeyField.

Alternatively, you could use a settings variable to customize the cipher algorithm option. You could define a PGCRYPTO_CIPHER_ALGO setting in your settings.py file and modify the encrypt method to use it:

from django.conf import settings
from django.db import models
from pgcrypto_fields import PGPTextField

class CharPGPSymmetricKeyField(PGPTextField):
    def encrypt(self, plaintext):
        if not self.key:
            raise ValueError("No key specified for encryption")

        options = f"compress-algo=1, cipher-algo={settings.PGCRYPTO_CIPHER_ALGO}"
        ciphertext = self.connection.ops.pgp_sym_encrypt(plaintext, self.key, options=options)
        return ciphertext

In this implementation, we've defined a PGCRYPTO_CIPHER_ALGO setting in settings.py and used it to customize the cipher algorithm option in the encrypt method. This allows you to easily change the cipher algorithm used for encryption without modifying the code directly.

@peterfarrell
Copy link
Collaborator

@some1ataplace PRs welcome

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

No branches or pull requests

5 participants