AES 128加密解密的Java在PHP [英] AES 128 encryption in Java Decryption in PHP

查看:369
本文介绍了AES 128加密解密的Java在PHP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在试图使用AES-128 CBC原本是加密的使用JAVA AES加密的字符串进行解密。在java中PKCS7使用填充。我试图进行加密和解密使用类似的PHP code。但我得到不同的结果。

我的JAVA code

 进口java.security.MessageDigest中;
进口java.security.spec.AlgorithmParameterSpec;

进口javax.crypto.Cipher中;
进口javax.crypto.spec.IvParameterSpec;
进口javax.crypto.spec.SecretKeySpec;

进口android.util.Base64;


/ **
 * @author vipin.cb,vipin.cb@experionglobal.com< BR>
 * 2013年9月27日,下午五时18分34秒< BR>
 *包装: - < B> com.veebow.util< / B> < BR>
 *项目: - < B> Veebow< / B>
 *所述p为H.;
 * /
公共类AESCrypt {

    私人最终加密密码;
    私人最终SecretKeySpec关键;
    私人的AlgorithmParameterSpec规范;
    公共静态最后弦乐SEED_16_CHARACTER =U1MjU1M0FDOUZ.Qz;

    公共AESCrypt()抛出异常{
        与SHA-256散列//密码和作物的产量为128位关键
        消息摘要摘要= MessageDigest.getInstance(SHA-256);
        digest.update(SEED_16_CHARACTER.getBytes(UTF-8));
        byte []的keyBytes =新的字节[32];
        System.arraycopy(digest.digest(),0,keyBytes,0,keyBytes.length);

        密码= Cipher.getInstance(AES / CBC / PKCS7Padding);
        键=新SecretKeySpec(keyBytes,AES);
        规格= getIV();
    }

    公众的AlgorithmParameterSpec getIV(){
        字节[] IV = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,};
        IvParameterSpec ivParameterSpec;
        ivParameterSpec =新IvParameterSpec(ⅳ);

        返回ivParameterSpec;
    }

    公共字符串加密(字符串明文)抛出异常{
        cipher.init(Cipher.ENCRYPT_MODE,重点,规范);
        byte []的加密= cipher.doFinal(plainText.getBytes(UTF-8));
        字符串encryptedText =新的String(Base64.en code(加密,
                Base64.DEFAULT),UTF-8);

        返回encryptedText;
    }

    公共字符串解密(字符串cryptedText)抛出异常{
        cipher.init(Cipher.DECRYPT_MODE,重点,规范);
        字节[]字节= Base64.de code(cryptedText,Base64.DEFAULT);
        byte []的解密= cipher.doFinal(字节);
        字符串decryptedText =新的String(解密,UTF-8);

        返回decryptedText;
    }

}
 

和等价的PHP code我使用。

 类mcrypt的{

    私人$ IV ='0000000000000000'; #Same在JAVA
    私人$键='U1MjU1M0FDOUZ.Qz'; #Same在JAVA

    功能__construct(){
        $这个 - >键=散列('SHA256',$这个 - >的关键,真正的);
    }

    函数加密($海峡){
        $ IV = $这个 - > 4;
        $ TD = mcrypt_module_open(MCRYPT_RIJNDAEL_128,'',MCRYPT_MODE_CBC,'');
        mcrypt_generic_init($ TD,$这个 - >的关键,$ IV);
        $块= mcrypt_get_block_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_CBC);
        $垫= $块 - (的strlen($海峡)%$块);
        $海峡= str_repeat(CHR($垫),$垫)。
        $加密= mcrypt_generic($ TD,$海峡);
        mcrypt_generic_deinit($ TD);
        mcrypt_module_close($ TD);
        返回base64_en code($加密);
    }

    功能解密($code){
        $ IV = $这个 - > 4;
        $ TD = mcrypt_module_open('的Rijndael-128','','CBC','');
        mcrypt_generic_init($ TD,$这个 - >的关键,$ IV);
        $海峡= mdecrypt_generic($ TD,base64_de code($code));
        $块= mcrypt_get_block_size('Rijndael算法-128,CBC);
        mcrypt_generic_deinit($ TD);
        mcrypt_module_close($ TD);
        返回$海峡;
        //返回$这个 - > strippadding($海峡);
    }

    / *
      对于PKCS7填充
     * /

    私有函数addpadding($字符串,$块大小= 16){
        $ LEN =的strlen($字符串);
        $垫= $块大小 - ($ LEN%$块大小);
        $字符串= str_repeat(CHR($垫),$垫)。
        返回$串;
    }

    私有函数strippadding($字符串){
        $ slast = ORD(SUBSTR($字符串,-1));
        $ slastc = CHR($ slast);
        $ P确认= SUBSTR($字符串 -  $ slast);
        如果(preg_match(/ $ slastc {。$ slast。} /,$弦)){
            $字符串= SUBSTR($字符串,0,strlen的($字符串) -  $ slast);
            返回$串;
        } 其他 {
            返回false;
        }
    }

}

