Derive secret key from a longer secret key - encryption

I use a user provided 32 byte secret key to sign some data using HMAC-256. I also want my application to encrypt data using AES-192. Should I ask the user for another secret key (this time 16 bytes in size) or is there a secure way to derive a 16 byte strong secret key from the other 32 byte key? Second method would make the application configuration a bit easier. Any guidelines or tips? Or is this approach complete nonsense?

The tool for this is an HKDF. This is a very good way to derive multiple keys from the same initial keying material. I would recommend that you use HKDF to derive both keys from the initial 32-byte secret, rather than deriving the AES key directly from the HMAC key. Typically you would stretch your 32 bytes IKM to 48 bytes and then split it into your two keys.
This is assuming that the initial 32 byte keying material is random. If it isn't, you should use PBKDF2 (or another password stretcher like scrypt or bcrypt) to stretch your keying material to 48 bytes and then split it into your two keys. HKDF is too fast of an algorithm to use with human-created passwords.

Related

3DES: does identical ciphertext mean identical keys?

Can we assume that same encryption key is used to encrypt data if encrypted data are same?
For example, plain text is 'This is sample'.
First time we use 3DES algorithm and encryption key to encrypt it. Encrypted data became 'MNBVCXZ'.
Second time again, we use 3DES algorithm and encryption key to encrypt it. Encrypted data became 'MNBVCXZ'.
My questions are:
Can I assume static encryption key is used in this encryption process?
How many keys can be used to encrypt data using 3DES algorithm?
Can I assume static encryption key is used in this encryption process?
Yes, if you perform the encryption yourself (with a very high probability), no if an adversary can perform the encryption and the plaintext/ciphertext is relatively small.
As 3DES does indeed have 2^168 possible keys and 2^64 possible blocks, it should be obvious that some keys will encrypt a single plaintext to the same ciphertext. Finding such a pair of keys requires about 2^32 calculations on average (because of the birthday paradox).
If the plaintext is larger (requires more than one block encrypt) then the chance of finding a different key that produces the same ciphertext quickly will go to zero.
If one of the keys is preset it will take about 2^64 calculations to find another key. And - for the same reason - there is only a chance of 1 / 2^64 to use two keys that unfortunately produce the same ciphertext for a specific plaintext.
If you want to make the calculations yourself, more information here on the crypto site.
How many keys can be used to encrypt data using 3DES algorithm?
2^168 if you consider the full set of possible keys, i.e. you allow DES-ABC keys. These keys are encoded as 192 bits including parity. This would include DES-ABA and DES-AAA keys (the latter is equivalent to single DES).
2^112 if you consider only DES-ABA keys. These keys are encoded as 128 bits including parity. This would include single DES.

Encryption key generation and app performance

A question for cryptography experts. Imagine we have a conceptual Notes.app:
There are notes (title|content) stored as AES-256 encrypted strings
Application has to present a list of all notes (titles) in a list on its main window
Every title|content is encrypted with a key, generated from a password and a salt
Let's imagine the key generation algorithm takes ~80ms on a mobile device to generate a key
With the following conditions, it would take almost 1 second to decrypt 10 note titles. But what if there are lots of notes?
My 2 pennies on the problem: Encrypt all notes with different initialization vectors, but also with identical salt. That would allow me to generate a decryption key only once and decrypt lots of notes fast.
The question: doing so we would end up with lots of different notes, encrypted with an identical key. Does that somehow compromise the security of AES encryption? Is it possible that knowing there's a bunch of files with not just identical password, but also identical salt somehow makes it possible to crack the encryption?
Thanks for your thoughts
AES-256 do not use a salt. But I guess you use the salt together with the password in a PBE algorithm to generate the key. Usually this kind of PBE algorithms are constructed to be computational expensive - thus the 80 ms you see on your mobile.
When encrypting different messages, you could instead of using different salts to create different keys, just use different initialization vectors (IV) but the same key. The different IV ensures that messages that starts with the same block encrypts to different messages.

Proper/Secure encryption of data using AES and a password

