为什么AES java解密返回额外的字符? [英] why AES java decryption return extra characters?

查看:152
本文介绍了为什么AES java解密返回额外的字符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请原谅我的英文不好
我使用mcrypt我从这里得到它 MCrypt for php和java 。在我的Android应用程序中,我需要php和java安全地通信,所以我得到上面提到的AES。
问题是当php发送加密数据时,java可以解密,但是会包含一些额外的字符。



JAVA代码

  import java.security.NoSuchAlgorithmException; 

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class MCrypt {

private String iv =fedcba9876543210; // Dummy iv(CHANGE IT!)
private IvParameterSpec ivspec;
private SecretKeySpec keyspec;
私密密码;

private String SecretKey =0123456789abcdef; // Dummy secretKey(CHANGE IT!)

public MCrypt()
{
ivspec = new IvParameterSpec (iv.getBytes());

keyspec = new SecretKeySpec(SecretKey.getBytes(),AES);

try {
cipher = Cipher.getInstance(AES / CBC / NoPadding);
} catch(NoSuchAlgorithmException e){
// TODO自动生成的catch块
e.printStackTrace();
} catch(NoSuchPaddingException e){
// TODO自动生成的catch块
e.printStackTrace();
}
}

public byte [] encrypt(String text)throws异常
{
if(text == null || text.length )== 0)
抛出新异常(空字符串);

byte [] encrypted = null;

try {
cipher.init(Cipher.ENCRYPT_MODE,keyspec,ivspec);

encrypted = cipher.doFinal(padString(text).getBytes());
} catch(Exception e)
{
throw new Exception([encrypt]+ e.getMessage());
}

返回加密;
}

public byte [] decrypt(String code)throws异常
{
if(code == null || code.length()== 0)
抛出新的异常(空字符串);

byte [] decryptpted = null;

try {
cipher.init(Cipher.DECRYPT_MODE,keyspec,ivspec);

decryptpted = cipher.doFinal(hexToBytes(code));
} catch(Exception e)
{
throw new Exception([decrypt]+ e.getMessage());
}
返回解密;
}



public static String bytesToHex(byte [] data)
{
if(data == null)
{
return null;
}

int len = data.length;
String str =; (int i = 0; i if((data [i]& 0xFF))16
str = str +0+ java .lang.Integer.toHexString(数据[1] - 安培;为0xFF);
else
str = str + java.lang.Integer.toHexString(data [i]& 0xFF);
}
return str;
}


public static byte [] hexToBytes(String str){
if(str == null){
return null;
} else if(str.length()< 2){
return null;
} else {
int len = str.length()/ 2;
byte [] buffer = new byte [len]; (int i = 0; i buffer [i] =(byte)Integer.parseInt(str.substring(i * 2,i * 2 + 2),16 );
}
return buffer;
}
}



private static String padString(String source)
{
char paddingChar =''
int size = 16;
int x = source.length()%size;
int padLength = size - x; (int i = 0; i< padLength; i ++)


{
source + = paddingChar;
}

返回源;
}
}

PHP代码

 <?php 

class MCrypt
{
private $ iv ='fedcba9876543210'; #如JAVA
private $ key ='0123456789abcdef'; #如JAVA


函数__construct()
{
}

函数加密($ str){

// $ key = $ this-> hex2bin($ key);
$ iv = $ this-> iv;

$ td = mcrypt_module_open('rijndael-128','','cbc',$ iv);

mcrypt_generic_init($ td,$ this-> key,$ iv);
$ encrypted = mcrypt_generic($ td,$ str);

mcrypt_generic_deinit($ td);
mcrypt_module_close($ td);

返回bin2hex($ encrypted);
}

函数解密($ code){
// $ key = $ this-> hex2bin($ key);
$ code = $ this-> hex2bin($ code);
$ iv = $ this-> iv;

$ td = mcrypt_module_open('rijndael-128','','cbc',$ iv);

mcrypt_generic_init($ td,$ this-> key,$ iv);
$ decryptpted = mdecrypt_generic($ td,$ code);

mcrypt_generic_deinit($ td);
mcrypt_module_close($ td);

return utf8_encode(trim($ decryptpted));
}

保护函数hex2bin($ hexdata){
$ bindata =''; ($ i = 0; $ i< strlen($ hexdata); $ i + = 2){
$ bindata。= chr(hexdec(substr($ hexdata,$ i,2)));
}

return $ bindata;
}

}

所以场景是java发送数据(简单文本)以JSON格式转换为PHP,php提取数据,对其进行加密,最后以JSON格式回显



PHP调用:

 <?php 

$ data = json_decode(file_get_contents('php:// input'),true);

$ data = $ data [request];
require_onceencryption.php;
$ etool = new MCrypt();
$ data = $ etool-> encrypt($ data);
$ array = array('data'=> $ data);
echo json_encode($ array);

JAVA代码:

  // sb是StringBuilder 
JSONObject j = new JSONObject(sb.toString());
加密etool = new encryption();
result = j.get(data)。toString();
result = new String(etool.decrypt(result));
Log.d(success remote,result);

结果是:



example



如果我使用波斯语/阿拉伯语,它会变得更糟糕



like this-> درود



此外,我检查了其他问题,但我无法得到答案。 >

AES加密,在解密文件中得到额外的垃圾字符,而

PHP MCRYPT加密/解密返回隐形奇怪的字符?



提前谢谢!

解决方案

AES 以16个字节的块加密。如果您的输入不是16字节的倍数,则需要填充方案。由于您没有为 Mcrypt 指定任何填充选项,所以使用零填充



