2012-03-20 42 views
8

這裏是一個PHP演示腳本,加密和解密數據:爲什麼mcrypt_encrypt()將二進制字符放在我的字符串末尾?

<? 

$encryptionkey = 'h8y2p9d1'; 

$card_nbr = "1234"; 
echo "original card_nbr: $card_nbr <br>\n"; 

$card_nbr_encrypted=encrypt_data($card_nbr); 
echo "card_nbr_encrypted: $card_nbr_encrypted <br>\n"; 

$card_nbr_decrypted=decrypt_data($card_nbr_encrypted); 
echo "card_nbr_decrypted: $card_nbr_decrypted <br>\n"; 

$len=strlen($card_nbr_decrypted); 
echo "length: $len <br>\n"; 



function encrypt_data($text){ 
    global $encryptionkey; 
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); 
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
    $encrypted_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $encryptionkey, $text, MCRYPT_MODE_ECB, $iv); 
    return $encrypted_text; 
} 

function decrypt_data($text){ 
    global $encryptionkey; 
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); 
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
    $decrypted_text = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $encryptionkey, $text, MCRYPT_MODE_ECB, $iv); 
    return $decrypted_text; 
} 

?> 


的輸出是:

original card_nbr: 1234 
card_nbr_encrypted: vY¨(Z$<§G3-žÃ-Éù3Ý2Ê×rz¨VÛ 
card_nbr_decrypted: 1234 (and 28 binary characters) 
length: 32 


輸出被成功地解密,但28個二進制字符被添加到結束。在查看HTML源代碼時,這在Firefox中很容易看到。 32的字符串長度也說明了這一點。有任何想法嗎?

enter image description here

+0

看看是否可以有任何幫助http://php.net/manual/en/function.base64-encode.php – 2012-03-20 05:33:34

+0

@Mian_Khurram_Ijaz我不明白爲什麼會有所幫助 – Ben 2012-03-20 05:38:41

+0

輸出實際上是二進制格式所以爲了使它安全跨網絡base64_encode是有益的加密和解密工作正常,所以我想如果二進制字符是問題,然後使用base64 .. – 2012-03-20 05:41:20

回答

8

使用空字符\0填充返回的字符串以填充n * blocksize字節,這就是您看到額外數據的原因。

如果您運行$card_nbr_decrypted= rtrim($card_nbr_decrypted, "\0");它應該返回實際數據。

+0

如果你想要的話,使用'rtrim'的解決方案當然會被破壞來加密任意二進制數據,這些數據可能實際上以一些空值結束。在這種情況下,你應該將帶外字符串的長度和substr的長度傳回給那個長度(容易,但是會泄漏字符串的長度),或者在加密前自己填充 - 我推薦使用PKCS#7填充方法,因爲它很容易理解。 – hobbs 2012-03-20 05:49:14

+0

PKCS#7的問題是編寫和維護mcrypt的bozos確實爲它提供了支持。 – zaph 2016-01-16 21:37:24

3

這似乎是一個known problem。解碼後使用rtrim()刪除多餘的NUL。

2

由於您使用電子代碼塊(ECB)爲您的block cipher mode of operation填充了明文末尾以符合塊大小,因此您正在接收空字節。在你的情況下,塊大小是256位,因爲你使用的是MCRYPT_RIJNDAEL_256

如果您使用密碼反饋(CFB)模式 - MCRYPT_MODE_CFB - 無空字節,無需修剪,則可以避免使用此填充問題。但是,對於CFB,您應該使用加密數據HMAC,以驗證它是否已被篡改(see "Mallet")。你可以在Cryptography For The Average Developer找到一個工作實現的例子。

另外值得注意的是,ECB模式被認爲不太安全,因爲它可以reveal data patterns。此外,ECB(和CBC,因爲它也墊)可能容易受到padding oracle attack

-1

我認爲這個問題是您正在使用二進制數據時:

mcrypt_encrypt - 加密與給定參數

您可以使用使用明文BASE64_ENCODE($文本)明文。

+0

編碼與加密不同。 – 2016-06-22 15:51:23

+0

我知道。但是,如果您使用mcrypt_encrypt將$ text作爲base64明文發送以避免編碼問題很有用。 您可以使用base64_encode($ text)或rtrim()作爲其他用戶的建議。 – bLuEdDy 2016-06-28 09:37:10

相關問題