简体   繁体   中英

AES 128 encryption in Java, PHP - difference in outputs

Followed AES 128 encryption in Java Decryption in PHP in writing the code for aes 128 encryption between Java and PHP (decryption - java, encryption - PHP)

Java Code

import java.security.MessageDigest;
import java.security.spec.AlgorithmParameterSpec;

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

import com.sun.jersey.core.util.Base64;

public class CipherUtils {
    private static Cipher cipher;
    private static SecretKeySpec key;
    private static AlgorithmParameterSpec spec;
    public static final String SEED_16_CHARACTER = "hello";

    public CipherUtils() throws Exception {
        // hash password with SHA-256 and crop the output to 128-bit for key
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        digest.update(SEED_16_CHARACTER.getBytes("UTF-8"));
        byte[] keyBytes = new byte[16];
        System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);

        cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        key = new SecretKeySpec(keyBytes, "AES");
        spec = getIV();
    }

    public AlgorithmParameterSpec getIV() {
        byte[] iv = { 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x46, 0x00, 0x23, 0x00, 0x00, 0x00 };

        IvParameterSpec ivParameterSpec;
        ivParameterSpec = new IvParameterSpec(iv);

        return ivParameterSpec;
    }

    public String encrypt(String plainText) throws Exception {
        cipher.init(Cipher.ENCRYPT_MODE, key, spec);
        byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));
        String encryptedText = new String(Base64.encode(encrypted));

        return encryptedText;
    }

    public String decrypt(String cryptedText) throws Exception {
        cipher.init(Cipher.DECRYPT_MODE, key, spec);
        byte[] bytes = Base64.decode(cryptedText);
        byte[] decrypted = cipher.doFinal(bytes);
        String decryptedText = new String(decrypted, "UTF-8");

        return decryptedText;
    }
 }

PHP Code

class MCrypt {

    private $hex_iv = '00500000000072000000460023000000 '; # converted JAVA byte code in to HEX and placed it here               
    private $key = 'hello'; #Same as in JAVA

    function __construct() {
        $this->key = hash('sha256', $this->key, true);
        //echo $this->key.'<br/>';
    }

    function encrypt($str) {       
        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($td, $this->key, $this->hexToStr($this->hex_iv));
        $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        $pad = $block - (strlen($str) % $block);
        $str .= str_repeat(chr($pad), $pad);
        $encrypted = mcrypt_generic($td, $str);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        return base64_encode($encrypted);
    }

    function decrypt($code) {        
        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($td, $this->key, $this->hexToStr($this->hex_iv));
        $str = mdecrypt_generic($td, base64_decode($code));
        $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);        
        return $this->strippadding($str);               
    }

    private function addpadding($string, $blocksize = 16) {
        $len = strlen($string);
        $pad = $blocksize - ($len % $blocksize);
        $string .= str_repeat(chr($pad), $pad);
        return $string;
    }

    private function strippadding($string) {
        $slast = ord(substr($string, -1));
        $slastc = chr($slast);
        $pcheck = substr($string, -$slast);
        if (preg_match("/$slastc{" . $slast . "}/", $string)) {
            $string = substr($string, 0, strlen($string) - $slast);
            return $string;
        } else {
            return false;
        }
    }

    function hexToStr($hex) {
        $string='';
        for ($i=0; $i < strlen($hex)-1; $i+=2) {
            $string .= chr(hexdec($hex[$i].$hex[$i+1]));
        }
        return $string;
    }
}

No matter what I try doing, the outputs of encrypted/decrypted outputs of Java and PHP don't match.

Important changes that were made in the Java code from the reference stated above are

  1. Used PKCS5 Padding in Java as it didn't allow me to use PKCS7 padding
  2. Changed

      byte[] keyBytes = new byte[32]; 

    to

      byte[] keyBytes = new byte[16]; 

as I didn' want to get into the mess of installing the jce unlimited strength policy files. Any help would be much appreciated.

PKCS#5 padding is the same as PKCS#7 padding, although it is officially only for 8 byte blocks (see this Q/A ).

However, you cannot change key size on just one end and expect it to work. Changing one bit of a key is enough to generate an entirely different ciphertext (and plaintext' after decryption). Changing the size even changes the underlying cipher for AES .

If you don't want to bother with the Jurisdiction files, you are probably best off resizing the PHP key as well; just take the leftmost bytes. You may use 256 bit AES by directly using Bouncy Castle lightweight API in Java as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM