tasos-py / AES-Encryption-Classes

AES encryption in Python, PHP, C#, Java, C++, F#, Ruby, Scala, Node.js
MIT License
145 stars 58 forks source link

MAC check Failed. #8

Closed shujaat-github closed 2 years ago

shujaat-github commented 2 years ago

I can encrypt and decrypt data in Java but if I encrypt data in Java then I can't decrypt it in PHP and I get MAC check failed error.

Java Code:

AesEncryption aes = new AesEncryption("cbc", 256);
byte[] encryptedData = aes.encrypt("Hello", "PASSWORD");
String encryptedString = new String(encryptedData);

Now when I try to decrypt encryptedString in PHP using the same password, I get this error:

MAC check failed!
tasos-py commented 2 years ago

I can't reproduce the error (with java version "17.0.1" and PHP 7.4.27). For example, the code below works fine, Java

    AesEncryption aes = new AesEncryption("cbc", 256);
    byte[] encryptedData = aes.encrypt("Hello", "PASSWORD");
    System.out.println(new String(encryptedData));

    //JnTRpJ2ql5ATHmiRWJsAO8Ek6DDLiAy/9HV0EncIPzFFfY4FnytwCQFvcb5z/lms1mp0VBP6w02SJLHW2BpycUZMD0vioTx96LzkEnmRZNU=

PHP

    $aes = new AesEncryption("cbc", 256);
    $ct = 'JnTRpJ2ql5ATHmiRWJsAO8Ek6DDLiAy/9HV0EncIPzFFfY4FnytwCQFvcb5z/lms1mp0VBP6w02SJLHW2BpycUZMD0vioTx96LzkEnmRZNU=';
    $pwd = "PASSWORD";
    var_dump($aes->decrypt($ct, $pwd));

    //string(5) "Hello"

Could you give me you Java and PHP versions, and a more detailed example of code usage and output?

shujaat-github commented 2 years ago

Tested using both PHP v7.4.25 and v7.4.3.

Java (Microsoft Build of OpenJDK): I use latest version of Visual Studio Code v1.71.2 and Extension Pack for Java Extension for Java development in VS Code.

java --version
openjdk 17.0.4.1 2022-08-12 LTS
OpenJDK Runtime Environment Microsoft-40354 (build 17.0.4.1+1-LTS)
OpenJDK 64-Bit Server VM Microsoft-40354 (build 17.0.4.1+1-LTS, mixed mode, sharing)

Anything I encrypt in Java I cannot decrypt in PHP as it fails with MAC check failed error, HOWEVER, anything I encrypt in PHP I can decrypt in Java.

Java:

AesEncryption aes = new AesEncryption("cbc", 256);
byte[] encryptedData = aes.encrypt("Hello", "PASSWORD");
System.out.println(new String(encryptedData));

//Rj65uM9cRkuGNdggFf4gUTUkF5G+HINn4Gp+4CBhRS481uMAvhvk4OmEUejkfDps0kcyvJLhGHj3QLp3uq794up9Uol/nsiXdApzOoxY0yc=

PHP

$aes = new AesEncryption("cbc", 256);
$ct = 'Rj65uM9cRkuGNdggFf4gUTUkF5G+HINn4Gp+4CBhRS481uMAvhvk4OmEUejkfDps0kcyvJLhGHj3QLp3uq794up9Uol/nsiXdApzOoxY0yc=';
$pwd = "PASSWORD";
var_dump($aes->decrypt($ct, $pwd));

//MAC check failed!NULL
tasos-py commented 2 years ago

Thanks for all the details. Unfortunately, I still can't reproduce the error. Your Java ciphertext decrypts fine with PHP in my environment. Can you do me a favor? Can you remove verification (comment out https://github.com/tasos-py/AES-Encryption-Classes/blob/master/AesEncryption.class.php#L109), to see what the plaintext looks like?

shujaat-github commented 2 years ago

I get:

Padding is invalid!NULL

when I comment out the following line:

$this->verify($iv.$ciphertext, $mac, $macKey);

shujaat-github commented 2 years ago

Any suggestions or ideas are welcomed. I would be happy to test this issue in any way you wish.

shujaat-github commented 2 years ago

AES-Encryption-Classes is quite stable and helpful library. I have tested encryption decryption using C++ and PHP and it work flawlessly. However, in case of Java and PHP I face the issue mentioned above.

tasos-py commented 2 years ago

I don't get this issue on my PC, so I really appreciate you helping me in debugging. So, now we know the problem is somewhere in padding. Could you replace Cipher.unpad(), https://github.com/tasos-py/AES-Encryption-Classes/blob/master/AesEncryption.class.php#L486 with the code bellow?

    private function unpad($data) {
        $pad = ord(mb_substr($data, -1, 1, "8bit"));
        $count = substr_count(mb_substr($data, -$pad, $pad, "8bit"), chr($pad));

        var_dump(bin2hex($data));
        var_dump($pad);
        var_dump($count);

        if ($pad < 1 || $pad > 16 || $count != $pad) {
            throw new RuntimeException("Padding is invalid!");
        }
        return mb_substr($data, 0, -$pad, "8bit");
    }

This should show us the last block, pad and pad length. It should be

string(32) "48656c6c6f0b0b0b0b0b0b0b0b0b0b0b"
int(11)
int(11)
shujaat-github commented 2 years ago

Here is the output:

string(32) "e74851067cc8f5195e6b27b802770ee9" int(233) int(1) Padding is invalid!NULL
tasos-py commented 2 years ago

Actually, the problem is not padding, because MAC check happens before decryption. It's either in key generation or data slicing. Please go to https://github.com/tasos-py/AES-Encryption-Classes/blob/master/AesEncryption.class.php#L108 and add those lines,

            var_dump(bin2hex($salt));
            var_dump(bin2hex($iv));
            var_dump(bin2hex($ciphertext));
            var_dump(bin2hex($mac));
            var_dump(bin2hex($aesKey));
            var_dump(bin2hex($macKey));
shujaat-github commented 2 years ago

Snapshot for reference: image

string(32) "31323334353637383930313233343536" string(32) "31323334353637383930313233343536" string(32) "3cd6e300be1be4e0e98451e8e47c3a6c" string(64) "d24732bc92e11878f740ba77baaefde2ea7d52897f9ec897740a733a8c58d327" string(64) "8704897df8d4a3b036c076e476807959e27b82cc32992638b64d1876168a209a" string(64) "84a79ca810cac775a3f094063edcacb181adab5dab73fd729bc7cb640961b6aa" string(32) "e74851067cc8f5195e6b27b802770ee9" int(233) int(1) Padding is invalid!NULL

shujaat-github commented 2 years ago

Updated previous comment with required changes.

tasos-py commented 2 years ago

Thanks. I can't make sense of your salt and IV. Hex decoded, they're both "1234567890123456". According to your ciphertext, they should be "463eb9b8cf5c464b8635d82015fe2051" and "35241791be1c8367e06a7ee02061452e" (hex encoded). And I don't see how mb_substr() in AesEncryption.decrypt() could produce "1234567890123456". Do you have any idea where those values could be coming from?

shujaat-github commented 2 years ago

I am ashamed to take up so much of your precious time even though the mistake was on my part. I had accidentally hardcoded the salt and iv.

shujaat-github commented 2 years ago

@tasos-py Thank you very much for your valuable time. I am very grateful to you.

Programmers like me are forever in your debt for such a great library!

tasos-py commented 2 years ago

Glad to hear that! I'll be closing this issue now, since it's just a typo basically. And don't worry about it, those things happen all the time