I'm working on a software that need to store and use secrets.
These secrets can be for example:
- a password to connect to a database
- a client secret for an OAuth 2.0
client_credentials
grant.
I need to store these passwords somewhere (preferably in some kind of configuration file) and protect them with reasonable security.
Reasonable security means: no heavy hardware based solution such as HSM or a complicate infrastructure (PKI, ...).
The software is in Java, it should run anywhere Java can run (Especially Windows, GNU/Linux, Solaris, AIX).
It cannot rely on a OS or distribution specific tool such as GNOME keystore, KDE Wallet or any of these unless Java provides way to handle them (but I doubt it).
I thought of using symetric cryptography to encrypt the secrets when configuring the software and decrypt them at runtime when needed. But I don't know how to handle the encryption key.
I have 4 found possible solutions:
- Use PBKDF2 (SHA256-AES256-CBC) or plain AES256-CBC with an hardcoded cryptographic key and optionally some code obfuscation (with ProGuard)
- There is a dedicated CWE about that: CWE-321 - Use of Hard-coded Cryptographic Key. So I doubt this is the solution.
- Use PBKDF2 (SHA256-AES256-CBC) or plain AES256-CBC with a key in a file on the filesystem
- It exposes the key in a file that should be protected by some way
- encrypted filesystem and/or
- enforced ACL
- anything else?
- It exposes the key in a file that should be protected by some way
- Use the Java keystore
- The Java keystore needs a password to unlock, so where to store the Java keystore password? How to protect it? The serpent is eating its own tail...
- Somehow equivalent to 2
- Use white-box cryptography
- It has shown some weaknesses and is more or less equivalent to obfuscation. (which is inside option 1).
- I'm not sure Java implementation of WBC are mature.
I've seen that question: Practices for storing username/password in Web applications.
So my question here is: What is the "best" resonable option to protect my secret data?
I feel that 2 is better, after all it is simple, and the secret key protection would rely on the OS rather than the software itself, just like OpenSSH but I'm not totally convinced.
EDIT:
PBKDF2 could be replaced by any other password base key derivation algorithm, such as PKCS #12 v1 key derivation algorithm.
Bonus:
If I were to choose between PBKDF2 (SHA256-AES256-CBC) or plain AES256-CBC, what would be the best?
- PBKDF2 is said to be good to protect passwords because it is 'slow'. And it was desgined for that.
- AES256-CBC is more simple (no need to salt/hash/iterate the key like in PBKDF2)