3
$\begingroup$

We have a system that has several SecretKeys (for example, one for a user, and one for us). We want to encrypt data in a way that requires all of those keys to be available in order to decrypt.

I think that the correct way to do this is to use a key derivation function of some sort to merge the source SecretKeys together, and use the result a the encryption key.

Given that all of the source keys are cryptographically generated SecretKeys using the following (apologies in advance if this isn't the right :

KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(256);
return generator.generateKey();

is it safe to just use a cryptographic hash of the source keys, or is that potentially introducing a vulnerability somehow? Like this:

SecretKey secretKey1 = ...
SecretKey secretKey2 = ...
SecretKey secretKey3 = ...

MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(secretKey1.getEncoded());
md.update(secretKey2.getEncoded());
byte[] digest = md.digest(secretKey3.getEncoded());

SecretKey mergedSecretKey = new SecretKeySpec(digest, "AES");

The database we are working with doesn't support native encryption, and we are only encrypting a very small number of fields.

Related (but no helpful responses): Using multiple cryptographic keys for encryption?

$\endgroup$
  • 1
    $\begingroup$ en.wikipedia.org/wiki/Secret_sharing $\endgroup$ – Luis Casillas May 4 '18 at 0:37
  • $\begingroup$ Good background. I'm still uncertain about whether using SHA is a cryptographically sound way of driving a symmetric key from two or three other keys... $\endgroup$ – Kevin Day May 4 '18 at 3:54
  • $\begingroup$ I agree with @LuisCasillas, you want to look into Secret Sharing. I would suggest looking into Shamir's scheme $\endgroup$ – Haris Nadeem May 4 '18 at 5:11
1
$\begingroup$

As long as the total entropy (unpredictability measured in units of bits) of the inputs is at least as large as the derived key size then it is okay in practice.

Reasons why it might not be good in theory (but really is harmless):

  • In theory you lose a tiny bit of entropy due to collisions. (Small enough not to ever ever ever matter for short inputs, acceptable mainstream hash functions, and greater than 128 bits of output.)
  • If someone hashes a known value together with a uncertain low entropy input, then reveals that value, an attacker can then enumerate likely values for brute forcing the low-entropy input value. Since the inputs are secret keys (with high entropy) and since the output is kept secret, it is no concern.
  • Some hash functions could be designed to be resistant to collision, first preimage, and second preimage attacks. But that doesn't guarantee the output is pseudorandom. It's okay because SHA-2 has enough scrutiny to believe it's practically a random oracle. And even if collisions or minor biases are found some day, the fact that inputs contain long random uniform bit strings means it won't effect key derivation.

I assumed your SecretKeys are symmetric shared secret (uniform full entropy) keys. (I don't know why you would want to combine shared secret keys to make a shared secret key and why the process that made the input keys can't be used.)

You can also hash public keys (but they add zero entropy because of their publicness) and Diffie-Helman style shared secrets. Key exchanges in protocols like TLS can use key derivations that are a function of inputs including a DH shared secret, public authentication keys, and protocol handshake details fed to a hash function to generate symmetric keys used for encryption and authentication.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.