$加密=新的mcrypt();
回声$加密 - >加密(123456)。 < BR />中;
回声$加密 - >解密('tpyxISJ83dqEs3uw8bN / + W ==');
 

在Java 纯文本= 123456 密文= tpyxISJ83dqEs3uw8bN / + W ==

在PHP

纯文本= 123456 密文= IErqfTCktrnmWndOpq3pnQ ==

当我试图decrpt了Java加密文本tpyxISJ83dqEs3uw8bN / + W ==使用PHP解密我得到一个空数组,如果我删除了填充。如果不去除填充我收到::::::::::

我觉得有一些错误的IV使用PHP和Java字节

任何人都可以帮助我在此。我已经尝试了多种组合。仍然没有结果。我是很新的Java概念。

---解决方案------------- 我已经根据owlstead给出的意见修改了我的PHP类。可能有一个更好的办法。我张贴在这里,这样的人可能会发现在未来有帮助,你的意见,欢迎进一步improvemenet。

 < PHP

一流的mcrypt {

    私人$ hex_iv ='00000000000000000000000000000000'; #转换JAVA字节code到十六进制,并在这里把它
    私人$键='U1MjU1M0FDOUZ.Qz'; #Same在JAVA

    功能__construct(){
        $这个 - >键=散列('SHA256',$这个 - >的关键,真正的);
        //回声$这个 - >的关键。< BR />';
    }

    函数加密($海峡){
        $ TD = mcrypt_module_open(MCRYPT_RIJNDAEL_128,'',MCRYPT_MODE_CBC,'');
        mcrypt_generic_init($ TD,$这个 - >的关键,$这个 - > hexToStr($这个 - > hex_iv));
        $块= mcrypt_get_block_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_CBC);
        $垫= $块 - (的strlen($海峡)%$块);
        $海峡= str_repeat(CHR($垫),$垫)。
        $加密= mcrypt_generic($ TD,$海峡);
        mcrypt_generic_deinit($ TD);
        mcrypt_module_close($ TD);
        返回base64_en code($加密);
    }

    功能解密($code){
        $ TD = mcrypt_module_open(MCRYPT_RIJNDAEL_128,'',MCRYPT_MODE_CBC,'');
        mcrypt_generic_init($ TD,$这个 - >的关键,$这个 - > hexToStr($这个 - > hex_iv));
        $海峡= mdecrypt_generic($ TD,base64_de code($code));
        $块= mcrypt_get_block_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_CBC);
        mcrypt_generic_deinit($ TD);
        mcrypt_module_close($ TD);
        返回$这个 - > strippadding($海峡);
    }

    / *
      对于PKCS7填充
     * /

    私有函数addpadding($字符串,$块大小= 16){
        $ LEN =的strlen($字符串);
        $垫= $块大小 - ($ LEN%$块大小);
        $字符串= str_repeat(CHR($垫),$垫)。
        返回$串;
    }

    私有函数strippadding($字符串){
        $ slast = ORD(SUBSTR($字符串,-1));
        $ slastc = CHR($ slast);
        $ P确认= SUBSTR($字符串 -  $ slast);
        如果(preg_match(/ $ slastc {。$ slast。} /,$弦)){
            $字符串= SUBSTR($字符串,0,strlen的($字符串) -  $ slast);
            返回$串;
        } 其他 {
            返回false;
        }
    }
