Encryption mismatch between Java and PHP

纵然是瞬间 提交于 2019-11-30 16:22:45

Since both encrypted strings start with the same characters, it looks like you're using ECB in one and CBC in the other.

What about this (to decrypt within Your PHP):

$toDecrypt = "TeUZAFxoFoQy/roPm5tXyPzJP/TLAwR1aIGn2xHbZpsbY1qrKwXfO+F/DAqmeTwB0b8e6dsSM+Yy0zrQt22E2Q==";
$decrypt = openssl_decrypt(base64_decode($toDecrypt),"AES256","key-32-char-long");
echo $decrypt;

You should decrypt the base64 decoded string and for decrypting You should call openssl_decrypt not openssl_encrypt :-)

you are using getBytes in java

instead use getBytes(Charset) method to ensure the same encoding of the key and plaintext as the one used in php

(dump the byte array in both and see if they match before you go on)

Some remarks:

  • the key size is not explicit in the java program
  • did you check what is the block cipher modes of operation of both programs ? CBC, ECB, OFB, etc... ? Some can require an IV to passe with the encrypted data.
  • last idea: what is the padding used by the Java and PHP programs ?

This document can help you: you have all the valid combinations cipher / block cipher mode / padding mode / key size.

user462990

I have just got this working. The thing to do is to encode the string as UTF-8 before padding and then send the byte array to encrypt. UTF-8 represents accented characters as two hex bytes c3 xx so the converted string will be longer if it contains characters that need to be encoded. BTW the c3 character is "A" with a "~" on top so if your decryption shows up with these odd characters then you haven't recoded the decryption.

import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec;

import android.util.Log;

public class MCrypt {

private IvParameterSpec ivspec;
private SecretKeySpec keyspec;
private Cipher cipher;
private String iv = "cant hear you";
private String SecretKey = "top secret";

public MCrypt()
{
    ivspec = new IvParameterSpec(iv.getBytes());
    keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");                        
    try {            
        cipher = Cipher.getInstance("AES/CBC/NoPadding");
    } catch (NoSuchAlgorithmException e) {
         e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    }
}

public byte[] encrypt(String text) throws Exception{
    if(text == null || text.length() == 0) throw new Exception("Empty string");

    byte[] bs = text.getBytes("UTF-8");

    byte[] toEncrypt = padBytes(bs);
    byte[] encrypted = null;
    try {
        cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
        encrypted = cipher.doFinal(toEncrypt);
    } catch (Exception e){                       
            throw new Exception("[encrypt] " + e.getMessage());
    }
    return encrypted;
}

public byte[] decrypt(String code) throws Exception{
    if(code == null || code.length() == 0)  throw new Exception("Empty string");        
    byte[] decrypted = null;
    try {
        cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);                
        decrypted = cipher.doFinal(hexToBytes(code));
    } catch (Exception e){
        throw new Exception("[decrypt] " + e.getMessage());
    }
    return decrypted;
}



    public static String bytesToHex(byte[] data){
        if (data==null){
            return null;
        }            
        int len = data.length;
        String str = "";
        for (int i=0; i<len; i++) {
            if ((data[i]&0xFF)<16)
                    str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
            else
                    str = str + java.lang.Integer.toHexString(data[i]&0xFF);
        }
        return str;
    }


    public static byte[] hexToBytes(String str) {
            if (str==null) {
                    return null;
            } else if (str.length() < 2) {
                    return null;
            } else {
                    int len = str.length() / 2;
                    byte[] buffer = new byte[len];
                    for (int i=0; i<len; i++) {
                            buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
                    }
                    return buffer;
            }
    }



    private static byte[] padBytes(byte[] source){
        char paddingChar = ' ';
        int size = 16;
        int x = source.length % size;
        int padLength = size - x;
        int bufferLength = source.length + padLength;
        byte[] ret = new byte[bufferLength];
        int i = 0;
        for ( ; i < source.length; i++){
            ret[i] = source[i];
        }
        for ( ; i < bufferLength; i++){
            ret[i] = (byte)paddingChar;
        }

        return ret;
    }
} // class close

The pHp side is similar... ( I cannot figure out how to enter pHp code here!!!!

class MCrypt
{               
private $iv =  'adfdadfgfd'; #Same as in JAVA
private $key = 'adfadfdfdafadfa'; #Same as in JAVA


function __construct()
{
}

function encrypt($str) {
  $iv = $this->iv;
  $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);
  mcrypt_generic_init($td, $this->key, $iv);
  $s = padString(utf8_encode($str));
  $encrypted = mcrypt_generic($td, $s);
    //echo $encrypted;
  mcrypt_generic_deinit($td);
  mcrypt_module_close($td);
  return bin2hex($encrypted);
}

function decrypt($code) {
  $code = $this->hex2bin($code);
  $iv = $this->iv;
  $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);
  mcrypt_generic_init($td, $this->key, $iv);
  $decrypted = mdecrypt_generic($td, $code);
  mcrypt_generic_deinit($td);
  mcrypt_module_close($td);
  return (trim(utf8_decode($decrypted)));
}

protected function hex2bin($hexdata) {
  $bindata = '';
  for ($i = 0; $i < strlen($hexdata); $i += 2) {
    $bindata .= chr(hexdec(substr($hexdata, $i, 2)));
  }
  return $bindata;
}   
}

that's it, quite straightforward really... Oh by the way, if you do the padding yourself then it does not matter if the method is Padding or NoPadding!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!