PHP equivalent encryption/decryption for Java trip

2019-04-17 18:17发布

问题:

I have to encrypt and decrypt using tripleDES to send some information to a specific server. The server use java to decrypt and I use PHP to encrypt and decrypt data.

I have tried using this PHP Equivalent for Java Triple DES encryption/decryption but it does not work for my problem.

My java code is the following: Note: Cadena means "string" and Llave means "key". The java code is not mine.

public class TripleDes {

    public static String EncryptTripleDES(String Cadena, String Llave)
    {
        String cryptedString = "";
        try{
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DESede");
            Cipher desEdeCipher = Cipher.getInstance("DESede/ECB/NoPadding");
            MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");

            byte[] arrayOfByte1 = Llave.getBytes();
            byte[] arrayOfByte3 = new byte[24];

            localMessageDigest.update(arrayOfByte1);
            byte[] result = localMessageDigest.digest();

            for (int i=0; i<999; i++){
               localMessageDigest.update(result);
               result = localMessageDigest.digest();
            }

            byte[] arrayOfByte4 = result;

            for (int n=0; n<16; n++)
               arrayOfByte3[n] = arrayOfByte4[n];

            for (int n=0; n<8; n++) 
               arrayOfByte3[(16 + n)] = arrayOfByte4[n];

            DESedeKeySpec localDESedeKeySpec = new DESedeKeySpec(arrayOfByte3, 0);
            SecretKey desEdeKey = secretKeyFactory.generateSecret(localDESedeKeySpec);
            desEdeCipher.init(1, desEdeKey);

            byte[] arrayOfByte = new byte[Cadena.length() % 8 > 0 ? Cadena.length() + 8 - Cadena.length() % 8 : Cadena.length()];
            System.arraycopy(Cadena.getBytes(), 0, arrayOfByte, 0, Cadena.length());

            //Resultado en base 64:
            String b_64 = encryptaBase64(desEdeCipher.doFinal(arrayOfByte));

            //Convertir resultado a cadena en hexadecimal
            cryptedString = StringToHexString(b_64);

        }catch(Exception e){
          e.printStackTrace();
        }
        return cryptedString;
    }

    public static String StringToHexString(String s) {
        StringBuffer stringbuffer = new StringBuffer(s.length() * 2);
        for (int i = 0; i < s.length(); i++) {
            int j = s.charAt(i) & 0xff;
            if (j < 16)
                stringbuffer.append('0');
            stringbuffer.append(Integer.toHexString(j));
        }
        return stringbuffer.toString().toUpperCase();
    }

    public static String encryptaBase64(byte[] paramArrayOfByte) throws Exception{
        int i = paramArrayOfByte.length;
        int j = (i * 4 + 2) / 3;
        int k = (i + 2) / 3 * 4;
        byte[] result = new byte[k];
        char[] map1 = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'};
        int m = 0;
        for (int n = 0; m < i; n++)
        {
            int i1 = paramArrayOfByte[(m++)] & 0xFF;
            int i2 = m < i ? paramArrayOfByte[(m++)] & 0xFF : 0;
            int i3 = m < i ? paramArrayOfByte[(m++)] & 0xFF : 0;
            int i4 = i1 >>> 2;
            int i5 = (i1 & 0x3) << 4 | i2 >>> 4;
            int i6 = (i2 & 0xF) << 2 | i3 >>> 6;
            int i7 = i3 & 0x3F;
            result[(n++)] = ((byte)map1[i4]);
            result[(n++)] = ((byte)map1[i5]);
            result[n] = ((byte)(n < j ? map1[i6] : 61)); n++;
            result[n] = ((byte)(n < j ? map1[i7] : 61));
        }
        return new String(result);
    }

