2012-08-07 53 views
1

我這裏有一些奇怪的問題....PHP vs JAVA AES加密有什麼區別?

我有以下兩個腳本:

首先,PHP腳本(我使用http://writecodeonline.com/php/測試)

$key = '[E%Xr6pG-IDIA89_&=NI[AREofOy0#Mv[[email protected]^PwgT!NVY*[email protected]($p4luBM)[email protected]*jBP3s$g#-XTH{[email protected]*0StJ'; 
$string = 'Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing '; 

// 
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, md5($key), $string, MCRYPT_MODE_ECB)); 

$decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, md5($key), base64_decode($encrypted), MCRYPT_MODE_ECB), "\0"); 


echo $encrypted . "<br>"; 
echo $decrypted; 

二,Java類,

import java.io.*; 
import java.net.*; 
import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 

import javax.crypto.*; 
import javax.crypto.spec.*; 

import org.apache.commons.codec.binary.Base64; 
import org.apache.commons.codec.digest.DigestUtils; 


public class Main { 

    /** 
    * @param args 
    * @throws Exception 
    */ 
    public static void main(String[] args) throws Exception { 

     String pw = "[E%Xr6pG-IDIA89_&=NI[AREofOy0#Mv[[email protected]^PwgT!NVY*[email protected]($p4luBM)[email protected]*jBP3s$g#-XTH{[email protected]*0StJ"; 
     String str = encode("Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing Testing ", pw); 
     System.out.println(str); 
     System.out.println(decode(str, pw)); 
    } 

    public static String encode(String s, String p) throws Exception 
    { 
     String cleartext = padRight(s, s.length()+(16-(s.length()%16))); 
     String key = DigestUtils.md5Hex(p); 
     SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES"); 
     Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); 
     cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
     byte[] encrypted = cipher.doFinal(cleartext.getBytes()); 
     return Base64.encodeBase64String(encrypted); 
    } 

    public static String decode(String encrypted, String p) throws Exception 
    { 
     byte[] bts = Base64.decodeBase64(encrypted); 


     String key = DigestUtils.md5Hex(p); 
     SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES"); 
     Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); 
     cipher.init(Cipher.DECRYPT_MODE, skeySpec); 



     byte[] decrypted = cipher.doFinal(bts); 

     return new String(decrypted).replaceAll("\0", ""); 
    } 

    public static String padRight(String s, int n) { 
     while (s.length() < n) 
     { 
      s+="\0"; 
     } 
     return s; 
    } 

} 

發生了一些非常奇怪的事情。當我測試PHP腳本時,我得到:

/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWg== 

作爲加密代碼。

當我測試的Java代碼,但是,我得到:

/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWv8MgkRUZlxQxpNDufhAB1r/DIJEVGZcUMaTQ7n4QAda/wyCRFRmXFDGk0O5+EAHWsdyQJ3DP2jBsJcLh2n2wv0= 

如果你仔細觀察,你會看到(在某種程度上)java的文本是更長久!但是,奇怪的是,兩個文本直到「+ EAH」出現時纔是完全相同的。我覺得這很奇怪 - 爲什麼?

因爲我已經在衆多其他字符串上測試了這個代碼,從lorum ipsum到沒有錯誤的單詞「Testing」。我發現導致這種情況的唯一方法(迄今爲止)是多次用空格隔開重複一個短小的單詞。

我非常擔心這個,因爲我不知道有什麼其他方式來觸發這種奇怪的行爲。所以這讓我想起了我的問題......以戴維瓊斯的儲物櫃的名義,這是爲什麼?

回答

4

我不是加密專家,但它可能是一個填充問題。你可以嘗試以下。

PHP
設置填充如下:

$blockSize = mcrypt_get_block_size(MCRYPT RIJNDAEIL_128, MCRYPT_MODE_ECB); 
$padding = $blockSize - (strlen($string) % $blockSize); 
$string .= str_repeat(chr($padding), $padding); 

這將使用PKCS#5填充,而不是PHP的空填充。

的Java
更改以下行:

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

到:

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 

不幸的是我沒有使用Java的環境中,我可以比較的結果,但我希望它有助於。

+0

由於一噸!這就像一個魅力!我想爲未來的觀衆注意,我必須將MCRYPT_RIJNDAEL_256更改爲MCRYPT RIJNDAEIL_128 – 2012-08-07 02:39:12

+0

很高興爲您提供幫助。我也更正了我的答案,我打算從頭開始寫128。這是早上有點早,我一定很困。 :) – Diego 2012-08-07 13:56:13

+0

不是問題!我自己很累 - 我的意思是在我的評論中寫MCRYPT_RIJNDAEIL_128而不是MCRYPT RIJNDAEIL_128 – 2012-08-07 23:06:47

1

的代碼在不斷的名字拼寫錯誤,正確的代碼是:

$blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB); 
$padding = $blockSize - (strlen($tokenRaw) % $blockSize); 
$tokenRaw .= str_repeat(chr($padding), $padding); 

$encode = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $tokenRaw, MCRYPT_MODE_ECB));