2013-10-05 25 views
15

Tôi đã cố gắng giải mã một chuỗi bằng AES-128 CBC vốn được mã hóa ban đầu bằng cách sử dụng mã hóa AES của JAVA. Trong java PKCS7 padding được sử dụng. Và tôi đã cố gắng mã hóa và giải mã bằng cách sử dụng mã PHP tương tự. Nhưng tôi nhận được kết quả khác nhau.Mã hóa AES 128 trong Giải mã Java trong PHP

Mã của tôi Java

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 , [email protected] <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; 
    } 

} 

Và mã PHP tương đương Tôi đang sử dụng.

<?php 

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

Trong Java
Plain text = 123456
văn bản Cipher = tpyxISJ83dqEs3uw8bN/+ w ==

Trong PHP

Plain text = 123456
văn bản Cipher = IErqfTCktrnmWndOpq3pnQ ==

Khi tôi cố gắng giải mã văn bản được mã hóa Java "tpyxISJ83dqEs3uw8bN/+ w ==" bằng cách sử dụng giải mã PHP Tôi là ge tting một mảng trống nếu tôi loại bỏ các padding. Nếu không loại bỏ các padding tôi nhận được "::::::::::" "

Tôi nghĩ rằng có một số sai lầm với các byte IV được sử dụng trong PHP và Java Bất cứ ai có thể giúp tôi về điều này. Tôi đã thử nhiều kết hợp. Vẫn không có kết quả. Tôi rất mới với khái niệm Java.

------ Giải pháp -------

tôi đã sửa đổi? Php class của tôi theo các ý kiến ​​được đưa ra bởi owlstead. có thể có một cách tốt hơn. Tôi đăng nó ở đây để ai đó có thể tìm thấy nó hữu ích trong tương lai và ý kiến ​​của bạn được chào đón để cải thiện hơn nữa.

<?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=='); 
+0

CẢM ƠN BẠN. Điều này thật đúng với gì mà tôi đã tìm kiếm. sửa lỗi đánh máy trong chìa khóa và magico của tôi! – ssdscott

+0

@ssdscott tôi vui vì nó đã giúp bạn ngay cả sau khi gửi bài 2 năm trở lại :) – shanavascet

Trả lời

9

IV của bạn là khác nhau, một byte với giá trị zero là khác nhau từ một nhân vật '0' đó sẽ chuyển thành một byte có giá trị 30 trong hexadecimals hoặc 48 trong số thập phân (nếu bạn đoán ASCII hoặc mã UTF-8).

+0

những gì nên là IV .. tôi đã đưa ra 16 không gian cho IV mà không có may mắn. tôi đã cố gắng để chuyển đổi byte iv để chuỗi trong java và có chuỗi rỗng với chiều dài 16. Tôi đã cố gắng mã hóa trong php bằng cách sử dụng nó mà không có bất kỳ may mắn. – shanavascet

+2

So sánh các giá trị byte của IV trên cả hai nền tảng. Hãy nhớ rằng đầu vào và đầu ra của mật mã đối xứng là theo byte, và thứ tự của các byte đã được định nghĩa trước cho mật mã. Bạn sẽ luôn nhận được kết quả tương tự không liên quan đến nền tảng. Vì vậy, hãy đảm bảo rằng các giá trị bạn nhập vào các thuật toán giống nhau trên cả hai nền tảng. Cách tốt nhất để làm điều này là in ra các giá trị đầu vào trong hệ thập lục phân ngay trước khi thực hiện thao tác mã hóa. Cẩn thận với các vấn đề mã hóa/giải mã (character-)! Nếu có thể, hãy kiểm tra đầu vào/đầu ra của thuật toán bằng cách sử dụng các mảng byte * giống hệt nhau *. –

+0

cảm ơn rất nhiều owlstead .. i theo các bước bạn đã đề cập .. cảm ơn sự kiên nhẫn của bạn để trả lời câu hỏi của tôi và cho các ý kiến ​​ở đây ... yêu u. – shanavascet

Các vấn đề liên quan