views:

194

answers:

3

I have a need to generate a random SecretKey, in Java, which I will be able to regenerate at some future point. The idea is that this key is unique to the machine on which it is created and isn't stored anywhere. I'm attempting something like this:

KeyGenerator keyGen = KeyGenerator.getInstance("DESede");

String hostname = InetAddress.getLocalHost().getHostName();
SecureRandom random = new SecureRandom(hostname.getBytes());
keyGen.init(random);

secretKey = keyGen.generateKey();

Obviously, this doesn't work because setting the seed of a SecureRandom doesn't work in the way I thought it did, and I get a different SecretKey each time. Maybe what I'm attempting won't ever work (I know that it looks like a weird thing to want to do...) but if there's a way, I'd realy appreciate it if someone could tell me what that way is!

+3  A: 

Even if it did work for you, you wouldn't really have a "secret" key - you'd have a key which is entirely derivable from the host name. That's not a secret - it's like everyone using their name as their password. Anyone wanting to attack the encrypted data would just have to know the name of the machine which created the key, and then they'd have access.

The final form of the key doesn't matter nearly as much as what information you need to recreate it. For the key to be effective, that information has to be secret, basically.

Jon Skeet
But he can use some salt to make it private? Or isn't that an good idea?
codedevour
chrsk: Well yeah, but then the key will be different again, on each machine. Even so, it's still not a good idea because, if you know the pattern of the key, you will be able to brute force it quite trivially.
Noon Silk
+3  A: 

You can't generate a random key twice, because it's random.

If InetAddress.getLocalHost().getHostName() is unique enough for your purpose, compute a hash value and use it as a key. As Jon said, the key is derivable for any person that knows the implementation.

Zappi
+2  A: 

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

  1. Guaranteed to be unique to each machine.
  2. Random.
  3. Not stored anywhere.
  4. 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:

  1. Tied to the host machine: a key from one machine cannot be used on another.
  2. Secure: unlikely to be duplicated, guessed, reverse-engineered, etc.
  3. Secure: not likely to be discovered within your program.
  4. 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:


  1. Generate a secret random seed that will be used on every machine.
  2. 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!
  3. 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!

Adam Liss
Thank you very much, this looks like the kind of information I need. Please be assured, I know that what I'm doing is easy to compromise, but I've been asked to find a way to protect the password used to protect access to the rest of our keys, the requirement being that it shouldn't be "trivially" discoverable - i.e. it shouldn't be possible to accidentally stumble across the password in plain-text form.
AndyB
Then you're looking for a KeyStore. ( no pun intended )
Nicholas Jordan