1

JAVA

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

class AES256JavaPhp{
        public static void main(String[] args) throws Exception {
                Base64 base64 = new Base64();
                Cipher ciper = Cipher.getInstance("AES/CBC/PKCS5Padding");
                SecretKeySpec key = new
                          SecretKeySpec("PasswordPassword".getBytes("UTF-8"),"AES");
                IvParameterSpec iv = new IvParameterSpec
                      ("dynamic@dynamic@".getBytes("UTF-8"),0,ciper.getBlockSize());
            //Encrypt
                ciper.init(Cipher.ENCRYPT_MODE, key,iv);
                byte[] encryptedCiperBytes = base64.encode
                                              ((ciper.doFinal("Hello".getBytes())));
                System.out.println("Ciper : "+new String(encryptedCiperBytes));
            //Decrypt
                ciper.init(Cipher.DECRYPT_MODE, key,iv);    
                byte[] text = ciper.doFinal(base64.decode(encryptedCiperBytes));
                System.out.println("Decrypt text : "+new String(text));
          }
    }

Java output:

Ciper : KpgzpzCRU7mTKZePpPlEvA==
Decrypt text : Hello

PHP

<?php>    
        $cipherText = encrypt("Hello", 'aes-256-cbc');
        exit();

        function encrypt($data, $algo)
        {
            $key = 'PasswordPassword';
            //$iv = random_bytes(openssl_cipher_iv_length($algo));
            $iv = 'dynamic@dynamic@';
            $cipherText = openssl_encrypt(
                    $data,
                    $algo,
                    $key,
                    OPENSSL_RAW_DATA,
                    $iv
                );
        $cipherText = base64_encode($cipherText);
        printData("Ciper Text : $cipherText");

        $cipherText = base64_decode($cipherText);
        $plaintext = openssl_decrypt(
                    $cipherText,
                    $algo,
                    $key,
                    OPENSSL_RAW_DATA,
                    $iv
                );
        printData("Plain Text after decryption : $plaintext");
        }

        function printData($obj)
        {
            print_r($obj);
        }
?>

PHP output:

Ciper Text : ef/ENVlBn9QBFlkvoN7P2Q==
Plain Text after decryption : Hello

The resulting ciphers are different, even though they are using the same key and IV. How is this possible?

Keith
  • 3,079
  • 2
  • 17
  • 26
  • What is your question? – Keith Feb 22 '17 at 16:15
  • If any of the given answers solved your problem, you may [accept](http://meta.stackexchange.com/q/5234/266187) one of them. If it didn't, then please expand on what is wrong. – Artjom B. Apr 08 '17 at 11:08

2 Answers2

2

Clearly you must use the same AES key and IV for a secure session. And they must be properly and securely communicated across clients. It does not matter at all what language the clients are written in. Your problem is not understanding the protocol for key agreement and session establishment.

The initialization vector is not a protected value; i.e., you are not encrypting it when communicating between clients. It must be packaged in cleartext with encrypted AES key (which you derive from some key agreement protocol).

CMS uses a KeyTransRecipientInfo to deliver this information. TLS also defines IV establishment followings its handshake. I would highly suggest following the CMS implementation instead of something contrived and almost guaranteed to contain security bugs.


Update

It is now clear that you are confused why the resulting ciphertexts are not deterministic. That is because the Java implementation is defaulting to a 128-bit encryption and has been supplied a 128-bit key, but the PHP code is requesting 256-bit strength encryption and only being supplied the same 128-bit key. Therefore, PHP must be padding the key.


Update 2

Based on your below comments, here is an example of using Java to generate a 256-bit key:

KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(256); // The AES key size in number of bits
SecretKey secKey = generator.generateKey();
Community
  • 1
  • 1
Keith
  • 3,079
  • 2
  • 17
  • 26
  • As Java implementation is defaulting to a 128-bit encryption, so can we override it to 256-bit ? – Viplove Chaudhary Feb 23 '17 at 10:49
  • as I'm changing bits in php to 128 it's working... but I don't won't to make changes at php end... – Viplove Chaudhary Feb 23 '17 at 10:54
  • 1
    Yes, you can create a 256-bit key -- I've just updated my answer with a snippet to do this. Also, you **must** add the [Unlimited Strength Jurisdition Security Policy](https://deveshsharma.info/2012/10/09/fixing-java-security-invalidkeyexception-illegal-key-size-exception/) or you'll get an `InvalidKeyException`. – Keith Feb 23 '17 at 13:12
0

Your key is only 128 bit (16 bytes) long, but you're requesting AES-256 in PHP. This will lead to a padded AES key of 256 bit (32 bytes). You have to request AES-128 for this to work. That is how the OpenSSL extension works in PHP.

A key should ideally look like random noise in order to prevent brute force attacks. Your current key is anything but that. It is very predictable. You should really generate some random key and add it to your code in encoded form like Base64. Then you can decode it before use.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222