Encryption Between PHP & Java

后端 未结 4 1663
借酒劲吻你
借酒劲吻你 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: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;
        }
    
    }
    

提交回复
热议问题