As the risk of data breaches continues to grow, it is important to re-evaluate how to better secure customer data.

Blog: How to use pgcrypto to further protect your data

Frequent news of data breaches affecting sensitive data of millions of customers have made the public, as well as governments and regulators, strictly legislate how organisations have the responsibility to protect their customers' data.

Damages caused by data breaches include not only reputation erosion of the breached organisation, but also result in additional costs in repairing / patching up their systems and hardening their databases.

Protecting customer data

After one of the many recent data breaches, I had a chat with some friends about how to better secure the data they hold for customers to prevent it from happening to them.

We discussed what would happen if someone managed to do some sort of SQL injection attack which gave the attacker access to the production database. We then talked about PostgreSQL prepared statements and how this could help defend against SQL injection attacks, and the conversation continued.

At this point, we decided to play with the worst-case scenario, in which an attacker somehow managed to gain access to our database as a valid user, and retrieved user passwords stored in the system.

One-way encryption using pgcrypto

The solution to this problem would be to use pgcrypto, one of the standard PostgreSQL extensions. Of course, if an attacker had managed to get access to your server in the real world then there would be bigger problems that would need resolving quickly.

The pgcrypto module is a cryptographic extension that provides a number of hashing and cryptographic functions using MD5, SHA, HMAC, AES, BLOWFISH, PGP, and CRYPT, as well as DES and 3DES if your community version of PostgreSQL was compiled with OpenSSL support — as is the case with FUJITSU Enterprise Postgres.

So, back to the password question

All you need to do to store a secure password in your database is to hash it before you store it.

To hash a password you would first append a random string (also know an as salt) to that password, encrypt the whole string, and then store the result.

The salt can be stored in the database as is, without encrypting. This may seem like a weird idea, but for someone trying to decrypt your password data, it means that each and every password has to be cracked individually, and each cracking attempt has to be started from scratch. Being able to obtain the salt doesn’t help the attacker at all, be it with a single password or the whole set of passwords.

Password encryption using PostgreSQL and pgcrypto

For this example, pgcrypto helps you keep the encryption method, the salt, and the encrypted password in one string, to make it easier to work with. You would normally do most of the following steps within your application code, or you could easily do this with a PL/pgSQL or similar function if you wanted to.

The example below encrypts the password "mypass", adding a salt to the hashing, with 4 rounds of blowfish — the returned string is marked in red below. (In a production environment you would probably want 8 or more rounds of blowfish.)

psql
CREATE EXTENSION pgcrypto;
SELECT crypt('mypass', gen_salt('bf', 4));
crypt
--------------------------------------------------------------
 $2a$04$1bfMQDOR6aLyD4q3KVb8/ujG7ZAkyie4d/s3ABwuZNbzkFFgXtC76

We can now execute the statement below to store the string safely in the database:

INSERT INTO users (user_id,enc_pass) VALUES (1,'$2a$04$1bfMQDOR6aLyD4q3KVb8/ujG7ZAkyie4d/s3ABwuZNbzkFFgXtC76');

To check if the password is correct, run the query below — specifying "mypass" returns a result row, indicating that it is correct.

SELECT * FROM users WHERE user_id = 1 AND encpass = crypt('mypass', encpass);
user_id | encpass
--------+--------------------------------------------------------------
1       | $2a$04$1bfMQDOR6aLyD4q3KVb8/ujG7ZAkyie4d/s3ABwuZNbzkFFgXtC76
(1 row)

But specifying "hacker" does not return any rows, indicating that the value is incorrect.

SELECT * FROM users WHERE user_id = 1 AND encpass = crypt('hacker', encpass);
user_id | encpass
--------+---------
(0 rows)

And that’s it, you can now store strongly encrypted passwords in your PostgreSQL database and later validate them.

This is a one-way process — what about data that needs to be retrieved later?

While the solution described here is great to secure passwords from data breaches, it is not feasible to store large quantities of data or data that needs to be listed. For those, transparent data encryption and data masking can be used to secure your data.

Transparent data encryption 

As we discussed last week (see "Providing maximum data security with minimal impact to your business"), you can use TDE to safeguard your data using PCI DDS-compliant 256-bit encryption at all times.

Diagram - Transparent data encryption

For further reading, see also our blog post "Why Encrypted Tablespaces Matter".

Data masking

With FUJITSU Enterprise Postgres, you can use data masking to make sure that only appropriate users/roles can view sensitive data.

Diagram - Online data masking

Diagram - Offline data masking

If you are interested in learning more about Transparent Data Encryption or Data Masking, and how they may improve your PostgreSQL database, please contact us directly. Fujitsu provides 24/7 PostgreSQL support and services, DBA and developer training, and our own enhanced version of PostgreSQL — FUJITSU Enterprise Postgres.


bnr-white-paper-data-masking

 

Topics: Database Security, Data Masking, Customer Data, Encyption, Transparent Data Encryption

  

RECEIVE OUR BLOG

Receive notification of PostgreSQL-based articles for business and technical audiences.