views:

236

answers:

6

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.

+1  A: 

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.

Kevin
+1  A: 

Whose private key is that? The private key is supposed to be private, so it is wrong to distribute it.

Bozho
The key would be one that I generated...was that a real question?
Jason Nichols
it was a rhetorical question. Meaning that if the code is not owned by the party where it resides, it is wrong to use it.
Bozho
A: 

First off - good on you for thinking about this problem!

Is it possible to instead generate a private key, communicate with your Certificate Authority and have it sign the key (and manage a CRL as well)?

As an alternative, if this is going to be running on Windows, you can use the Crypto API to securely store a private key that is marked as not-exportable. How you distribute that key securely can be another challenge though.

Goyuix
What is so good about it? It seems to be making him miserable.
GregS
+3  A: 

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.

kdgregory
I agree with your sentiments and solution wholeheartedly. Unfortunately the deployment constraints won't allow me to change the requirement as you describe.In this case, I'm looking to ward off an attack up to a given level of sophistication. If resistance up to someone half skilled with a debugger is all that's possible, then so be it.
Jason Nichols
A: 

Can you break the private key out into two parts: store one in your program, then interactively request the second half - when your app starts ?

monojohnny
+2  A: 

Your only defense in this case is to attempt to bore the reverse engineer to death, in both his static analysis (i.e. decompilation) and dynamic analysis using a debugger. kdgregory and others have given you suggestions, here are a few others. You can encrypt the key with key1, and encrypt key1 with key2, and so on. You can generate a hundred calls to Mac.getInstance() and Mac.init(), but all except one somewhere in the middle are dummies. But do be careful, because you know you're not buying yourself anything measurable and you may very well bore yourself to death in the process.

GregS