doudong3570 2014-07-30 12:26
浏览 78
已采纳

Java端的AES加密 - 在PHP端解密并选择单个密钥

I am using AES and I want to settle for a key which I can use on the Java side to encrypt a string, I hardcode the same key on php side and decrypt the string if the strings match I am authenticated to step inside.

Following is my code in Java:

public class AESencrp {

     private static final String ALGO = "AES";
    private static final byte[] keyValue = 
        new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't',
'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };

public static String encrypt(String Data) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encVal = c.doFinal(Data.getBytes());
        String encryptedValue = new BASE64Encoder().encode(encVal);
        return encryptedValue;
    }

    public static String decrypt(String encryptedData) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }
    private static Key generateKey() throws Exception {
        Key key = new SecretKeySpec(keyValue, ALGO);
        return key;
}

}

Here is the function I use in PHP:

function fnDecrypt()
{
 // echo $_POST['key'];
 $sValue = $_POST['key']; 
 $sSecretKey = "TheBestSecretKey";
    return rtrim(
        mcrypt_decrypt(
            MCRYPT_RIJNDAEL_256, 
            $sSecretKey, 
            base64_decode($sValue), 
            MCRYPT_MODE_CBC,
            mcrypt_create_iv(
                mcrypt_get_iv_size(
                    MCRYPT_RIJNDAEL_256,
                    MCRYPT_MODE_CBC
                ), 
                MCRYPT_RAND
            )
        ), "\0"
    );
}

However it seems, that I always get different decrypted text on php side, I feel the issue is with the key, while as I am hard coding it, this behavior should not occur, any hints?

  • 写回答

2条回答 默认 最新

  • duandao7704 2014-07-30 14:00
    关注

    There seem to be a few things you are doing wrong, I'll go over these in order:

    Always specify "Algorithm/Mode/Padding" when creating an instance of Cipher in Java. Otherwise you never know which mode and padding will be used, which is especially problematic if you want to pass encrypted data between different platforms and programming languages, since they will probably have different defaults. (for example Java's default padding is PKCS1Padding where as PHP's mcrypt_decrypt() requires ZeroBytePadding)
    So initialize ALGO with:

    /* ZeroBytePadding should better not be used in practice */
    private static final String ALGO = "AES/CBC/ZeroBytePadding";
    

    As Roland Jansen has already mentioned, is the Java AES the 128-bit version. So use in PHP:

    MCRYPT_RIJNDAEL_128
    

    Third, you must always specify a different random IV for every encryption (must not be secret). You then must use the same IV for decryption. So you will also have to generate an IV in java that you then pass to PHP and use for decryption there.

    byte[] iv = new byte[16]; // must be 16 bytes for AES-128
    new SecureRandom().nextBytes(iv); // generate random bytes
    IvParameterSpec ivSpec = new IvParameterSpec(iv);
    
    /* create instance of Cipher and keys */
    
    cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
    

    As of now you also generate a random IV in PHP, which will obviously not lead to the desired plaintext. So do the following in php for decryption:

     $key = "{insert Java encryption key here}";
     $iv; = "{insert Java encryption IV here}";
    
     mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext, MCRYPT_MODE_CBC, $iv);
    

    If it still does not work after these fixes, the problem is probably the encoding of the ciphertext- or the key/IV-Strings. Try to make sure that you pass exactly the same data to PHP which you receive from cipher.doFinal in Java then.

    I hope, I could help you.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同
  • ¥50 如何openEuler 22.03上安装配置drbd
  • ¥20 ING91680C BLE5.3 芯片怎么实现串口收发数据
  • ¥15 无线连接树莓派,无法执行update,如何解决?(相关搜索:软件下载)
  • ¥15 Windows11, backspace, enter, space键失灵