重写PHP Rijndael算法到Java(安卓)重写、算法、Rijndael、PHP

2023-09-04 07:47:54 作者:莫名。

我需要连接在Java中codeA字符串和PHP的地方,结果一定是一样的。

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

在以下条件下给出:

算法:RIJNDAEL算法-128 键:5P443m2Q1R9A7f5r3e1z08642 模式:ECB 初始化向量:N / A(由于我们使用的是欧洲央行,IV的被忽略)

字符串连接code:201412181656005P443m2Q1R9A7f5r3e1z08642

 <?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);     
?>

输出: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);
    }

}

输出:wd0FHYpLbgdpHhcSql7VVCiKWJWN5hvP0W9F4sgKWAWeDcSjvfKWTM5LHBCZJSRw

更新:

我改变填充由 NoPadding PKCS5Padding

这是正确的?我不知道,如果你的PHP code引起。有没有指定任何填充(基于语法我自己的假设)。

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).

信息上的mcrypt

阅读这篇文件关于填充(没有填充)。一定发生了相关的问题。

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

推荐答案

看起来你的PHP版本使用AES-128,它通过定义,使用128位(16字节)的密钥。不过看起来就像你在一个25字节的密钥( 5P443m2Q1R9A7f5r3e1z08642 ),这我不知道什么是PHP做当这种情况发生经过。

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.

您的Java版本的getKeyBytes()方法只返回前16个字节所提供的密钥,因此它只能用于加密。

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

尝试截取你的PHP版本的密钥,以 5P443m2Q1R9A7f5r ,你会得到同样的结果。除的端部可以是不同的。在这一点上,这个问题则是填充。您可以将 pkcs5_pad PHP函数在你的明文,使其符合你的Java版本。

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.

所有这一切说,如果这只是学习之用,它的确定。否则,对于实际使用它,你不使用ECB加密模式。

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.