<?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.