Is it safe and secure to use bin2hex()
on output of openssl_random_pseudo_bytes()
and mcrypt_create_iv()
to have them as Hex instead of binary raw data for use as an IV, or this is a security risk and not recommended?
The Initialization Vector (IV) is at most the size of the block size for most block cipher modes. Its use is to randomize the encryption so that if you encrypt the same message with the same key, something different comes out each time. This is an important property of semantic security.
If you encode the raw output of openssl_random_pseudo_bytes()
to hex, then you lose set half of the bits of the IV to a known value (0).
Examples:
The important property of the IV in CBC mode is that it must be unpredictable. If you use AES which has a block size of 128 bit, then this would result in an IV with 64 variable bits which makes predicting the IV easier, but not necessarily easy. See this example.
In CTR mode, the IV has to be unique and is generally called nonce. If the IV is reused, then it may be possible to deduce the plaintexts of the original and the new message. If you use AES, then it's common to use an IV of 96 bit, but your hex encoding would reduce that to 48 variable bits. If we take the birthday paradox into account, you will probably see the same IV after 224 encryptions with the same key. Basically, this quickly breaks security of your system. The behavior for block ciphers with smaller block sizes such as DES completely breaks the security even for a small amount of messages with the same key.
Always use the full raw output of openssl_random_pseudo_bytes()
and mcrypt_create_iv()
for IVs or keys. Using fewer entropy can make the life for an attacker of your system considerably easier.
However, you can use bin2hex()
and base64_encode()
for printing such randomly generated bytes for debug purposes or text-based transmission, but don't forget to decode them into their unprintable counterparts before using them again.