功能hexToStr($十六进制)
{
    $字符串='';
    为($ i = 0; $ I< strlen的($十六进制)-1; $ I + = 2)
    {
        。$字符串= CHR(hexdec($十六进制[$ I] $十六进制[$ I + 1]));
    }
    返回$串;
}
}

$加密=新的mcrypt();
回声$加密 - >加密(123456)。 < BR />中;
回声$加密 - >解密('tpyxISJ83dqEs3uw8bN / + W ==');
 

解决方案

您IV是不同的,与零值是一个字符不同的字节'0'这将翻译与价值字节在小数30 以十六进制或48(如果presume ASCII或UTF-8编码)。

I have been trying to decrypt a string using AES-128 CBC which was originally crypted using JAVA AES encryption. In java PKCS7 padding is used. And i have tried to encrypt and decrypt using similar PHP code. But i am getting different result.

my JAVA code

 import java.security.MessageDigest;
import java.security.spec.AlgorithmParameterSpec;

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

import android.util.Base64;


/**
 * @author vipin.cb , vipin.cb@experionglobal.com <br>
 *         Sep 27, 2013, 5:18:34 PM <br>
 *         Package:- <b>com.veebow.util</b> <br>
 *         Project:- <b>Veebow</b>
 *         <p>
 */
public class AESCrypt {

    private final Cipher cipher;
    private final SecretKeySpec key;
    private AlgorithmParameterSpec spec;
    public static final String SEED_16_CHARACTER = "U1MjU1M0FDOUZ.Qz";

    public AESCrypt() throws Exception {
        // hash password with SHA-256 and crop the output to 128-bit for key
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        digest.update(SEED_16_CHARACTER.getBytes("UTF-8"));
        byte[] keyBytes = new byte[32];
        System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);

        cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        key = new SecretKeySpec(keyBytes, "AES");
        spec = getIV();
    }

    public AlgorithmParameterSpec getIV() {
        byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
        IvParameterSpec ivParameterSpec;
        ivParameterSpec = new IvParameterSpec(iv);

        return ivParameterSpec;
    }

    public String encrypt(String plainText) throws Exception {
        cipher.init(Cipher.ENCRYPT_MODE, key, spec);
        byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));
        String encryptedText = new String(Base64.encode(encrypted,
                Base64.DEFAULT), "UTF-8");

        return encryptedText;
    }

    public String decrypt(String cryptedText) throws Exception {
        cipher.init(Cipher.DECRYPT_MODE, key, spec);
        byte[] bytes = Base64.decode(cryptedText, Base64.DEFAULT);
        byte[] decrypted = cipher.doFinal(bytes);
        String decryptedText = new String(decrypted, "UTF-8");

        return decryptedText;
    }

}

And the equivalent PHP code i am using.

class MCrypt {

    private $iv = '0000000000000000'; #Same as in JAVA              
    private $key = 'U1MjU1M0FDOUZ.Qz'; #Same as in JAVA

    function __construct() {
        $this->key = hash('sha256', $this->key, true);
    }

    function encrypt($str) {
        $iv = $this->iv;
        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($td, $this->key, $iv);
        $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        $pad = $block - (strlen($str) % $block);
        $str .= str_repeat(chr($pad), $pad);
        $encrypted = mcrypt_generic($td, $str);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        return base64_encode($encrypted);
    }

