This is so cool -- I get regularly asked for an irssi plugin that can do mircryption and i always had to say no -- people are going to be happy to see this. Really nice.
For those with some technical interest:
Gothic and I spent a few hours actually getting the CBC encryption mode to work.. It was really an interesting mystery solving experience.. It's amazing how little incompatibilities creep in with these things.. there are so many different ways to do everything, and using one person's code to do encryption and another persons code to do decryption, even when there is a standard, can be nervewracking.
Perl use a clever module "
Crypt-CBC" that basically oversees the creation of an object to do CBC encryption using different cipher algorithms. Well, blowfish (which is used in mircryption), is somewhat unusual in that it can accept a variable length key. The Crypt-CBC wrapper has code to check whether the key you pass is the length that the cipher algorithm wants. In the case of Blowfish, the algorithm tells CBC that it wants a 448 bit key, but really this value is just the maximum length of the key that it will accept. Crypt-CBC actually has a few options that aren't quite standard blowfish-cbc (like password hashing), which may be good ideas but makes compatibility a little tricky. But it's the fixed 56character key length strict requirement that was causing us trouble.
What really through me was that because of the way blowfish uses the key, it seemed like we could just fill up the remaining characters to get a 56 byte key, by repeating the key (so key of "test" becomes "testtesttest.." and so on up to 56 characters). This should work because blowfish uses the key by iterating through a loop and advancing over the key and then recycling when it gets to the end (thats how it is able to use a variable length key). So we thought we had it figured out, gothic wrote his readme and posted it, then we tried a different key and BZZZZ it stopped working -- encryption and decryption between the irssi script and mircryption was garbled.
It turned out some keys worked and others didn't. We pretty quickly determined that keys that were evenly divisible into 56 characters worked, others didn't. It seemed like that clue pointed to the way we were generating the expanded 56 character key for the perl module, but it took us several hours and going through the original c++ of the blowfish algorithm (which i don't claim to understand well even after reading a couple of schneier's books), before we solved the problem.
I incorrectly assumed that there had to be a 56 byte (448bit) key equivalent of any shorter key (ie that the shorter key was being expanded to 56 characters in some fashion, explicitly or implicitly). But this is simply not valid. The Blowfish algorithm reuses shorter keys by wrapping around the end of the key back to the beginning as it iterates over it. But significantly, the index it uses goes PAST 56 iterations (its more like 72). What this means basically is that when you expand a short key to fill 56 bytes, then the first 56 iterations over a small key or an expanded key will be identical. BUT after the 56 iteration, the short key will wrap around perfectly just as it has been doing, but the long key, if its original source key length was not divisible evenly into 56, will "wrap around" to something different.
To see why, imagine a key of 3 letters "ABC". Now we expand that to be 56 bytes, and we get "ABCABCABCABC...ABCABCAB" so that its a repeating pattern, BUT it doesnt end at the end of the original key, so that when the blowfish algorithm wraps around at the 56th iteration we see ABC
ABABCABC" and therein was the problem.
So the heart of the problem and fix is that the Crypt-CBC perl module should NOT be enforcing a fixed length 448 bit key when blowfish is used for the cipher algorithm. It's a simple one line change in the module code. There is also, luckily for us, a way to trick it to use the smaller key, which is what gothic does, by initializing it the object one way (at which point it checks the length), and then afterwards manually setting a flag to change the key type or length behind the back of the module. then everything works fine.