Encryption Between PHP & Java

后端 未结 4 1657
借酒劲吻你
借酒劲吻你 2020-12-09 14:10

I was looking to encrypt data between a PHP server and a Java Client. Individually the code works fine and I would like to stick with OpenSSL on the PHP server.

Do

相关标签:
4条回答
  • 2020-12-09 14:31

    I can't figure out why your method fails. By the way, Here's how i did it,

    Java

    import com.sun.org.apache.xml.internal.security.utils.Base64;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    import java.security.Key;
    
    public class MyClass {
    
        public static void main(String[] args) {
            String data = "Arnab C";
            final String enc = DarKnight.getEncrypted(data);
            System.out.println("Encrypted : " + enc);
            System.out.println("Decrypted : " + DarKnight.getDecrypted(enc));
        }
    
        static class DarKnight {
    
            private static final String ALGORITHM = "AES";
    
            private static final byte[] SALT = "tHeApAcHe6410111".getBytes();// THE KEY MUST BE SAME
            private static final String X = DarKnight.class.getSimpleName();
    
            static String getEncrypted(String plainText) {
    
                if (plainText == null) {
                    return null;
                }
    
                Key salt = getSalt();
    
                try {
                    Cipher cipher = Cipher.getInstance(ALGORITHM);
                    cipher.init(Cipher.ENCRYPT_MODE, salt);
                    byte[] encodedValue = cipher.doFinal(plainText.getBytes());
                    return Base64.encode(encodedValue);
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
                throw new IllegalArgumentException("Failed to encrypt data");
            }
    
            public static String getDecrypted(String encodedText) {
    
                if (encodedText == null) {
                    return null;
                }
    
                Key salt = getSalt();
                try {
                    Cipher cipher = Cipher.getInstance(ALGORITHM);
                    cipher.init(Cipher.DECRYPT_MODE, salt);
                    byte[] decodedValue = Base64.decode(encodedText);
                    byte[] decValue = cipher.doFinal(decodedValue);
                    return new String(decValue);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
    
            static Key getSalt() {
                return new SecretKeySpec(SALT, ALGORITHM);
            }
    
        }
    }
    

    PHP

    <?php
    
    $key = "tHeApAcHe6410111";
    
    function encrypt($text,$key){
         $block = mcrypt_get_block_size('rijndael_128', 'ecb');
         $pad = $block - (strlen($text) % $block);
         $text .= str_repeat(chr($pad), $pad);
         return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_ECB));
    }
    
    function decrypt($str, $key){ 
         $str = base64_decode($str);
         $str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB);
         $block = mcrypt_get_block_size('rijndael_128', 'ecb');
         $pad = ord($str[($len = strlen($str)) - 1]);
         $len = strlen($str);
         $pad = ord($str[$len-1]);
         return substr($str, 0, strlen($str) - $pad);
    }
    
    $enc =  encrypt("Arnab C",$GLOBALS['key']);
    echo "Encrypted : ".$enc."</br>";
    $dec = decrypt($enc,$GLOBALS['key']);
    echo "Decrypted : ".$dec;
    

    Java Output

    Encrypted : PJG1Uu6SjJuuVGf7ApuHAw==

    Decrypted : Arnab C

    PHP Output

    Encrypted : PJG1Uu6SjJuuVGf7ApuHAw==

    Decrypted : Arnab C

    0 讨论(0)
  • 2020-12-09 14:36

    A working version can be found - https://github.com/chaudhuri-ab/CrossPlatformCiphers

    Some things to keep in mind is the that if you do not specify OPENSSL_RAW_DATA in PHP the data will be encrypted as base64. That was throwing me off.

    PHP:

    class PHP_AES_Cipher {
    
        private static $OPENSSL_CIPHER_NAME = "aes-128-cbc"; //Name of OpenSSL Cipher 
        private static $CIPHER_KEY_LEN = 16; //128 bits
    
        /**
         * Encrypt data using AES Cipher (CBC) with 128 bit key
         * 
         * @param type $key - key to use should be 16 bytes long (128 bits)
         * @param type $iv - initialization vector
         * @param type $data - data to encrypt
         * @return encrypted data in base64 encoding with iv attached at end after a :
         */
    
        static function encrypt($key, $iv, $data) {
            if (strlen($key) < PHP_AES_Cipher::$CIPHER_KEY_LEN) {
                $key = str_pad("$key", PHP_AES_Cipher::$CIPHER_KEY_LEN, "0"); //0 pad to len 16
            } else if (strlen($key) > PHP_AES_Cipher::$CIPHER_KEY_LEN) {
                $key = substr($str, 0, PHP_AES_Cipher::$CIPHER_KEY_LEN); //truncate to 16 bytes
            }
    
            $encodedEncryptedData = base64_encode(openssl_encrypt($data, PHP_AES_Cipher::$OPENSSL_CIPHER_NAME, $key, OPENSSL_RAW_DATA, $iv));
            $encodedIV = base64_encode($iv);
            $encryptedPayload = $encodedEncryptedData.":".$encodedIV;
    
            return $encryptedPayload;
    
        }
    
        /**
         * Decrypt data using AES Cipher (CBC) with 128 bit key
         * 
         * @param type $key - key to use should be 16 bytes long (128 bits)
         * @param type $data - data to be decrypted in base64 encoding with iv attached at the end after a :
         * @return decrypted data
         */
        static function decrypt($key, $data) {
            if (strlen($key) < PHP_AES_Cipher::$CIPHER_KEY_LEN) {
                $key = str_pad("$key", PHP_AES_Cipher::$CIPHER_KEY_LEN, "0"); //0 pad to len 16
            } else if (strlen($key) > PHP_AES_Cipher::$CIPHER_KEY_LEN) {
                $key = substr($str, 0, PHP_AES_Cipher::$CIPHER_KEY_LEN); //truncate to 16 bytes
            }
    
            $parts = explode(':', $data); //Separate Encrypted data from iv.
            $decryptedData = openssl_decrypt(base64_decode($parts[0]), PHP_AES_Cipher::$OPENSSL_CIPHER_NAME, $key, OPENSSL_RAW_DATA, base64_decode($parts[1]));
    
            return $decryptedData;
        }
    
    }
    

    Java:

    package ciphers;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    
    import java.util.Base64;
    
    public class Java_AES_Cipher {
    
        private static String CIPHER_NAME = "AES/CBC/PKCS5PADDING";
        private static int CIPHER_KEY_LEN = 16; //128 bits
    
        /**
         * Encrypt data using AES Cipher (CBC) with 128 bit key
         * 
         * 
         * @param key  - key to use should be 16 bytes long (128 bits)
         * @param iv - initialization vector
         * @param data - data to encrypt
         * @return encryptedData data in base64 encoding with iv attached at end after a :
         */
        public static String encrypt(String key, String iv, String data) {
            try {
                if (key.length() < Java_AES_Cipher.CIPHER_KEY_LEN) {
                    int numPad = Java_AES_Cipher.CIPHER_KEY_LEN - key.length();
    
                    for(int i = 0; i < numPad; i++){
                        key += "0"; //0 pad to len 16 bytes
                    }
    
                } else if (key.length() > Java_AES_Cipher.CIPHER_KEY_LEN) {
                    key = key.substring(0, CIPHER_KEY_LEN); //truncate to 16 bytes
                }
    
    
                IvParameterSpec initVector = new IvParameterSpec(iv.getBytes("UTF-8"));
                SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
    
                Cipher cipher = Cipher.getInstance(Java_AES_Cipher.CIPHER_NAME);
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec, initVector);
    
                byte[] encryptedData = cipher.doFinal((data.getBytes()));
    
                String base64_EncryptedData = Base64.getEncoder().encodeToString(encryptedData);
                String base64_IV = Base64.getEncoder().encodeToString(iv.getBytes("UTF-8"));
    
                return base64_EncryptedData + ":" + base64_IV;
    
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    
            return null;
        }
    
        /**
         * Decrypt data using AES Cipher (CBC) with 128 bit key
         * 
         * @param key - key to use should be 16 bytes long (128 bits)
         * @param data - encrypted data with iv at the end separate by :
         * @return decrypted data string
         */
    
        public static String decrypt(String key, String data) {
            try {
    
                String[] parts = data.split(":");
    
                IvParameterSpec iv = new IvParameterSpec(Base64.getDecoder().decode(parts[1]));
                SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
    
                Cipher cipher = Cipher.getInstance(Java_AES_Cipher.CIPHER_NAME);
                cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
    
                byte[] decodedEncryptedData = Base64.getDecoder().decode(parts[0]);
    
                byte[] original = cipher.doFinal(decodedEncryptedData);
    
                return new String(original);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    
            return null;
        }
    
    }
    
    0 讨论(0)
  • 2020-12-09 14:43

    I used the solution from theapache64, but in PHP 7.2 it stopped working since Mcrypt has been deprecated and later removed. So I changed the code and it works:

    function encrypt($data, $key) {
        return base64_encode(openssl_encrypt($data, "aes-128-ecb", $key, OPENSSL_RAW_DATA));
    }
    
    function decrypt($data, $key) {
        return openssl_decrypt(base64_decode($data), "aes-128-ecb", $key, OPENSSL_RAW_DATA);
    }
    
    0 讨论(0)
  • 2020-12-09 14:46

    In Java 8, you cannot use

    import com.sun.org.apache.xml.internal.security.utils.Base64;
    

    Instead, you can use

    import android.util.Base64;
    

    Then you also need to change the Base64.decode and Base64.encode lines.

    The complete code will be as follows (the comment from petrnohejl, about MCRYPT that has been deprecated in PHP7, taken into account):

    Java:

    import android.util.Base64;
    import java.security.Key;
    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    
    public class MyClass {
        public static void main(String[] args) {
            String data = "Arnab C";
            final String enc = DarKnight.getEncrypted(data);
            System.out.println("Encrypted : " + enc);
            System.out.println("Decrypted : " + DarKnight.getDecrypted(enc));
        }
    
        static class DarKnight {
            private static final String ALGORITHM = "AES";
            private static final byte[] SALT = "tHeApAcHe6410111".getBytes();// THE KEY MUST BE SAME
            private static final String X = DarKnight.class.getSimpleName();
            static String getEncrypted(String plainText) {
                if (plainText == null) {
                    return null;
                }
    
                Key salt = getSalt();
    
                try {
                    Cipher cipher = Cipher.getInstance(ALGORITHM);
                    cipher.init(Cipher.ENCRYPT_MODE, salt);
                    byte[] encodedValue = cipher.doFinal(plainText.getBytes());
                    return Base64.encodeToString(encodedValue,Base64.DEFAULT);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                throw new IllegalArgumentException("Failed to encrypt data");
            }
    
            public static String getDecrypted(String encodedText) {
                if (encodedText == null) {
                    return null;
                }
    
                Key salt = getSalt();
                try {
                    Cipher cipher = Cipher.getInstance(ALGORITHM);
                    cipher.init(Cipher.DECRYPT_MODE, salt);
                    byte[] decodedValue = Base64.decode(encodedText, Base64.DEFAULT);
                    byte[] decValue = cipher.doFinal(decodedValue);
                    return new String(decValue);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
    
            static Key getSalt() {
                return new SecretKeySpec(SALT, ALGORITHM);
            }
        }
    }
    

    PHP:

    <?php
    
    $key = "tHeApAcHe6410111";
    
    function encrypt($data, $key) {
        return base64_encode(openssl_encrypt($data, "aes-128-ecb", $key, OPENSSL_RAW_DATA));
    }
    
    function decrypt($data, $key) {
        return openssl_decrypt(base64_decode($data), "aes-128-ecb", $key, OPENSSL_RAW_DATA);
    }
    
    $enc =  encrypt("Arnab C",$GLOBALS['key']);
    echo "Encrypted : ".$enc."</br>";
    $dec = decrypt($enc,$GLOBALS['key']);
    echo "Decrypted : ".$dec;
    
    ?>
    

    Don't give me credits, I am just the messenger, who combined a few posts.

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