    public static String DecryptTripleDES(String Cadena, String Llave)
    {
        String decryptedString = "";
        try
        {
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DESede");
            Cipher desEdeCipher = Cipher.getInstance("DESede/ECB/NoPadding");
            MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");

            byte[] arrayOfByte1 = Llave.getBytes();
            byte[] arrayOfByte3 = new byte[24];

            localMessageDigest.update(arrayOfByte1);
            byte[] result = localMessageDigest.digest();

            for (int i=0; i<999; i++){
               localMessageDigest.update(result);
               result = localMessageDigest.digest();
            }
            byte[] arrayOfByte4 = result;

            for (int n=0; n<16; n++)
               arrayOfByte3[n] = arrayOfByte4[n];

            for (int n=0; n<8; n++) 
               arrayOfByte3[(16 + n)] = arrayOfByte4[n];

            DESedeKeySpec localDESedeKeySpec = new DESedeKeySpec(arrayOfByte3, 0);
            SecretKey desEdeKey = secretKeyFactory.generateSecret(localDESedeKeySpec);
            desEdeCipher.init(2, desEdeKey);

            //Convertir cadena hexadecimal a String
            String hexString = "";
            for(int i = 0; i < Cadena.length()/2; i++){
                int k = Integer.parseInt(Cadena.substring(i*2, (i*2)+2), 16);
                hexString += (char)k;
            }

            result = desEdeCipher.doFinal(decrypt(hexString.getBytes()));
            decryptedString = new String(result).trim();
        }
        catch(Exception e){
            e.printStackTrace();
        }
        return decryptedString;
    }

    public static byte[] decrypt(byte[] paramArrayOfByte) throws Exception {
        byte[] map2 = new byte[256];
        char[] map1 = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'};
        for (int i = 0; i < map2.length; i++) map2[i] = -1;
        for (int i = 0; i < 64; i++) map2[map1[i]] = ((byte)i);

        int i = paramArrayOfByte.length;
        if (i % 4 != 0) throw new IllegalArgumentException("Length of Base64 encoded input string is not a multiple of 4.");
        while ((i > 0) && (paramArrayOfByte[(i - 1)] == 61)) i--;
        int j = i * 3 / 4;
        byte[] result = new byte[j];
        int k = 0;
        int m = 0;
        while (k < i)
        {
            int n = paramArrayOfByte[(k++)];
            int i1 = paramArrayOfByte[(k++)];
            int i2 = k < i ? paramArrayOfByte[(k++)] : 65;
            int i3 = k < i ? paramArrayOfByte[(k++)] : 65;
            if ((n > 127) || (i1 > 127) || (i2 > 127) || (i3 > 127))
                throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
            int i4 = map2[n];
            int i5 = map2[i1];
            int i6 = map2[i2];
            int i7 = map2[i3];
            if ((i4 < 0) || (i5 < 0) || (i6 < 0) || (i7 < 0))
                throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
            int i8 = i4 << 2 | i5 >>> 4;
            int i9 = (i5 & 0xF) << 4 | i6 >>> 2;
            int i10 = (i6 & 0x3) << 6 | i7;
            result[(m++)] = ((byte)i8);
            if (m < j) result[(m++)] = ((byte)i9);
            if (m < j) result[(m++)] = ((byte)i10);
        }
        return result;
    }
}

My PHP code:

function encrypt($key, $data) {
    $rc4 = new rc4();
    //$size = mcrypt_get_block_size('des', 'ecb');
    //$data = pkcs5_pad($data, $size);
    $mcrypt_module = mcrypt_module_open(MCRYPT_TRIPLEDES, '', 'ecb', '');
    $mcrypt_iv     = mcrypt_create_iv(mcrypt_enc_get_iv_size($mcrypt_module), MCRYPT_RAND);
    $key_size      = mcrypt_enc_get_key_size($mcrypt_module);

    mcrypt_generic_init($mcrypt_module,$key,$mcrypt_iv);
    $encrypted = base64_encode(mcrypt_generic($mcrypt_module, $data));
    mcrypt_module_close($mcrypt_module);

    return $rc4->StringToHexString($encrypted);
}

function decrypt($key, $data) {
    $mcrypt_module = mcrypt_module_open(MCRYPT_TRIPLEDES, '', 'ecb', '');
    $mcrypt_iv     = mcrypt_create_iv(mcrypt_enc_get_iv_size($mcrypt_module), MCRYPT_RAND);
    $decrypted     = mcrypt_decrypt(MCRYPT_TRIPLEDES, $key, base64_encode($data), 'ecb', $mcrypt_iv);
    mcrypt_module_close($mcrypt_module);
    return pkcs5_unpad($decrypted);
}

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

function pkcs5_unpad($text) {
    $pad = ord($text{strlen($text)-1});
    if ($pad > strlen($text)) return false;
    if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
    return substr($text, 0, -1 * $pad);
}

StringToHexString is a method which converts a String into Hexadecimal String.