should we encrypt sensitve data on cloud?

Viewed 55

We have some application on cloud not yet in production, and honestly we don't know if we should encrypt sensitive data. If we should encrypt we have 3 solution in mind. We are using Postgres and spring data jpa. keep in mind that some of this fields that we are encrypting are used in filters.

(1) Using PG CRYPTO, this is a very good solution but if we go in the logs of the database we see the key for decryption example:

select testenc0_.id as id1_6_, PGP_SYM_DECRYPT(testenc0_.otherColumn::otherColumn, 'MySuperSecretKey') as byteac2_6_, PGP_SYM_DECRYPT(testenc0_.email::bytea, 'MySuperSecretKey') as email3_6_, testenc0_.name as name4_6_ from test_enc testenc0_ 

as you see any DBA can easily decrypt our data. We cannot control logs of database.

We can use this on the fields that should be encrypted/decrypted

@Column(name = "email", length = 255)
    @ColumnTransformer(
            read = "PGP_SYM_DECRYPT(email::bytea, '${encryption.key}')",
            write = "PGP_SYM_ENCRYPT (?, '${encryption.key}')"
    )

And also we can use this function because we have some native queries because we use some specific feature of the database. With this solution also the like on the columns encrypted is easy to implement, nothing to do in this case, because the decryption is made before the like statement because the decryption is made at database level.

(2) Using Hibernate @Converter example on column:

@Convert(converter = CryptoConverter.class)

@Converter
public class CryptoConverter implements AttributeConverter<String, String> {

    private static final String ALGORITHM = "AES/ECB/PKCS5Padding";
    @Value("${database.encrypt.key}")
    private String KEY = "";

    @Override
    public String convertToDatabaseColumn(String ccNumber) {
        // do some encryption
        Key key = new SecretKeySpec(KEY.getBytes(), "AES");
        try {
            Cipher c = Cipher.getInstance(ALGORITHM);
            c.init(Cipher.ENCRYPT_MODE, key);
           return Base64.getEncoder().encodeToString(c.doFinal(ccNumber.getBytes()));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String convertToEntityAttribute(String dbData) {
        // do some decryption
        Key key = new SecretKeySpec(KEY.getBytes(), "AES");
        try {
            Cipher c = Cipher.getInstance(ALGORITHM);
            c.init(Cipher.DECRYPT_MODE, key);
            return new String(c.doFinal(Base64.getDecoder().decode(dbData)));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

With this approach we can hide the key to the DBA because the encryption is made on application level but we cannot use like statement. So in this use case if we have to apply a filter it will not work because the like statement will be applied on encrypted values. Both of this two solution uses symmetric key. And for native queries we have to decrypt encrypt output/input columns that needs that.

(3) The most secure solution using asymmetric/symmetric key. We will have a common column that will be present in all the tables. This column will be used to generate a public key for the asymmetric encryption/decryption and stored into a common table. So in this case if we have for example the same sensitive field equals for example name MARIO = MARIO the encryption for the two equals string will be different. But this is a nightmare for the performance because let's say we have to store 700 records we have to retrieve/generate key if not exists in database for each field that should be encrypted. The same if we have to extract those 700 records we have to perform a lot of queries to decrypt each field on the common table. Also here we can't use like.

What should we do? Do we really need to perform this kind of encryption?

And what about request/response? Should we encrypt/decrypt also them? Honestly this is a nightmare

0 Answers
Related