mcrypt doesn't work in PHP 5.6 on windows/IIS
Asked Answered
B

4

7

I have been making heavy use of mcrypt in my php app for years, both on win/IIS and on linux. Although I'm running PHP 5.4.28 on my linux server, I just upgraded to PHP 5.6.11 on my windows 8.1 IIS box. And mcrypt no longer works. It doesn't throw any errors that I can see; it just doesn't work. Here is my encryption function:

function Encrypt($text){ 
    global $salt;
    if($text != "")
        return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $salt, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))));  
    else
        return "";
}   

This works fine on my linux server, but returns blank on my local windows box. From what I have read, mcrypt is built into php 5.6 for windows, so there should be no fiddling with extensions or ini file.

What am I missing?

Bloc answered 8/9, 2015 at 1:23 Comment(4)
Doesn't mcrypt use /dev/urandom?Atonsah
Tested with PHP 5.6.12 on Windows 8 and it works ... it can not as simple as your $text is empty ? have tried to var_dump($text) ?Hoy
I hope you realize how insecure that Encrypt function is.Gabbey
Notice that by chaining all the calls together you loose the ability to debug, to find where the error is occurring. It is also harder to rerad and comprehend. You are also conflating the various operations together. Consider using multiple statements with short lived variables. Write fore developers to read, understand and debug.Officer
B
5

PHP 5.6 has stronger encryption requirements than 5.4. In 5.6 you'll get this warning, which is really an error because it actually causes encryptions and decryptions to fail:

Warning: mcrypt_encrypt(): Key of size xx not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported.

...where "xx" is the length of your salt value. So the salt value has to be exactly 16, 24, or 32 characters in length.

Bloc answered 15/9, 2015 at 1:46 Comment(0)
G
8

Let's look at your code piece by piece. (With mostly cosmetic/whitespace changes.)

function Encrypt($text)
{
    global $salt; // Why not make this a second parameter?
    if($text != "") { // An unusual check, for sure
        return trim( // base64_encode doesn't leave whitespace
            base64_encode(
                mcrypt_encrypt(
                    MCRYPT_RIJNDAEL_256, // This is a non-standard variant of the
                                         // Rijndael cipher. You want to use the
                                         // MCRYPT_RIJNDAEL_128 constant if you
                                         // wanted to use AES here.
                    $salt, // This is a key, not a salt!
                    $text,
                    MCRYPT_MODE_ECB, // ECB mode is the worst mode to use for
                                     // cryptography. Among other reasons, it
                                     // doesn't even use the IV. Search for 
                                     // ECB penguins for an idea of why ECB
                                     // mode is such a bad idea.
                    mcrypt_create_iv(
                        mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
                        MCRYPT_RAND // You're using ECB mode so this is a waste
                                    // anyway, but you should use
                                    // MCRYPT_DEV_URANDOM instead of MCRYPT_RAND
                    )
                )
            )
        );  
    }
    return "";
}

I would strongly recommend that you don't use this function for anything. It's not secure. Don't use ECB mode.

Furthermore, unauthenticated encryption is dangerous and libmcrypt is abandonware.

Gabbey answered 17/9, 2015 at 7:35 Comment(7)
Scott, if you can give me a working example according to all your recommendations, I'll award you the bounty, in case you care about that.Bloc
Yeah, that's easy. Use defuse/php-encryption instead of writing your own.Gabbey
Hmmm...using encr libs included w/php isn't exactly writing my own. Also my webapp is not banking or national security...just sports refs checking their schedule.Bloc
You're not writing your own primitives, but you are writing your own protocol, which is just as dangerous. cryptofails.com/post/75204435608/…Gabbey
I wrote my own encryption algorithm once. It was based on ASCII substitutions, so primitive it was cheesy. Yet nobody could hack it. Several experienced crypto experts tried. I put it up on encryption forums. Nobody could touch it, even after I provided encryption examples with their decrypted plain text. This talk of "dangerous" encryption methodologies, easy to hack, etc, is all nonsense--unless it's someone like the NSA doing the hack.Bloc
"This talk ... is all nonsense--unless it's someone like the NSA doing the hack." ietf.org/mail-archive/web/cfrg/current/msg06805.htmlGabbey
"abandonware", love it. But is is not fully abandoned, when I submit change requests such as supporting PKCS#7 with code they are actively deleted! It is worse than abandonware and rather universally used.Officer
B
5

PHP 5.6 has stronger encryption requirements than 5.4. In 5.6 you'll get this warning, which is really an error because it actually causes encryptions and decryptions to fail:

Warning: mcrypt_encrypt(): Key of size xx not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported.

...where "xx" is the length of your salt value. So the salt value has to be exactly 16, 24, or 32 characters in length.

Bloc answered 15/9, 2015 at 1:46 Comment(0)
S
3

I don't have an answer, but this is rather long for a comment.

It doesn't throw any errors that I can see

Have you tested your configuration to verify that you can you see errors when they occur?

but returns blank on my local windows box

If it's returning then it's not causing a fatal error. Hence the mcrypt functions are defined. Have you checked that the constants are defined? Have you checked that the version of libmcrypt matches the PHP extension requirement?

Have you checked that the inputs to the mcrypt_*() functions look sensible?

return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $salt, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))));  

Even if the above worked, its a horrible bit of code. The reason for writing code and using high level languages is not so your computer can understand them but so human beings can understand the code:

$iv=mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$encypted=mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $salt, $text, MCRYPT_MODE_ECB
               , $iv, MCRYPT_RAND); 
$encoded=base64_encode($encrypted);
return $encoded;

(laying your code out like this also makes it simpler to inject checks, breakpoints and other debugging measures).

Shaduf answered 10/9, 2015 at 12:33 Comment(1)
"The reason for writing code and using high level languages is not so your computer can understand them but so human beings can understand the code" == quote of the day.Synchronize
B
0

As SweatCoder stated before, your key for MCRYPT_RIJNDAEL_256 has to have a length of 32. To continue working with your old key being smaller than 32 (here called $oldkey) use

$key = str_pad($oldkey, 32, chr(0));

($key is what you called $salt)

Bogey answered 17/12, 2015 at 12:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.