Rewrite PHP Rijndael algorithm to Java (Android)

2020-02-08 23:44发布

I need to encode a string in Java and php where the result must be the same.

The following conditions are given:

  1. algorithm: RIJNDAEL-128
  2. key: 5P443m2Q1R9A7f5r3e1z08642
  3. mode: ECB
  4. initialization vector: N/A (Since we're using ECB, IV's are ignored)

String to encode: 201412181656005P443m2Q1R9A7f5r3e1z08642

PHP

 <?php
        class Cipher
        {
            private $securekey, $iv;

            function __construct($textkey)
            {
                $this->securekey = $textkey;
                $this->iv = mcrypt_create_iv(32);
            }

            function encryptR($input)
            {
                $enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->securekey, $input, MCRYPT_MODE_ECB, $this->iv);
                return base64_encode($enc);
            }

            function decryptR($input)
            {
                return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->securekey, base64_decode($input), MCRYPT_MODE_ECB, $this->iv));
            }
        }

        $raw_text = '201412181656005P443m2Q1R9A7f5r3e1z08642';
        $secretKey = '5P443m2Q1R9A7f5r3e1z08642';

        $cipher = new Cipher($secretKey);
        $encrypted = $cipher->encryptR($raw_text);     
?>

Output: MbDHhIanWgySlMTOX+ItgVKudVLXbtj7ig2GMQacVM9JhyAPvVQxLJnHpEj/vhqW

JAVA

encrypted = encrypt("201412181656005P443m2Q1R9A7f5r3e1z08642","5P443m2Q1R9A7f5r3e1z08642");

public class Crypt {

    private final String characterEncoding = "UTF-8";
    private final String cipherTransformation = "AES/ECB/PKCS5Padding";
    private final String aesEncryptionAlgorithm = "AES";

    public  byte[] decrypt(byte[] cipherText, byte[] key) throws Exception
    {
        Cipher cipher = Cipher.getInstance(cipherTransformation);
        SecretKeySpec secretKeySpecy = new SecretKeySpec(key, aesEncryptionAlgorithm);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpecy);
        cipherText = cipher.doFinal(cipherText);
        return cipherText;
    }

    public byte[] encrypt(byte[] plainText, byte[] key) throws Exception
    {
        Cipher cipher = Cipher.getInstance(cipherTransformation);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, aesEncryptionAlgorithm);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        plainText = cipher.doFinal(plainText);
        return plainText;
    }

    private byte[] getKeyBytes(String key) throws UnsupportedEncodingException{
        byte[] keyBytes= new byte[16];
        byte[] parameterKeyBytes= key.getBytes(characterEncoding);
        System.arraycopy(parameterKeyBytes, 0, keyBytes, 0, Math.min(parameterKeyBytes.length, keyBytes.length));
        return keyBytes;
    }

    @SuppressLint("NewApi")
    public String encrypt(String plainText, String key) throws Exception {
        byte[] plainTextbytes = plainText.getBytes(characterEncoding);
        byte[] keyBytes = getKeyBytes(key);
        // Log.i("iv", ""+keyBytesIV);
        return Base64.encodeToString(encrypt(plainTextbytes,keyBytes), Base64.DEFAULT);
    }

    @SuppressLint("NewApi")
    public String decrypt(String encryptedText, String key) throws Exception {
        byte[] cipheredBytes = Base64.decode(encryptedText, Base64.DEFAULT);
        byte[] keyBytes = getKeyBytes(key);

        return new String(decrypt(cipheredBytes, keyBytes), characterEncoding);
    }

}

Output: wd0FHYpLbgdpHhcSql7VVCiKWJWN5hvP0W9F4sgKWAWeDcSjvfKWTM5LHBCZJSRw

Updated:

I changed the padding from NoPadding to PKCS5Padding

Is this correct? I'm not sure, cause if you look at the PHP code. There wasn't any padding specified(my own assumption based on syntax).

Info on Mcrypt

Additional Insight:

Read this document regarding padding(No Padding). Must've been related to the issue.

2条回答
闹够了就滚
2楼-- · 2020-02-09 00:26

I changed byte[] keyBytes= new byte[16]; to byte[] keyBytes= new byte[32]; in getKeyBytes method then it worked fine.

查看更多
我只想做你的唯一
3楼-- · 2020-02-09 00:40

Looks like your PHP version uses AES-128, which by definition, uses 128-bit (16-byte) keys. However looks like you passed in a 25-byte key (5P443m2Q1R9A7f5r3e1z08642), which I'm not sure what PHP does when that happens.

Your Java version's getKeyBytes() method only returns the first 16 bytes of the supplied key, so it encrypts with only that.

Try truncating the key in your PHP version to 5P443m2Q1R9A7f5r and you'd get the same result. Except the end part which may be different. At that point, the issue then would be the padding. You can apply the pkcs5_pad PHP function on your plaintext so it matches your Java version.

All that said, if this was just for learning purposes, it's ok. Otherwise, for actual use it's important that you do not use ECB cipher mode.

查看更多
登录 后发表回答