Search code examples
phpmcryptrijndael

mcrypt_encrypt(): Key of size 29 not supported by this algorithm


i have my old code back from 2011 which calculate hash

private static $key = '[email protected]#€2011GAMESITES';

/**
 * Computes salted password hash.
 * @param  string
 * @return string
 */
public static function calculateHash($password)
{
    $text = $password;
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, self::$key, $text, MCRYPT_MODE_ECB, $iv);
    return base64_encode($crypttext);
}

When i try to run it now I get an error:

Warning: mcrypt_encrypt(): Key of size 29 not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported in ..\Hash.php on line 27

I know it takes a long time from 2011 and there can be better ways to do it now, but I need to make it work from previous version for some historical issue. What i am doing wrong? I cant even see what size 29 does it mean.

Or alternativly is there a way how to break a hash if I still got a function? with this i can potencialy start using new way of calculating hash.

Thanks for any advise


Solution

  • If you consult the changelog in the documentation for mcrypt_encrypt, you should see that since PHP 5.6.0...

    Invalid key and iv sizes are no longer accepted. mcrypt_encrypt() will now throw a warning and return FALSE if the inputs are invalid. Previously keys and IVs were padded with '\0' bytes to the next valid size.

    The solution is therefore to replace your key by one that is padded with null characters to 32 bytes.

    Unfortunately, there is a non-ASCII character in there (the euro sign), so there are multiple possibilities how that is supposed to be encoded. It's probably best to manually encode this character. In Unicode, the euro sign has codepoint U+20AC, which would translate to '\xE2\x82\xAC' (which explains why mcrypt counts 29 bytes instead of 27), making your new key

    private static $key = '[email protected]#\xE2\x82\xAC2011GAMESITES\0\0\0';
    

    Note that we have to assume some character encoding for your code; I have assumed UTF-8. It's unlikely but possible that, in 2011, it was supposed to be encoded in another character encoding (e.g. ISO-8859-1), which results in a very different encoding for the euro sign.