Right now, this is what I am doing:
1. SHA-1 a password like "pass123", use the first 32 characters of the hexadecimal decoding for the key
2. Encrypt with AES-256 with just whatever the default parameters are
^Is that secure enough?
I need my application to encrypt data with a password, and securely. There are too many different things that come up when I google this and some things that I don't understand about it too. I am asking this as a general question, not any specific coding language (though I'm planning on using this with Java and with iOS).
So now that I am trying to do this more properly, please follow what I have in mind:
Input is a password such as "pass123" and the data is
what I want to encrypt such as "The bank account is 038414838 and the pin is 5931"
Use PBKDF2 to derive a key from the password. Parameters:
1000 iterations
length of 256bits
Salt - this one confuses me because I am not sure where to get the salt from, do I just make one up? As in, all my encryptions would always use the salt "F" for example (since apparently salts are 8bits which is just one character)
Now I take this key, and do I hash it?? Should I use something like SHA-256? Is that secure? And what is HMAC? Should I use that?
Note: Do I need to perform both steps 2 and 3 or is just one or the other okay?
Okay now I have the 256-bit key to do the encryption with. So I perform the encryption using AES, but here's yet another confusing part (the parameters).
I'm not really sure what are the different "modes" to use, apparently there's like CBC and EBC and a bunch of others
I also am not sure about the "Initialization Vector," do I just make one up and always use that one?
And then what about other options, what is PKCS7Padding?
For your initial points:
Using hexadecimals clearly splits the key size in half. Basically, you are using AES-128 security wise. Not that that is bad, but you might also go for AES-128 and use 16 bytes.
SHA-1 is relatively safe for key derivation, but it shouldn't be used directly because of the existence/creation of rainbow tables. For this you need a function like PBKDF2 which uses an iteration count and salt.
As for the solution:
You should not encrypt PIN's if that can be avoided. Please make sure your passwords are safe enough, allow pass phrases.
Create a random number per password and save the salt (16 bytes) with the output of PBKDF2. The salt does not have to be secret, although you might want to include a system secret to add some extra security. The salt and password are hashed, so they may have any length to be compatible with PBKDF2.
No, you just save the secret generated by the PBKDF2, let the PBKDF2 generate more data when required.
Never use ECB (not EBC). Use CBC as minimum. Note that CBC encryption does not provide integrity checking (somebody might change the cipher text and you might never know it) or authenticity. For that, you might want to add an additional MAC, HMAC or use an encryption mode such as GCM. PKCS7Padding (identical to PKCS5Padding in most occurences) is a simple method of adding bogus data to get N * [blocksize] bytes, required by block wise encryption.
Don't forget to prepend a (random) IV to your cipher text in case you reuse your encryption keys. An IV is similar to a salt, but should be exactly [blocksize] bytes (16 for AES).

Key salt and initial value AES

