How do you hide secret keys in code?
I've wondered for some time how some software hides secret keys in such a way that they can't be trivially discovered. Just a few examples:
- DVD Player Software hides CSS keys
- Software with serial numbers/registration codes hides keys/hashes used to validate the serial numbers
Obviously, these programs do something more than just have the key in a byte[], as that would make it easy to steal their keys and generate your own serial numbers, etc.
What sorts of strategies are used to hide these keys so that they can't be found easily?
The reasons those secret keys were so easily discovered is because they were hidden in software.
Avoid hiding secrets in software at all cost - obfuscation will only get you so far. Ask yourself this: How well can I hide a key in software from someone with full access to the disassembly, user mode and kernel mode debuggers, and no day job? It's only a matter of time before it gets cracked.
You just hide the key somewhere, and decrypt it when you need it. Using the key "securely" is the complicated part. Crackers might set a breakpoint to the place where you use the decrypted key and dump it. They might scan your code for patterns which show that you are using a known crypto algorithm (most algorithms have precalculated tables). etc etc.
That's why you need to make the whole software executable hard to analyze. For this you use executable packers, running code in a virtual machine, integrity checks etc. All this is to slow down debugging and modifying your code.
As most people here point out you can't stop anyone, just slow them down. I'd go to a cracker forum and ask there for suggestions about key hiding problematics. They are most likely helpful if you ask nicely.
ps. Public key crypto won't hide the key any better, but it might make it harder (or theoretically impossible) to make a key generator, if you're doing a licensing scheme.
The bottom line is, you can't. See any other comment here for the reasons why. Even encryption software like PGP/GPG stores the keys in a file, and then stridently urges those files to be kept on a flash drive in a safe, or something else secure. Keys stored as part of executable code will be discovered.
In fact, if you're trying to encrypt anything on a client machine that will be decrypted by the client as part of normal operations, that is also a fool's errand. The client machines are inherently insecure, and you can't control what they're going to be able to do to your data.
If you're trying to authenticate, instead, look at Internet based authentication with logins to a server, or some kind of generated KeyCode that is used to validate the software.
Secret keys as part of a Public-Private Keypair should be kept in data files that can be secured. Symmetric keys should be generated on the fly as Session Keys, then discarded. Always assume that anyone who has a Secret or Session key on their computer will be able to discover it, and use it against your intentions.
Read "Applied Cryptography" by Bruce Schneier for more information.
You can't hide a key forever. But you can sure make it hard to find. Some approaches are to encrypt the key in memory, keep multiple copies (perhaps encrypted differently) that are checked against each other, leave dummy copies to be accessed, store the key in some bizarre format, etc. None of them will work if somebody really wants your key, but you can at least dissuade a casual/inexperienced attacker.
You don't always need a key to validate a license.
But ignoring that fact, your key can also be the result of another function. You don't actually store a specific key value, instead you have a function that generates the key on the fly (always the same result). Although not impossible, it's much harder to find since you're no longer looking for a value, but you have to figure out it's an equation.