PHP Documentation Woes

This bit of php documentation has some interesting code:

 <?php <br /> $passphrase = 'My secret';  

/* Turn a human readable passphrase
* into a reproducable iv/key pair
*/
$iv = substr(md5('iv'.$passphrase, true), 0, 8);
$key = substr(md5('pass1'.$passphrase, true) .
md5('pass2'.$passphrase, true), 0, 24);
$opts = array('iv'=>$iv, 'key'=>$key);

$fp = fopen('secret-file.enc', 'wb');
stream_filter_append($fp, 'mcrypt.tripledes', STREAM_FILTER_WRITE, $opts);
fwrite($fp, 'Secret secret secret data');
fclose($fp);
?>

3DES takes a 192-bit key (actually 168), so the first two keys are taken from the first MD5 and the third key is taken from the second MD5. I have a strong suspicion that that alignment introduces some kind of vulnerability, but I can’t quite put my finger on it. If anyone knows, please leave a comment.

This tweet says it all:

Lessons Learned:
  • Don’t use MD5 to derive keys from passwords. Use PBKDF2.
  • Use a random, unique IV. Don’t derive it from the password.
  • Documentation will be used by many people. It’s worth hiring a cryptographer to check it.