0
$\begingroup$

Let's say that I want to save some encrypted data to a database through a Spring Boot microservice. For that I will be using Spring Security Crypto that, as the documentation says it uses AES256 with CBC or GCM and derives the key from a passphrase and salt through PBKDF2. And I want to comment about the possible security implications of some decisions. The database, being a database, will get many frequent read and write operations. Let's say that my project is quite successful and I get hundreds or thousands of requests per second, so the performance of the encryption and decryption process matters here.

  • Since only the microservice writes to the database and the data doesn't come encrypted from the user (save for coming by HTTPS requests), I think I can improve the performance using CBC instead of GCM since the data don't need to be authenticated. It's only encrypted and decrypted by a trusted party (the microservice) supposing that the database access hasn't been compromised (we'll get to that) and returned in clear through HTTPS to the final user.
  • The key derivation process needs a passphrase and a salt and here I have two options: Use a different random salt per encryption operation or use the same salt for all the records in the database and here is where I'd like to discuss the security vs performance implications.

I've seen libraries like Jasypt that generate a salt per encryption operation and saves this salt prepended to the encrypted message. With this approximation the encryption key is unique per encrypted text but the throughput gets a very huge performance penalty. The derived key needs to be computed per every encrypt and decrypt operation and that means that it needs to be computed constantly for a big number of read and write operations. Furthermore, even in a single record the key is different per encrypted column so if I want to read a record with three encrypted columns it will need to derive three keys per record. Multiply that by potentially hundreds of records.

Another possibility is to use a constant salt which is secret, just like the passphrase. In this situation the key is derived once when the microservice starts and it can be enforced to be even stronger. For example, since the service is starting and not serving I could enforce ten times or a hundred times the iterations needed to derive the key since it will only be computed once. After this, every operation to the database will use the same key and the throughput in any modern hardware is stellar given it uses AES-NI. The throughput gets multiplied by thousands over the first scenario.

The derived key will be in memory as long as the microservice runs but so will be the passphrase in the first case even using a random salt per encryption so a malicious attacker getting a memory dump will get the key in both cases. What's more, in the first case he would get the passphrase itself while in the second case he will get the derived key since the passphrase can be thrown immediately after the key has been generated.

Now let's suppose the database is compromised. ¿Is there any advantage in the random salt scenario over the constant salt one? If the salt is random it needs to be saved in clear prepended to the cyphered message so the attacker can get a record, get the salt, compose a rainbow table using this salt and try to decrypt the record. If it succeeds then the random salt won't save the rest of the records since he already knows the passphrase. On the other hand, if the salt is constant but secret, the attacker needs to compose a rainbow table for every possible passphrase and salt combination, making it harder to guess the passphrase and compose a rainbow table to attack a single record.

Barring the leak of the secret data (passphrase and salt, in which case the database is compromised for good with random or constant salt) I see that using a random salt in this case has a huge impact in the performance of the system, offering little to none security advantage over a constant but secret salt. ¿Am I missing something here? ¿Is there any type of attack that I'm missing and that can compromise the database data for using a AES-256 CBC with PBKDF2 and constant but secret salt?

$\endgroup$
1
$\begingroup$

3 things to note:

1: a constant salt no longer functions as a salt

2: a constant secret salt is just an addition to the password

3: your suspicions about the method of cryptography employed to secure the DB in your example are well founded, simply, it is not good. Luckily for you, that is not how it is actually done.

With Spring Boot, you run the framework and database on your own infrastructure, whether that be a cloud instance or a dedicated server. You are in control of the DB as well as its at-rest encryption, additionally you control if you encrypt data that is passed to/from the DB, and how you do it. You do not need to use password based encryption for that.

If you decide to encrypt data outside of the DB, you are performance limited in the same way the database is, basically if you scale up the DB for more users, you add more computing power for encryption, and should not run into a bottleneck. The bottleneck will be running the app in java.

As for keys, with AES key changes are cheap, but if you want to limit them, using GCM with the same key for each record but difference nonces for each column in the record will be quite fast.

TLDR: do not use passwords or PBKDF for DB encryption.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Thanks for the answer. What I'm trying to do here is to add some layer of security on every level of the data chain. In this case, data will be encrypted at rest so anyone with physical access to the database data folder will not get clear data. I could use the database native encryption features if they have them but since all the data will be encrypted in disk, this is not necessary because if someone gets access to the database (due to a hack exploiting some vulnerability in the DBMS software, for example) he will get the data in clear through the API. $\endgroup$ – Jose Antonio Apr 12 at 8:35
  • $\begingroup$ What I want is to encrypt some columns, not all of them, so the DBMS API returns this sensitive data encrypted. This can be sensitive data like user telephones, social security numbers, ID numbers, credit card number, medical information and so that must be saved to the database but that I want to put a second layer of security in case the DBMS gets hacked so getting a database dump will not get the data in clear. $\endgroup$ – Jose Antonio Apr 12 at 8:43
  • $\begingroup$ My question is more related to: if someone gets this dump by whatever means but he doesn't have the password. Will he get any advantage by the fact that all records are encrypted with the same key vs saving them with a different key just changing the salt which is anyway included in clear in every record? Also, if not using Password Based Encryption then what other methods can I use to achieve my goal? $\endgroup$ – Jose Antonio Apr 12 at 8:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.