Unable to exchange data encrypted with AES-256 between Java and PHP

前端 未结 4 1563
陌清茗
陌清茗 2020-12-04 22:51

My problem is: what I encrypt in Java I can decrypt perfectly in Java, but PHP mcrypt can\'t decrypt. What I encrypt with mcrypt I can decrypt with

相关标签:
4条回答
  • 2020-12-04 23:32

    I know this is an old topic, but I will add my working solution.

    You have to rewrite PHP side of the script:

    function getEncrypt($sStr, $sKey) {
      return base64_encode(
        mcrypt_encrypt(
            MCRYPT_RIJNDAEL_128, 
            base64_decode($sKey),
            $sStr,
            MCRYPT_MODE_ECB
        )
      );
    }
    
    function getDecrypt($sStr, $sKey) {
      return mcrypt_decrypt(
        MCRYPT_RIJNDAEL_128, 
        base64_decode($sKey), 
        base64_decode($sStr), 
        MCRYPT_MODE_ECB
      );
    }
    

    You should base64_decode($sKey) because your key is base64 encoded.

    $key = "Zvzpv8/PXbezPCZpxzQKzL/FeoPw68jIb+NONX/LIi8=";
    

    Then, you need to create this function (credit goes to beltrachi from http://www.php.net/manual/en/function.mcrypt-decrypt.php):

    function pkcs5_pad ($text, $blocksize) { 
      $pad = $blocksize - (strlen($text) % $blocksize); 
      return $text . str_repeat(chr($pad), $pad); 
    }
    

    Use this code do encode/decode:

    $decrypt = getDecrypt("6XremNEs1jv/Nnf/fRlQob6oG1jkge+5Ut3PL489oIo=", $key);
    echo $decrypt;
    echo "\n\n";
    echo getEncrypt(pkcs5_pad("My very secret text:)", 16), $key);
    

    I hope this will be useful for someone! :)

    0 讨论(0)
  • 2020-12-04 23:32

    Keep in mind to have the same encoding for the strings. Try to convert the strings in both languages to UTF-8, e.g., and than convert to binary data that is encoded:

    PHP (s. utf8_encode() function):

    $strAndBlob = utf8_encode("My string");
    

    Java:

    String str = "My string";
    byte[] blob = str.getBytes("utf-8");
    

    PHP, e.g., must not use UTF-8 by default.

    0 讨论(0)
  • 2020-12-04 23:35

    Please see here:

    • Difference in PHP encryption from iOS and .NET

    • AES Encrypt in C#, decrypt in PHP

    • DES Encryption in PHP and C#

    The problem you're encountering is a padding-issue. I don't know Java, but AES/ECB/PKCS5Padding looks like you're using a PKCS#5 (that's essentially the same as PKCS#7) padding while PHP natively only support NULL-padding. That's what PKCS#5/7 does:

    Pad the input with a padding string of between 1 and 8 bytes to make the total length an exact multiple of 8 bytes. The value of each byte of the padding string is set to the number of bytes added - i.e. 8 bytes of value 0x08, 7 bytes of value 0x07, ..., 2 bytes of 0x02, or one byte of value 0x01.

    So the PHP code to do the padding right is trivial:

    $blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
    $padding   = $blockSize - (strlen($data) % $blockSize);
    $data      .= str_repeat(chr($padding), $padding);
    
    0 讨论(0)
  • 2020-12-04 23:36

    BUG#1

    MCRYPT_RIJNDAEL_256 is not AES. The 256 in that constant refers to the blocksize, not the keysize. Use MCRYPT_RIJNDAEL_128 to get the same algorithm as AES. The keysize is set just by the number of bytes in the key argument you supply. So supply 32 bytes and you get AES with a 256-bit key.

    BUG#2

    These two lines are never correct in Java and indicate a fundamental misunderstanding of the nature of the arbitrary binary data produced by cryptographic transforms:

    output = cipher.doFinal(Base64.decodeBase64(input));
    return new String(output);
    

    There is nothing wrong with transmitting and storing byte[] directly, but if you must use only printable strings then you should base64 encode/decode to do so. As you are already using base64 extensively that would seem like the way to go. I would guess that the correct two lines would be:

    output = cipher.doFinal(Base64.decodeBase64(input));
    return new String(Base64.encodeBase64(output), "UTF-8");
    

    EDIT:

    Just kidding about bug #2. Really, I was wrong, I didn't notice it was the decrypt direction. Of course, if you know the decrypted byte[] is a valid string then it is perfectly correct to do what your code does.

    0 讨论(0)
提交回复
热议问题