AES 128加密解密的Java在PHP [英] AES 128 encryption in Java Decryption in 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屋!