2013-10-05 27 views
15

Orijinal olarak JAVA AES şifrelemesi kullanılarak şifrelenmiş olan AES-128 CBC'yi kullanarak bir dizgenin şifresini çözmeye çalışıyorum. Java PKCS7 dolgu kullanılır. Ve benzer PHP kodunu kullanarak şifrelemek ve şifresini çözmeye çalıştım. Ama farklı sonuç alıyorum.PHP'de Java Şifre Çözümünde AES 128 şifreleme

Benim Java kodu

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; 
    } 

} 

Ve kullanıyorum eşdeğer PHP kodu. Java
Düz metin olarak

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

= 123456
Şifreleme metin = tpyxISJ83dqEs3uw8bN/+ == w

PHP

Düz metin = 123456
Şifreleme metin = IErqfTCktrnmWndOpq3pnQ ==

Java şifrelenmiş metni "tpyxISJ83dqEs3uw8bN/+ w ==" kullanarak PHP şifre çözme işlemini denediğimde Dolguyu çıkarırsam boş bir diziyi tting. Tamponu çıkarmadan, "::::::::::"

Bence PHP ve Java'da kullanılan IV baytlarla ilgili bazı hatalar var. Bu konuda bana yardımcı olan var mı? Birçok kombinasyon denedim. Hala sonuç yok. Java kavramları için çok yeni.

------ Çözüm ------- Ben owlstead verdiği yorumlara göre benim php sınıfını değiştirdiniz

. daha iyi bir yol olabilir. Burada yayınlıyorum, böylece birileri bunu gelecekte yararlı bulabilir ve yorumlarınız daha da iyileştirilebilir. (Eğer ASCII veya UTF-8 kodlamasını tahmin eğer)

<?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

TEŞEKKÜRLER. Tam olarak aradığım şey bu. Anahtarımdaki bir yazım hatası düzeltildi ve magico'ya basma! – ssdscott

+0

@ssdscott 2 yıl geri gönderildikten sonra bile size yardım ettiğine sevindim :) – shanavascet

cevap

9

Kişisel IV değeri sıfır olan bir bayt ondalık içinde Heksadesimalleri değer 30 veya 48 olan bir byte çevirmek olacak bir karakteri '0' farklıdır, farklı.

+0

IV ..i ne olmalıydı? Ben java dizesine byte iv dönüştürmek için çalıştı ve uzunluğu 16 ile boş dize var. Ben hiç şans olmadan php kullanarak şifrelemek çalıştı. – shanavascet

+2

Her iki platformda IV'ün bayt değerlerini karşılaştırın. Simetrik şifrelerin girdi ve çıktısının bayt olduğunu ve baytların sırasının şifreler için önceden tanımlandığını unutmayın. Her zaman aynı sonucu platformdan bağımsız olarak almalısınız. Bu yüzden, algoritmalara girdiğiniz değerlerin her iki platformda da aynı olduğundan emin olun. Bunu yapmanın en iyi yolu, kriptografik işlemi gerçekleştirmeden önce onaltılık sayılardaki giriş değerlerini yazdırmaktır. (Karakter-) kodlama/kod çözme sorunlarına dikkat edin! Mümkünse, özdeş * bayt dizileri * kullanarak algoritmanın giriş/çıkışını test edin. –

+0

çok teşekkürler owlstead .. Bahsettiğin adımları takip ettim .. Sorunu cevaplamak için sabrınız ve yorumlarınız için teşekkürler ... aşkım. – shanavascet

İlgili konular