I'm working on a software project where the application will end up being run in an untrusted environment. I have a need to perform some ancillary cryptographic signing (meaning this is not the primary means of securing data), but do not wish to leave the key in plain view as such:
private static final String privateKey = "00AABBCC....0123456789";
What method can I use to reasonably secure this? I'm aware that nothing is full proof, but this will add an extra layer in the security wall.
For clarification: I've got what is essentially a String that I don't wish to have easily pulled out in a debugger or via reflection. I'm aware that decompilation of the class file could essentially render this moot, but that's an acceptable risk.
Obviously storing the key offsite would be ideal, but I can't guarantee Internet access.
The most secure method of storing your private keys is to use some form of cryptographic hardware storage device. While they can be expensive, tools like Hardware Storage Modules (HSM), Smart Cards, or USB tokens are great lines of defense against an attack.
Where to store the private key? Generally, the best practice is to generate the private key along with the CSR on the server where you intend to install the SSL certificate. This way, you eliminate the risk of vulnerability during the transfer from one machine to another.
Private key can't be hashed, we need its actual text. A suggestion is to symmetrically encrypt the private key before storing in the database with the user's password. But this means that the user needs to decrypt the private on every transaction, which is kinda user unfriendly.
It's impossible to secure a key in an untrusted environment. You can obfuscate your code, you can create a key from arbitrary variables, whatever. Ultimately, assuming that you use the standard javax.crypto
library, you have to call Mac.getInstance()
, and sometime later you'll call init()
on that instance. Someone who wants your key will get it.
However, I think the solution is that you tie the key to the environment, not the program. A signature is meant to say that the data originated from a known source, and has not been tampered with since that source provided it. Currently, you're trying to say "guarantee that my program produced the data." Instead, change your requirement to "guarantee that a particular user of my program produced the data." The onus is then shifted to that user to take care of his/her key.
Forget about obscuring it in the code. It will only make your software harder to read, debug and maintain. You'll also be nailed if your software has to go through a security audit.
If you can't put the key in secure storage (securely on disk, secure memory or a passphrase in someones head), don't bother with anything else.
If you're in a *nix environment, storing the key on disk with root/root 400 permissions might be "good enough".
On Windows, you could use the DPAPI to store the data in Microsofts secure memory.
You could also use a lightweight PBE to encrypt the sensitive key and have the user enter the passphrase when the application starts up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With