    function decrypt($code) {
        $iv = $this->iv;
        $td = mcrypt_module_open('rijndael-128', '', 'cbc', '');
        mcrypt_generic_init($td, $this->key, $iv);
        $str = mdecrypt_generic($td, base64_decode($code));
        $block = mcrypt_get_block_size('rijndael-128', 'cbc');
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        return $str;
        //return $this->strippadding($str);             
    }

    /*
      For PKCS7 padding
     */

    private function addpadding($string, $blocksize = 16) {
        $len = strlen($string);
        $pad = $blocksize - ($len % $blocksize);
        $string .= str_repeat(chr($pad), $pad);
        return $string;
    }

    private function strippadding($string) {
        $slast = ord(substr($string, -1));
        $slastc = chr($slast);
        $pcheck = substr($string, -$slast);
        if (preg_match("/$slastc{" . $slast . "}/", $string)) {
            $string = substr($string, 0, strlen($string) - $slast);
            return $string;
        } else {
            return false;
        }
    }

}

$encryption = new MCrypt();
echo $encryption->encrypt('123456') . "<br/>";
echo $encryption->decrypt('tpyxISJ83dqEs3uw8bN/+w==');

In Java Plain text = 123456 Cipher text = tpyxISJ83dqEs3uw8bN/+w==

In PHP

Plain text = 123456 Cipher text = IErqfTCktrnmWndOpq3pnQ==

When i tried to decrpt the Java encrypted text "tpyxISJ83dqEs3uw8bN/+w==" using PHP decryption i am getting an empty array if i removed the padding . Without removing the padding i am getting "::::::::::"

I think there is some mistake with the IV bytes used in PHP and Java

Can anyone help me on this. I have tried many combinations . Still no result. I am very new to Java concepts.

---Solution------------- I have modified my php class according to the comments given by owlstead. may be there is a better way. I am posting it here so that someone may find it helpful in future and your comments are welcome for further improvemenet.

    <?php

class MCrypt {

    private $hex_iv = '00000000000000000000000000000000'; # converted JAVA byte code in to HEX and placed it here               
    private $key = 'U1MjU1M0FDOUZ.Qz'; #Same as in JAVA

    function __construct() {
        $this->key = hash('sha256', $this->key, true);
        //echo $this->key.'<br/>';
    }

    function encrypt($str) {       
        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($td, $this->key, $this->hexToStr($this->hex_iv));
        $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        $pad = $block - (strlen($str) % $block);
        $str .= str_repeat(chr($pad), $pad);
        $encrypted = mcrypt_generic($td, $str);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);        
        return base64_encode($encrypted);
    }

    function decrypt($code) {        
        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($td, $this->key, $this->hexToStr($this->hex_iv));
        $str = mdecrypt_generic($td, base64_decode($code));
        $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);        
        return $this->strippadding($str);               
    }

    /*
      For PKCS7 padding
     */

    private function addpadding($string, $blocksize = 16) {
        $len = strlen($string);
        $pad = $blocksize - ($len % $blocksize);
        $string .= str_repeat(chr($pad), $pad);
        return $string;
    }

    private function strippadding($string) {
        $slast = ord(substr($string, -1));
        $slastc = chr($slast);
        $pcheck = substr($string, -$slast);
        if (preg_match("/$slastc{" . $slast . "}/", $string)) {
            $string = substr($string, 0, strlen($string) - $slast);
            return $string;
        } else {
            return false;
        }
    }
function hexToStr($hex)
{
    $string='';
    for ($i=0; $i < strlen($hex)-1; $i+=2)
    {
        $string .= chr(hexdec($hex[$i].$hex[$i+1]));
    }
    return $string;
}
}

$encryption = new MCrypt();
echo $encryption->encrypt('123456') . "<br/>";
echo $encryption->decrypt('tpyxISJ83dqEs3uw8bN/+w==');

解决方案

Your IV is different, a byte with value zero is different from a character '0' which would translate into a byte with value 30 in hexadecimals or 48 in decimals (if you presume ASCII or UTF-8 encoding).

这篇关于AES 128加密解密的Java在PHP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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