不同的AES加密导致PHP和JAVA

时间:2016-02-22 20:26:43

标签: java php android-studio encryption aes

我已经实现了两个加密/解密数据的功能 在服务器(PHP)和客户端(Android应用程序)之间传输。 虽然两个键都相同,但我得到了完全不同的结果 从功能。有什么问题?

JAVA(Android Studio功能):

public static String encryptString(String string, String key){
    try {
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(string.getBytes());
        return Base64.encodeToString(encrypted, Base64.URL_SAFE);
    } catch(Exception e){
        return e.getMessage();
    }
}

private static String decryptString(String string, String key){
    try {
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] decrypted = cipher.doFinal(string.getBytes());
        return Base64.decode(decrypted, Base64.DEFAULT ).toString();

    } catch(Exception e){
        return null;
    }
}

PHP函数:

function fnEncrypt($sValue, $sSecretKey){
return rtrim(
    base64_encode(
        mcrypt_encrypt(
            MCRYPT_RIJNDAEL_128,
            $sSecretKey, $sValue, 
            MCRYPT_MODE_ECB, 
            mcrypt_create_iv(
                mcrypt_get_iv_size(
                    MCRYPT_RIJNDAEL_256, 
                    MCRYPT_MODE_ECB
            ), 
            MCRYPT_RAND)
        )
    ), "\0"
);
}

function fnDecrypt($sValue, $sSecretKey){
return rtrim(
    mcrypt_decrypt(
        MCRYPT_RIJNDAEL_128, 
        $sSecretKey, 
        base64_decode($sValue), 
        MCRYPT_MODE_ECB,
        mcrypt_create_iv(
            mcrypt_get_iv_size(
                MCRYPT_RIJNDAEL_256,
                MCRYPT_MODE_ECB
            ), 
            MCRYPT_RAND
        )
    ), "\0"
);
}

1 个答案:

答案 0 :(得分:2)

在初始化字符串中未明确指定默认选项(填充,模式)时,很难说明这些选项是什么:Cipher.getInstance("AES")

AES的块大小为128.bits,因此您需要将其调整为mcrypt:MCRYPT_RIJNDAEL_128。 MCRYPT_RIJNDAEL_256不是AES。

一个可靠的假设是Java正在使用PKCS#5(实际上是PKCS#7 for AES)填充。但是mcrypt不支持PKCS#5(或PKCS#7)填充,只有空填充和空填充不能用于二进制数据。

最好的解决方案是明确指定Java填充和模式,php代码指定ECB(这是不安全的)。 Java字符串可能应该是:“AES / ECB / PKCS5Padding(128)”see Cipher docs。然后为mcrypt添加PKCS#7填充到要加密的数据并在解密后删除。见PKCS padding

为什么不使用:ECB mode,向下滚动到企鹅。