|
mcrypt_create_iv
Create an initialization vector (IV) from a random source
(PHP 4, PHP 5)
Example 1290. mcrypt_create_iv() example<?php Code Examples / Notes » mcrypt_create_ivfandelem
note: if you are experiencing a problem about complaining that the second parameter has to be a 'long' and you are giving a 'string' (for me, it was using MCRYPT_URANDOM) you might want to try MCRYPT_DEV_URANDOM :)
robert
It is important to note that all cipher modes except ecb require the same IV to be used in decryption as was used in encryption. You need to pass the key *and* the IV to your decrypt function. Initializing a new IV in the decrypt routine will not work. Since, "you even can send [the IV] along with your ciphertext without loosing security," a nice way to handle this is to prepend your IV to your ciphertext. Since the IV is fixed-width, you can then easily recover the IV and original ciphertext using mcrypt_get_iv_size() and substr(). Here is an example: <?PHP function my_encrypt($string,$key) { srand((double) microtime() * 1000000); //for sake of MCRYPT_RAND $key = md5($key); //to improve variance /* Open module, and create IV */ $td = mcrypt_module_open('des', '','cfb', ''); $key = substr($key, 0, mcrypt_enc_get_key_size($td)); $iv_size = mcrypt_enc_get_iv_size($td); $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); /* Initialize encryption handle */ if (mcrypt_generic_init($td, $key, $iv) != -1) { /* Encrypt data */ $c_t = mcrypt_generic($td, $string); mcrypt_generic_deinit($td); mcrypt_module_close($td); $c_t = $iv.$c_t; return $c_t; } //end if } function my_decrypt($string,$key) { $key = md5($key); //to improve variance /* Open module, and create IV */ $td = mcrypt_module_open('des', '','cfb', ''); $key = substr($key, 0, mcrypt_enc_get_key_size($td)); $iv_size = mcrypt_enc_get_iv_size($td); $iv = substr($string,0,$iv_size); $string = substr($string,$iv_size); /* Initialize encryption handle */ if (mcrypt_generic_init($td, $key, $iv) != -1) { /* Encrypt data */ $c_t = mdecrypt_generic($td, $string); mcrypt_generic_deinit($td); mcrypt_module_close($td); return $c_t; } //end if } // to test: //print my_decrypt(my_encrypt("Hello, world.","foo"),"foo"); ?> tim
From http://www.ciphersbyritter.com/GLOSSARY.HTM#IV (linked to above): "While it is often said that IV values need only be random-like or unpredictable, and need not be confidential, in the case of CBC mode, that advice can lead to man-in-the-middle attacks on the first plaintext block. If a MITM opponent knows the usual content of the first block, they can change the IV to manipulate that block (and only that block) to deliver a different address, or different dollar amounts, or different commands, or whatever. And while the conventional advice is to use a MAC at a higher level to detect changed plaintext, that is not always desirable or properly executed. But the CBC first-block problem is easily solved at the CBC level simply by enciphering the IV and otherwise keeping it confidential, and that can be reasonable even when a MAC will be used later." edwardzyang
For some reason, on my Windows installation, MCRYPT_RAND doesn't work at all: it always gives the same IV. This is a huge problem, especially for OFB and CTR, where using the same IV destroys security. Fortunantely, it's easy to emulate the IV function using other random generators that do indeed work (such as rand() ). Here's an example: <?php function alt_mcrypt_create_iv ($size) { $iv = ''; for($i = 0; $i < $size; $i++) { $iv .= chr(rand(0,255)); } return $iv; } ?> Note that this doesn't make it "more random" in any way, it just let's you use your own favorite random function to create randomness than the quirky mcrypt_create_iv. 03-jun-2005 05:53
First, the IV should be random and variable. The whole point of it is to ensure that the same plaintext does not encrypt to the same ciphertext every time. You most certainly do lose security if the IV is constant or public. The ciphertext should be E(IV | plaintext, key) Second, the IV should not be part of the decryption parameters at all. You should be able to decrypt the cipher text, throw away the initial vector at the front w/o even reading it, and have your plaintext: [IV | plaintext ] = D(ciphertext, key) All that is public is the size of the IV. These are well-known facts about cryptography. Check N. Kobliz's books for backup. Unless mcrypt conforms to the above, it is very seriously flawed and should not be used. 04-sep-2005 07:12
Correction to the last comment, the second parameter of rtrim() uses double quotes, not single quotes. So the corrected code is as follows: $retval = rtrim($retval, "\0"); // trim ONLY the nulls at the END ;) kkaiser
Clarification: I meant to type MCRYPT_DEV_RANDOM, MCRYPT_DEV_URANDOM and MCRYPT_RAND in the previous note, instead of DEV_RANDOM, DEV_URANDOM and DEV_RAND. :)
30-dec-2006 11:37
Chris is right. I think that the person to whom he was responding was mixing up initialization vectors and salts that you would use when MD5 hashing passwords to prevent dictionary attacks. In that case they do need to be random to thwart the dictionary attack most effectively, although they don't need to be secret (which is a moot point since every salt is different).
anonymous
At: edwardzyang at thewritingpot dot com 19-Jul-2005 10:06 This is because of the fact, that (like described in the manual above) this function does NOT reseed the random number generator, in contrary to rand(). Use srand() like suggested above to get correct IVs. kkaiser
After profiling a rather large, dynamic website I maintain to determine the cause of intermittent freezing in execution, I found that calls to mcrypt_create_iv() using DEV_RANDOM as the source consistently halted execution for anywhere from 0.2 to ~12 seconds per call, ironically at random. I'm making the assumption that the halts were caused by insufficient random input being currently available in /dev/random due to its intended function to block until enough random input is provided back to the device. I've found it to be sufficient for my needs to use a modified version of the alt_mcrypt_create_iv() function found below. Although untested, I assume using DEV_URANDOM or a combination of DEV_RAND with srand() would've solved the problem as well; I found out after the fact that /dev/urandom's intended function is to seamlessly provide cryptographically secure output from the random number generator when the /dev/urandom buffer was empty, and DEV_RAND would simply use the same rand() function as alt_mcrypt_create_iv(). -Kevin Kaiser chris
>First, the IV should be random and variable. The whole >point of it is to ensure that the same plaintext does not >encrypt to the same ciphertext every time. You most >certainly do lose security if the IV is constant or public. Wrong, Wrong WRONG! The initialization vector is ALLOWED to be PUBLIC! It is generally sent along with the ciphertext, UNENCRYPTED. >The ciphertext should be E(IV | plaintext, key) Wrong again! The initialization vector is NOT prepended to the plaintext before encryption. The IV is used to seed the feedback system! (which is why you don't need one in ECB mode - there is no feedback) >Second, the IV should not be part of the decryption >parameters at all. You should be able to decrypt the cipher >text, throw away the initial vector at the front w/o even >reading it, and have your plaintext: Nope. You need to seed the feedback mechanism during decryption to the SAME state as it was seeded during encryption. This means using the SAME IV! |
Change Languagemcrypt_cbc mcrypt_cfb mcrypt_create_iv mcrypt_decrypt mcrypt_ecb mcrypt_enc_get_algorithms_name mcrypt_enc_get_block_size mcrypt_enc_get_iv_size mcrypt_enc_get_key_size mcrypt_enc_get_modes_name mcrypt_enc_get_supported_key_sizes mcrypt_enc_is_block_algorithm_mode mcrypt_enc_is_block_algorithm mcrypt_enc_is_block_mode mcrypt_enc_self_test mcrypt_encrypt mcrypt_generic_deinit mcrypt_generic_end mcrypt_generic_init mcrypt_generic mcrypt_get_block_size mcrypt_get_cipher_name mcrypt_get_iv_size mcrypt_get_key_size mcrypt_list_algorithms mcrypt_list_modes mcrypt_module_close mcrypt_module_get_algo_block_size mcrypt_module_get_algo_key_size mcrypt_module_get_supported_key_sizes mcrypt_module_is_block_algorithm_mode mcrypt_module_is_block_algorithm mcrypt_module_is_block_mode mcrypt_module_open mcrypt_module_self_test mcrypt_ofb mdecrypt_generic |