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

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

问题描述

我的问题是:我用Java加密我可以在Java中完美解密,但PHP mcrypt 无法解密。我使用 mcrypt 进行加密我可以使用 mcrypt 进行解密,但不能在Java中。



我希望从Java应用程序发送和接收加密数据到PHP页面,所以我需要它兼容。



这里是我有...



JAVA ...

  public static String crypt(String input,String key){
byte [] crypted = null;
try {
SecretKeySpec skey = new SecretKeySpec(Base64.decodeBase64(key),AES);
密码密码= 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.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));
}

输出:

 示例

PHP ...

 函数getEncrypt($ sStr,$ sKey){
返回base64_encode(
mcrypt_encrypt(
MCRYPT_RIJNDAEL_256,
$ sKey,
$ sStr,
MCRYPT_MODE_ECB

);
}

函数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>;

输出:

 code> Crypt:example                         

使用PHP用Zvzpv8 / PXbezPCZpxzQKzL / FeoPw68jIb + NONX / LIi8 =键入示例,我得到YTYhgp4zC + w5IsViTR5PUkHMX4i7JzvA6NJT1FqhoGY =。
使用Java对相同的键隐藏相同的东西,我得到+ tdAZqTE7WAVPXhB3Tp5 + g ==。



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

解决方案

BUG#1



MCRYPT_RIJNDAEL_256 不是AES。该常量中的256指的是块大小,而不是keysize。使用 MCRYPT_RIJNDAEL_128 获得与AES相同的算法。 keysize仅由您提供的键参数中的字节数设置。所以提供32个字节,你将获得一个256位密钥的AES。



BUG#2



这两行在Java中是不正确的,并且表示对加密转换产生的任意二进制数据的性质的一个根本的误解:

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

发送和存储没有错误 byte [] 直接,但如果您只能使用可打印的字符串,那么您应该base64编码/解码这样做。由于您已经广泛使用base64,看起来像是要走的路。我会猜测正确的两行是:

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

编辑:



#2。真的,我错了,我没有注意到这是解密的方向。当然,如果你知道解密的 byte [] 是一个有效的字符串,那么执行代码是完全正确的。


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.

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

Here's what I have...

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

Running:

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

Output:

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

Running:

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

Output:

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

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==".

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

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

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

EDIT:

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天全站免登陆