2017-01-10 52 views
3

我想實現一種簡單而安全的方式,將一些信息從PHP腳本發送到Java客戶端。我已經在這裏查看了幾個實現,但目前爲止沒有任何工作,現在我感到很沮喪。我有位編輯使用的最後一個是這一個:PHP中的簡單AES加密,Java解密

PHP:

function enc3($plaintext) { 

$length = 16; 
$key = openssl_random_pseudo_bytes($length); 

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 

$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, 
          $plaintext, MCRYPT_MODE_CBC, $iv); 

echo base64_encode($ciphertext); 
echo "\n".base64_encode($iv); 
echo "\n".base64_encode($key); 
} 
enc3("test"); 

的Java:

public static byte[] decrypt(byte[] key, byte[] initVector, byte[] encryptedValue) { 

    try { 

     IvParameterSpec iv = new IvParameterSpec(initVector); 
     SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); 

     Cipher cipher = Cipher.getInstance("AES/CBC/NOPADDING"); 
     cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); 

     byte[] original = cipher.doFinal(encryptedValue); 

     return original; 
    } catch (Exception ex) { 
     Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex); 
    } 

    return null; 
} 
... 
byte[] encpryted = Base64.getDecoder().decode(rd.readLine()); 
byte[] iv = Base64.getDecoder().decode(rd.readLine()); 
byte[] key = Base64.getDecoder().decode(rd.readLine()); 

byte[] output = decrypt(key, iv, encpryted); 

我也得到一個:

javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes 

的關鍵只是爲了在那裏調試,當然,我會在工作時將其刪除,並將其存儲在客戶端中。不知道最好的辦法是什麼,不知怎的,我想通過隱藏的方式隱藏它,服務器也知道如何生成它。但我想它會在內存中可讀,不是嗎?

+0

如果您使用PHP 7.1.0,mcrypt_encrypt()已被拒絕。 –

+0

不,我不使用PHP7,它是PHP5.6.22-2 –

+0

你檢查過'encryptedValue'的長度嗎? – SubOptimal

回答

3

AES是分組密碼,只適用於16個字節的塊。如果密文長度不能被16整除,則會導致IllegalBlockSizeException事件。

您可以輕鬆實現PKCS5填充的AES/CBC加密在PHP中,這基本上是一個標準化的方式你的明文輸入如何墊是塊大小的整數倍:

function pkcs5_pad($text) { 
    $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 
    $pad = $size - (strlen($text) % $size); 
    return $text . str_repeat(chr($pad), $pad); 
} 

然後更新您的加密功能,使用填充:

$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, 
pkcs5_pad($plaintext), MCRYPT_MODE_CBC, $iv); 

的Java已經實施了PKCS5支持,只需更新AES密碼初始化:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); 
+0

現在正在工作,謝謝!但我有另一個問題,我完全不知道如何或爲什麼會發生這種情況。我編碼這樣的東西:「sha1,sha2」,並將其拆分爲Java。現在解碼工作正常,但split [1]的長度不等於split [0]。它有15個以下的「不可見」字符,似乎是字節= 0。如果我將[1] .toString()分割出來,它只顯示「sha2」,但是如果我將split1.length()顯示爲19而不是4.任何想法,這些字節來自哪裏?它使我瘋狂了幾個小時,因爲我沒有得到爲什麼split [1] .equal(sha2)不起作用,直到我檢查了split [1]的長度。 –

+0

好吧,這只是運氣,我猜,仍然得到javax.crypto.IllegalBlockSizeException:輸入長度不是隨機的16個字節的倍數,即使您的修剪實施,任何想法爲什麼或如何解決這個問題?它不會總是發生,但有時候,即使加密文本也不會改變。 –

+1

@ M.H。你是對的,以前的解決方案有問題,所以解碼後的文本尾隨隱藏的字符。我已經更新了我的答案,以使用標準化的方式來正確填充加密的文本。 – sider