2

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?

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
user4271704
  • 723
  • 1
  • 12
  • 37
  • 2
    how would it be a security risk? All you're doing is taking some bytes and converting them into some other bytes. The risk comes from how you **USE** those bytes. – Marc B Jan 08 '16 at 16:42
  • If converting some bytes to other bytes has nothing to do with security then why those php functions and `random_bytes()` are there at all? as anybody could just generate some random bytes? – user4271704 Jan 08 '16 at 16:52
  • because bin2hex isn't fundamentally changing the bytes, it's just converting them into a different DISPLAY FORMAT. the values don't change, just how humans can view them. They're still random bytes, they're just printable as hex values, instead of being "garbage" on your screen. – Marc B Jan 08 '16 at 16:56
  • @MarcB Since bytes are basically strings in PHP, this means that an IV that is used from the hex-encoded string only has half of the entropy. It's not unheard of to use the hex-encoded output in as though it's bytes, particularly to the untrained eye. – Artjom B. Jan 08 '16 at 17:03
  • @ArtjomB. Like said, it depends how those hex'd bytes are being used. OP made no mention about feeding the hex back into the system. – Marc B Jan 08 '16 at 17:10
  • @MarcB Well, it was a little reading between the lines. Since the question is tagged with [tag:initialization-vector], I assumed that it should be used as an IV. – Artjom B. Jan 08 '16 at 17:17
  • If I understood correctly this all, I should convert back them into binary before using it as IV. Not recommended to use its hexits version as IV, right? – user4271704 Jan 08 '16 at 17:23
  • @user4271704 Yes, exactly. – Artjom B. Jan 08 '16 at 17:32
  • @Artjom B. And how to convert back this hexit to binary as `hex2bin()` just gives 0, 1? I guess I should use `pack()`? But how? – user4271704 Jan 08 '16 at 18:37
  • @user4271704 `$bin_string = pack("H*", $hex_string)` – Artjom B. Jan 08 '16 at 18:46
  • @Artjom B.   If using hash_pbkdf2() to generate AES key or even use it as password, how much iteration is reasonable? 1000 is good? – user4271704 Jan 08 '16 at 18:51
  • @user4271704 1000 is a bit low nowadays. A million is better, but you should profile your server so that a single password derivation is not longer than half a second or a second. Otherwise, you will have piss off your users. Please don't ask further questions in comments. Either ask new questions or google a bit. You will quickly find most of your answers here on [so] or over on [security.se]. – Artjom B. Jan 08 '16 at 18:54
  • 2
    Stack Overflow is a site for programming and development questions. This question appears to be off-topic because it is not about programming or development. See [What topics can I ask about here](http://stackoverflow.com/help/on-topic) in the Help Center. Perhaps [Cryptography Stack Exchange](http://crypto.stackexchange.com/) or [Information Security Stack Exchange](http://security.stackexchange.com/) would be a better place to ask. – jww Jan 09 '16 at 01:48
  • 1
    Cross-posted from Crypto.SE: [Is it secure to use hexadecimal data for IV instead of raw binary?](http://crypto.stackexchange.com/q/31781/13022) – Artjom B. Jan 09 '16 at 12:04

1 Answers1

3

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.

Community
  • 1
  • 1
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • Sidenote: the PHP implementations don't conform to [cryptography coding standards](https://cryptocoding.net/index.php/Coding_rules), and thus might leak information via timing differences on cache misses. There's no good mitigation for this at the moment, though PHP 7.1 might fix it. I haven't seen any practical exploits, so it might not be a big deal. – Scott Arciszewski Jan 14 '16 at 07:54