无法在Java和PHP之间交换使用AES-256加密的数据

LZZ*_*LZZ 12 php java encryption aes

我的问题是:我在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 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);
}
Run Code Online (Sandbox Code Playgroud)

运行:

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));
}
Run Code Online (Sandbox Code Playgroud)

输出:

example
Run Code Online (Sandbox Code Playgroud)

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
    );
}
Run Code Online (Sandbox Code Playgroud)

运行:

$crypt = getDecrypt(getEncrypt($str, $key), $key);
echo "<p>Crypt: $crypt</p>";
Run Code Online (Sandbox Code Playgroud)

输出:

Crypt: example?????????????????????????
Run Code Online (Sandbox Code Playgroud)

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

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

Jam*_*olk 14

BUG#1

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

BUG#2

这两行在Java中永远不正确,表明对加密转换产生的任意二进制数据的性质有一个基本的误解:

output = cipher.doFinal(Base64.decodeBase64(input));
return new String(output);
Run Code Online (Sandbox Code Playgroud)

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

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

编辑:

开个玩笑吧#2.真的,我错了,我没注意到它是解密方向.当然,如果你知道解密byte[]是一个有效的字符串,那么完成代码所做的就完全正确了.


Xdg*_*Xdg 9

我知道这是一个老话题,但我会添加我的工作解决方案.

你必须重写脚本的PHP端:

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

function getDecrypt($sStr, $sKey) {
  return mcrypt_decrypt(
    MCRYPT_RIJNDAEL_128, 
    base64_decode($sKey), 
    base64_decode($sStr), 
    MCRYPT_MODE_ECB
  );
}
Run Code Online (Sandbox Code Playgroud)

你应该base64_decode($ sKey),因为你的密钥是base64编码的.

$key = "Zvzpv8/PXbezPCZpxzQKzL/FeoPw68jIb+NONX/LIi8=";
Run Code Online (Sandbox Code Playgroud)

然后,您需要创建此功能(信用从http://www.php.net/manual/en/function.mcrypt-decrypt.php转到beltrachi ):

function pkcs5_pad ($text, $blocksize) { 
  $pad = $blocksize - (strlen($text) % $blocksize); 
  return $text . str_repeat(chr($pad), $pad); 
}
Run Code Online (Sandbox Code Playgroud)

使用此代码执行编码/解码:

$decrypt = getDecrypt("6XremNEs1jv/Nnf/fRlQob6oG1jkge+5Ut3PL489oIo=", $key);
echo $decrypt;
echo "\n\n";
echo getEncrypt(pkcs5_pad("My very secret text:)", 16), $key);
Run Code Online (Sandbox Code Playgroud)

我希望这对某人有用!:)