Erroneous cryptography usage in reCAPTCHA API

As a developer you’ll definitely stumble upon a lot of ugly code, and sometimes some snippets are just plain “wtf?”. I found this one by an accident a couple of months ago while browsing through the reCAPTCHA API library developed by Google. First, let’s take a quick look at the PHP manual for a libmcrypt introduced function called mcrypt_encrypt():

string mcrypt_encrypt ( string $cipher , string $key , string $data , string $mode [, string $iv ] )

reCAPTCHA offers a way to only display email addresses to users that solve a CAPTCHA (catchy, huh?) called Mailhide. The Mailhide part of recaptchalib declares a function called _recaptcha_aes_encrypt() and it is declared as below:

function _recaptcha_aes_encrypt($val,$ky) {
        if (! function_exists ("mcrypt_encrypt")) {
                die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
        }
        $mode=MCRYPT_MODE_CBC;
        $enc=MCRYPT_RIJNDAEL_128;
        $val=_recaptcha_aes_pad($val);
        return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
}

As you can see, the initialization vector (the last parameter of mcrypt_encrypt()) used is statically defined as a nullbyte string. If you’ve studied cryptography to some extent you probably know that the entire purpose of the initialization vector is to ensure that the same data encrypted with the same key outputs different ciphertext, just like the purpose of a password salt is to generate different hashes for equal password strings in authentication.

By using the \0 IV string Google simply silences a warning which PHP would generate if mcrypt_encrypt() would be called using Rijndael in CBC mode without a specified IV, thus it is possible that the used IV is nothing but a fix of this warning. However, using a static nonrandom IV makes the algorithm susceptible to dictionary attacks. _recaptcha_aes_encrypt() may not be a very important part of the reCAPTCHA API to keep secure, but a very easy solution to this would be to use another block cipher mode which does not require an initialization vector.

Leave a Reply

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>