There are two ways to secure a key programmatically:
- Keep the key itself secret, or
- Keep the algorithm secret.
Cryptographers (and common sense) will tell you that, of the two, the second is far less secure because it's relatively easy to reverse-engineer the code. So you're left with the first method.
If I'm reading your requirements correctly, you need a key that is
- Guaranteed to be unique to each machine.
- Random.
- Not stored anywhere.
- Reproducible (by your software).
But it's not possible to satisfy all of these. For example, a truly random key that is not stored anywhere (either as data or embedded in an algorithm) cannot be reproduced at will. So if I can take some leeway, I'll read into your use case and substitute these less stringent requirements:
- Tied to the host machine: a key from one machine cannot be used on another.
- Secure: unlikely to be duplicated, guessed, reverse-engineered, etc.
- Secure: not likely to be discovered within your program.
- Reproducible: your application must be able to regenerate the key as necessary.
All of these new requirements, with the exception of #3, can be satisfied with this procedure:
- Generate a secret random seed that will be used on every machine.
- Choose a machine-dependent signature that is unique to each host, and append it to the seed. The classic example is a MAC address, but on machines with two or more NICs you must be careful to use the same NIC each time!
- Hash the result with an algorithm (like SHA) that will generate a result that is reasonably unique and irreversible.
Now all that's left is to satisfy the third requirement by making it reasonably difficult for an attacker to guess the one item that must be secret: the seed. And this is where the process becomes more of a religious argument than a technical one, because "reasonably difficult" depends on how badly an attacker wants to discover the key and the risks if s/he succeeds.
To be as secure as possible, the key must be stored outside your application, e.g. in your brain, and supplied each time it's needed. But generally some form of the weaker security through obscurity mechanism is acceptable; one of my favorites is to use something like 0x%-6.2d
that is likely to be overlooked as a printf()
format. If you're paranoid, store it in pieces and re-create it in a part of your application that isn't otherwise associated with the key-processing modules.
Please do tell us a little more about your application and its use cases if you'd like more specific suggestions.
Good luck!