在您的 Java 代码中,您在实例化密码时指定了NoPadding

  cipher = Cipher.getInstance(AES / CBC / NoPadding); 

所以 Java 认为由 php 成为加密数据的一部分。



您只需确保您的 php Java 代码使用相同的填充方案。


Excuse me for bad English. i use mcrypt which i get it from here MCrypt for php and java. in my android application i need php and java communicate securely so i get above mentioned AES. the problem is when php sends encrypted data, java can decrypt it but some extra characters are included.

JAVA Code

    import java.security.NoSuchAlgorithmException;

    import javax.crypto.Cipher;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;

    public class MCrypt {

            private String iv = "fedcba9876543210";//Dummy iv (CHANGE IT!)
            private IvParameterSpec ivspec;
            private SecretKeySpec keyspec;
            private Cipher cipher;

            private String SecretKey = "0123456789abcdef";//Dummy secretKey (CHANGE IT!)

            public MCrypt()
            {
                    ivspec = new IvParameterSpec(iv.getBytes());

                    keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");

                    try {
                            cipher = Cipher.getInstance("AES/CBC/NoPadding");
                    } catch (NoSuchAlgorithmException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    } catch (NoSuchPaddingException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    }
            }

            public byte[] encrypt(String text) throws Exception
            {
                    if(text == null || text.length() == 0)
                            throw new Exception("Empty string");

                    byte[] encrypted = null;

                    try {
                            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);

                            encrypted = cipher.doFinal(padString(text).getBytes());
                    } catch (Exception e)
                    {                       
                            throw new Exception("[encrypt] " + e.getMessage());
                    }

                    return encrypted;
            }

            public byte[] decrypt(String code) throws Exception
            {
                    if(code == null || code.length() == 0)
                            throw new Exception("Empty string");

                    byte[] decrypted = null;

                    try {
                            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

                            decrypted = cipher.doFinal(hexToBytes(code));
                    } catch (Exception e)
                    {
                            throw new Exception("[decrypt] " + e.getMessage());
                    }
                    return decrypted;
            }



            public static String bytesToHex(byte[] data)
            {
                    if (data==null)
                    {
                            return null;
                    }

                    int len = data.length;
                    String str = "";
                    for (int i=0; i<len; i++) {
                            if ((data[i]&0xFF)<16)
                                    str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
                            else
                                    str = str + java.lang.Integer.toHexString(data[i]&0xFF);
                    }
                    return str;
            }


            public static byte[] hexToBytes(String str) {
                    if (str==null) {
                            return null;
                    } else if (str.length() < 2) {
                            return null;
                    } else {
                            int len = str.length() / 2;
                            byte[] buffer = new byte[len];
                            for (int i=0; i<len; i++) {
                                    buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
                            }
                            return buffer;
                    }
            }



            private static String padString(String source)
            {
              char paddingChar = ' ';
              int size = 16;
              int x = source.length() % size;
              int padLength = size - x;

              for (int i = 0; i < padLength; i++)
              {
                      source += paddingChar;
              }

              return source;
            }
    }

the PHP code

 <?php 

    class MCrypt
    {
            private $iv = 'fedcba9876543210'; #Same as in JAVA
            private $key = '0123456789abcdef'; #Same as in JAVA


            function __construct()
            {
            }

            function encrypt($str) {

              //$key = $this->hex2bin($key);    
              $iv = $this->iv;

              $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);

              mcrypt_generic_init($td, $this->key, $iv);
              $encrypted = mcrypt_generic($td, $str);

              mcrypt_generic_deinit($td);
              mcrypt_module_close($td);

              return bin2hex($encrypted);
            }

            function decrypt($code) {
              //$key = $this->hex2bin($key);
              $code = $this->hex2bin($code);
              $iv = $this->iv;

              $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);

              mcrypt_generic_init($td, $this->key, $iv);
              $decrypted = mdecrypt_generic($td, $code);

              mcrypt_generic_deinit($td);
              mcrypt_module_close($td);

              return utf8_encode(trim($decrypted));
            }

            protected function hex2bin($hexdata) {
              $bindata = '';

              for ($i = 0; $i < strlen($hexdata); $i += 2) {
                    $bindata .= chr(hexdec(substr($hexdata, $i, 2)));
              }

              return $bindata;
            }

    }

so the scenario is java send data (simple text) in JSON format to PHP , php extract the data , encrypt it and finally echo it in JSON format

PHP call:

<?php

$data =json_decode(file_get_contents('php://input'), true);

$data=$data["request"];
require_once "encryption.php";
$etool=new MCrypt();
$data=$etool->encrypt($data);
$array=array('data'=>$data);
echo json_encode($array);

JAVA code:

 //sb is StringBuilder
JSONObject j=new JSONObject(sb.toString());
encryption etool=new encryption();
result=j.get("data").toString();
result= new String(etool.decrypt( result ));
Log.d("success remote ",result );

the result is:

example������

and if i use Farsi/Arabic word it get worse

like this-> درود����������������

in addition, i checked other questions but i could not get the answer.

AES encryption, got extra trash characters in decrypted file and
PHP MCRYPT encrypt/decrypt returns invisible strange characters?

thank you in advance!

解决方案

AES encrypt in blocks of 16 bytes. If your input ain't a multiple of 16 bytes, a padding scheme is needed. As you have not specified any padding option for Mcrypt, it uses "zero padding".

In your Java code you specify "NoPadding" when you instantiate your Cipher:

 cipher = Cipher.getInstance("AES/CBC/NoPadding");

So Java considers the padding done by php to be part of the encrypted data.

You just need to ensure that your php and Java code uses the same padding scheme.

这篇关于为什么AES java解密返回额外的字符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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