<?php
$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:
@DefuseSec With documentation like that, it's no wonder we see so much crap code. :-\Lessons Learned:
— Adam Caudill (@adamcaudill) July 29, 2013
- 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.
Well I'd say that one problem with mentioned approach is that MD5 is fast while PBKDF2 is slow by design. This means that you bruteforce / run a dictionary attack on MD5 derived keys more efficiently.
ReplyDeleteMartin Rublik