Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLAlchemy encrypt a column without automatically decrypting upon retrieval

Currently, I use EncryptedType from sqlalchemy_utils in order to automatically encrypt data on the way in to the table and decrypt the data when it's being retrieved from the table, using some predefined string as the encryption key. This works fine, but now requirements have changed and while I still need to encrypt the data on the way in to the table, I now need to keep that data encrypted when it is retrieved. I'm not sure if this is something that EncryptedType supports or if there is any other way to do this using SQLAlchemy without rolling my own in what I would assume would be the cryptography library.

Example of my table:

class MyTable(db.Model):
    __tablename__ = "my_table"
    id = db.Column(db.Integer, primary_key=True, autoincrement="auto")
    name = db.Column(db.String(50), nullable=False)
    username = db.Column(EncryptedType(db.String, _key), nullable=True)
    password = db.Column(EncryptedType(db.String, _key), nullable=True)
like image 581
Jfach Avatar asked Mar 29 '18 16:03

Jfach


People also ask

Which operations are allowed on always encrypted column?

Always Encrypted supports two types of encryption: randomized encryption and deterministic encryption. Deterministic encryption always generates the same encrypted value for any given plain text value. Using deterministic encryption allows point lookups, equality joins, grouping and indexing on encrypted columns.

How do I decrypt always encrypted column?

Make sure you have enabled Always Encrypted for the database connection for the Query Editor window, from which you will run a SELECT query retrieving and decrypting your data. This will instruct the . NET Framework Data Provider for SQL Server (used by SSMS) to decrypt the encrypted columns in the query result set.

Which option would be used to configure the always encrypted keys?

To create a column encryption key, use Object Explorer to connect to the database instance, navigate to the database, then to Security , and expand the Always Encrypted Keys folder. Right-click Column Encryption Keys , and then select New Column Encryption Key .


1 Answers

I found that using the cryptography library, which is what EncryptedType uses to handle encryption, was the simplest solution here.

I added an __init__ method to the model class and handled the encryption there.

from cryptography.fernet import Fernet
key = "my_encryption_key_here"

class MyTable(db.Model):
    __tablename__ = "my_table"
    id = db.Column(db.Integer, primary_key=True, autoincrement="auto")
    name = db.Column(db.String(50), nullable=False)
    username = db.Column(EncryptedType(db.String, _key), nullable=True)
    password = db.Column(EncryptedType(db.String, _key), nullable=True)
    auth_password = db.Column(EncryptedType(db.String, _key), nullable=True)

    def __init__(self, name, username, password, auth_password):
        cipher_suite = Fernet(key)
        self.name = name
        self.username = cipher_suite.encrypt(bytes(username))
        self.password = cipher_suite.encrypt(bytes(password))
like image 50
Jfach Avatar answered Nov 07 '22 00:11

Jfach