I am creating an encryption scheme with AES in cbc mode with a 256-bit key. Before I learned about CBC mode and initial values, I was planning on creating a 32-bit salt for each act of encryption and storing the salt. The password/entered key would then be padded with this salt up to 32 bits.
ie. if the pass/key entered was "tree," instead of padding it with 28 0s, it would be padded with the first 28 chars of this salt.
However, this was before I learned of the iv, also called a salt in some places. The question for me has now arisen as to whether or not this earlier method of salting has become redundant in principle with the IV. This would be to assume that the salt and the iv would be stored with the cipher text and so a theoretical brute force attack would not be deterred any.
Storing this key and using it rather than 0s is a step that involves some effort, so it is worth asking I think whether or not it is a practically useless measure. It is not as though there could be made, with current knowledge, any brute-force decryption tables for AES, and even a 16 bit salt pains the creation of md5 tables.
Thanks,
Elijah
It's good that you know CBC, as it is certainly better than using ECB mode encryption (although even better modes such as the authenticated modes GCM and EAX exist as well).
I think there are several things that you should know about, so I'll explain them here.
Keys and passwords are not the same. Normally you create a key used for symmetric encryption out of a password using a key derivation function. The most common one discussed here is PBKDF2 (password based key derivation function #2), which is used for PBE (password based encryption). This is defined in the latest, open PKCS#5 standard by RSA labs. Before entering the password need to check if the password is correctly translated into bytes (character encoding).
The salt is used as another input of the key derivation function. It is used to prevent brute force attacks using "rainbow tables" where keys are pre-computed for specific passwords. Because of the salt, the attacker cannot use pre-computed values, as he cannot generate one for each salt. The salt should normally be 8 bytes (64 bits) or longer; using a 128 bit salt would give you optimum security. The salt also ensures that identical passwords (of different users) do not derive the same key.
The output of the key derivation function is a secret of dkLen bytes, where dkLen is the length of the key to generate, in bytes. As an AES key does not contain anything other than these bytes, the AES key will be identical to the generated secret. dkLen should be 16, 24 or 32 bytes for the key lengths of AES: 128, 192 or 256 bits.
OK, so now you finally have an AES key to use. However, if you simply encrypt each plain text block with this key, you will get identical result if the plain text blocks are identical. CBC mode gets around this by XOR'ing the next plain text block with the last encrypted block before doing the encryption. That last encrypted block is the "vector". This does not work for the first block, because there is no last encrypted block. This is why you need to specify the first vector: the "initialization vector" or IV.
The block size of AES is 16 bytes independent of the key size. So the vectors, including the initialization vector, need to be 16 bytes as well. Now, if you only use the key to encrypt e.g. a single file, then the IV could simply contain 16 bytes with the value 00h.
This does not work for multiple files, because if the files contain the same text, you will be able to detect that the first part of the encrypted file is identical. This is why you need to specify a different IV for each encryption you perform with the key. It does not matter what it contains, as long as it is unique, 16 bytes and known to the application performing the decryption.
[EDIT 6 years later] The above part is not entirely correct: for CBC the IV needs to be unpredictable to an attacker, it doesn't just need to be unique. So for instance a counter cannot be used.
Now there is one trick that might allow you to use all zero's for the IV all the time: for each plain text you encrypt using AES-CBC, you could calculate a key using the same password but a different salt. In that case, you will only use the resulting key for a single piece of information. This might be a good idea if you cannot provide an IV for a library implementing password based encryption.
[EDIT] Another commonly used trick is to use additional output of PBKDF2 to derive the IV. This way the official recommendation that the IV for CBC should not be predicted by an adversary is fulfilled. You should however make sure that you do not ask for more output of the PBKDF2 function than that the underlying hash function can deliver. PBKDF2 has weaknesses that would enable an adversary to gain an advantage in such a situation. So do not ask for more than 256 bits if SHA-256 is used as hash function for PBKDF2. Note that SHA-1 is the common default for PBKDF2 so that only allows for a single 128 bit AES key.
IV's and salts are completely separate terms, although often confused. In your question, you also confuse bits and bytes, key size and block size and rainbow tables with MD5 tables (nobody said crypto is easy). One thing is certain: in cryptography it pays to be as secure as possible; redundant security is generally not a problem, unless you really (really) cannot afford the extra resources.
When you understand how this all works, I would seriously you to find a library that performs PBE encryption. You might just need to feed this the password, salt, plain data and - if separately configured- the IV.
[Edit] You should probably look for a library that uses Argon2 by now. PBKDF2 is still considered secure, but it does give unfair advantage to an attacker in some cases, letting the attacker perform fewer calculations than the regular user of the function. That's not a good property for a PBKDF / password hash.
If you are talking about AES-CBC then it is an Initialisation Vector (IV), not Salt. It is common practice to send the IV in clear as the first block of the encyphered message. The IV does not need to be kept secret. It should however be changed with every message - a constant IV means that effectively your first block is encrypted in ECB mode, which is not properly secure.

AES key derivation

What is the correct (acceptable) way to derive an, lets say 128 bit AES key from the secret derived in a DH negotiation?
Use the first 128 bit
Hash the secret and use the first 128 bit
Use some more complicated derivation function
How would you derive a set of keys in a "correct" manner?
I would use a standard. One such standard is NIST Special Pub 800-56A. See in particular section 5.8.
For instance, in TLS used pseudo-random function, which is based on SHA1 and MD5 hash over shared secret (i.e. DH key exchange value), string label (to distinguish different cases for which key is generated, HMAC, cipher and so on), and shared random parameter (both client and server generates his own half of random parameter).
So, i'd recommend to add some random data generated by both client and server, and hash it together with DH key exchange value.

Resources