无法在 Java 和 PHP 之间交换使用 AES-256 加密的数据 [英] Unable to exchange data encrypted with AES-256 between Java and PHP

查看:23
本文介绍了无法在 Java 和 PHP 之间交换使用 AES-256 加密的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是:我用 Java 加密的东西我可以用 Java 完美解密,但 PHP mcrypt 无法解密.我用 mcrypt 加密的我可以用 mcrypt 解密,但不能用 Java.

My problem is: what I encrypt in Java I can decrypt perfectly in Java, but PHP mcrypt can't decrypt. What I encrypt with mcrypt I can decrypt with mcrypt, but can't in Java.

我想从 Java 应用程序向 PHP 页面发送和接收加密数据,因此我需要它兼容.

I want to send and receive encrypted data from a Java application to a PHP page, so I need it to be compatible.

这是我所拥有的...

Java...

public static String crypt(String input, String key){
    byte[] crypted = null;
    try{
        SecretKeySpec skey = new SecretKeySpec(Base64.decodeBase64(key), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skey);
        crypted = cipher.doFinal(input.getBytes());
    }catch(Exception e){
    }
    return Base64.encodeBase64String(crypted);
}

public static String decrypt(String input, String key){
    byte[] output = null;
    try{
        SecretKeySpec skey = new SecretKeySpec(Base64.decodeBase64(key), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, skey);
        output = cipher.doFinal(Base64.decodeBase64(input));
    }catch(Exception e){
    }
    return new String(output);
}

运行:

public static void main(String[] args) {
    String key = "Zvzpv8/PXbezPCZpxzQKzL/FeoPw68jIb+NONX/LIi8=";
    String data = "example";
    System.out.println(Cpt.decrypt(Cpt.crypt(data, key), key));
}

输出:

example

PHP...

function getEncrypt($sStr, $sKey) {
    return base64_encode(
        mcrypt_encrypt(
            MCRYPT_RIJNDAEL_256, 
            $sKey,
            $sStr,
            MCRYPT_MODE_ECB
        )
    );
}

function getDecrypt($sStr, $sKey) {
    return mcrypt_decrypt(
        MCRYPT_RIJNDAEL_256, 
        $sKey, 
        base64_decode($sStr), 
        MCRYPT_MODE_ECB
    );
}

运行:

$crypt = getDecrypt(getEncrypt($str, $key), $key);
echo "<p>Crypt: $crypt</p>";

输出:

Crypt: example�������������������������

使用 PHP 使用密钥Zvzpv8/PXbezPCZpxzQKzL/FeoPw68jIb+NONX/LIi8="加密示例",我得到YTYhgp4zC+w5IsViTR5PUkHMX4i7JzvA6NJT1FqhoGY=".使用 Java 用相同的密钥加密相同的东西,我得到+tdAZqTE7WAVPXhB3Tp5+g==".

Using PHP to crypt "example" with key "Zvzpv8/PXbezPCZpxzQKzL/FeoPw68jIb+NONX/LIi8=" I get "YTYhgp4zC+w5IsViTR5PUkHMX4i7JzvA6NJT1FqhoGY=". Using Java to crypt the same thing with the same key I get "+tdAZqTE7WAVPXhB3Tp5+g==".

我正在以正确的顺序对 base64 进行编码和解码,并测试了 Java 和 PHP 之间的 base64 编码和解码兼容性,并且它正在工作.

I'm encoding and decoding to base64 in the right order and I tested base64 encode and decode compatibility between Java and PHP and it's working.

推荐答案

BUG#1

MCRYPT_RIJNDAEL_256 不是 AES.该常量中的 256 指的是块大小,而不是密钥大小.使用 MCRYPT_RIJNDAEL_128 获得与 AES 相同的算法.密钥大小仅由您提供的密钥参数中的字节数设置.因此,提供 32 个字节,您将获得带有 256 位密钥的 AES.

MCRYPT_RIJNDAEL_256 is not AES. The 256 in that constant refers to the blocksize, not the keysize. Use MCRYPT_RIJNDAEL_128 to get the same algorithm as AES. The keysize is set just by the number of bytes in the key argument you supply. So supply 32 bytes and you get AES with a 256-bit key.

BUG#2

这两行在 Java 中永远不会正确,表明对密码转换产生的任意二进制数据的性质存在根本性的误解:

These two lines are never correct in Java and indicate a fundamental misunderstanding of the nature of the arbitrary binary data produced by cryptographic transforms:

output = cipher.doFinal(Base64.decodeBase64(input));
return new String(output);

直接传输和存储 byte[] 没有任何问题,但是如果您必须只使用可打印的字符串,那么您应该使用 base64 编码/解码来这样做.由于您已经广泛使用 base64,这似乎是要走的路.我猜正确的两行应该是:

There is nothing wrong with transmitting and storing byte[] directly, but if you must use only printable strings then you should base64 encode/decode to do so. As you are already using base64 extensively that would seem like the way to go. I would guess that the correct two lines would be:

output = cipher.doFinal(Base64.decodeBase64(input));
return new String(Base64.encodeBase64(output), "UTF-8");

只是在开玩笑说错误 #2.真的,我错了,我没注意到是解密方向.当然,如果您知道解密后的 byte[] 是一个有效字符串,那么执行您的代码所做的事情是完全正确的.

Just kidding about bug #2. Really, I was wrong, I didn't notice it was the decrypt direction. Of course, if you know the decrypted byte[] is a valid string then it is perfectly correct to do what your code does.

这篇关于无法在 Java 和 PHP 之间交换使用 AES-256 加密的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