# Proper Way to Encrypt Data with Two Keys?

I'm going to develop a system that will have two keys. One supplied and generated by the system that's specific to an individual user and one from the user.

I plan on using AES.

Does it make sense to:

1. Concatenate the two keys to make a "master" key and then encrypt the data?
2. Encrypt with one key and the encrypt again with the other key?

Does it really matter? I can't see that it'd really matter, but maybe I'm missing something.

-
symmetric or asymmetric? $\;$ –  Ricky Demer May 24 '13 at 5:26
Ya, that's important... AES, so symmetric. –  JP Richardson May 24 '13 at 5:33
It depends what you are looking for.. what should the restrictions be for someone who doesn't have any key? one key? both? do you need to handle compromise/rekeying, do the two parties trust each other or interact in any way? etc.. –  Thomas May 24 '13 at 6:14
You are describing your proposed solution instead of describing your problem/goal. –  tylo May 24 '13 at 13:15

To begin with, some essential requirements are missing from your question at the time I write this, so I am going to assume:

• $User$ trusts $System$.
• $System$ trusts that $User$ will not pass $Key_{User}$ to any entity that $User$ does not trust to be $System$.

This implies, in particular:

• $System$ is already authenticated to $User$, and $User$ already has a channel for passing $Key_{User}$ to $System$ with preserved authenticity, integrity and confidentiality.
• The environment of $System$ is such that there is no risk $Key_{User}$ or $Key_{System,User}$ will be extracted from $System$ by an attacker. Alternatively, there is no risk it will happen without detection, in which case an auxiliary protocol exists for replacing the keys.

If the above conditions are met, both methods you describe in your questions are fine for generating an effective content encryption scheme. Just a few points:

• Generating an effective key simply by concatenating two pieces contributed by two separate entities (as in your first method) is an unusual approach. I would probably prefer to combine them using a Key Derivation Function instead of simply concatenating them. However, given that $System$ and $User$ both trust each other, the only compelling reason for using a KDF instead of concatenation, would be if, in some sense, it would be worse if both entities are compromised, compared to if just one of them is compromised. A KDF will be better at hiding the other part of the key material, compared to just concatenation before the AES key schedule.
• Encrypting the payload contents twice (as in your second method) is also a bit unorthodox, but it can be done in such way that you will get at least the same security, as with just one encryption key. Hence, you could in such case rather just encrypt $Key_{System,User}$ with $Key_{User}$ using a key wrap encryption scheme, and store the resulting cipher text $System$ side. Using key wrap encryption might provide additional benefits, such as the ability for $User$ to change $Key_{User}$ without $System$ having to decrypt and re-encrypt the entire content cipher test (if the key is used for stored data), and the ability for $System$ to give multiple users ability to decrypt the same cipher text, bu wrapping the same content encryption key using multiple user keys.
-

There are many standardized key derivation functions designed specifically for this purpose. It would generally be better to use one of those rather than rolling your own. For example, HKDF (RFC 5869) should work nicely for your purposes, and it's versatile enough to let you also derive any other key material you might need (e.g. for message authentication) from the same master key(s).

That said, I see no obvious problems with either of your suggestions. One potential drawback of simply splitting the key into two parts and concatenating them is that the parts must, necessarily, be shorter than the full key. This could be an issue for ciphers with short key lengths, if one of the key parts was compromised, but it shouldn't be a problem if you use a cipher with a key at least 256 bits long, such as AES-256. In any case, you could avoid this issue entirely by XORing the key parts instead of concatenating them (or, more generally, by using a secret sharing scheme).

-

Hash the two keys, and use the result as your symmetric key for encryption.

Example: compute the encryption key as $K = \text{SHA256}(\text{len}(k_1) || k_1 || k_2)$, where $k_1,k_2$ are the two key parts provided as input. Then, encrypt the message using key $K$ using a standard scheme (e.g., an authenticated encryption scheme like EAX or AES-GCM).

-
It's very little work to generate a KDF from a hash function, and a hash is (officially) not a KDF. –  owlstead Jun 24 '13 at 11:11
A KDF would be a great choice, too. In this case I expect it probably doesn't matter too much which you use (the crypto purists would say you should use a KDF, so a KDF is the more conservative/careful choice, and I won't argue with that), so if a KDF feels more comfortable, go for it! –  D.W. Jun 24 '13 at 18:18