2015-06-19 63 views
1

我時不時地開始創建用於在PHP中加密/解密字符串和文件的函數。 我決定最終確定這些功能並做了一些搜索,但是我找不到足夠的資源來確認這些功能的安全性。php - 使用mcrypt對字符串和文件進行加密/解密

請注意,我不想使用另一個成熟的庫,除非有必要,我不明白爲什麼PHP提供了mcrypt函數,但沒有人真正實現它們。

我能夠找到these函數,但它們沒有被評論,並且有些步驟不清楚(也不會生成密鑰,但使用預定義密鑰)。 以下這些功能我也發現this stackoverflow的問題,但第一個答案使用另一個庫,而第二個使用ECB。

編輯:我更新先前使用的mcrypt到所建議的評價僅使用OpenSSL的代碼示例:

function generate_key($cipher = 'AES-256-CBC') 
{ 
    return base64_encode(openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher))); // Generate a random key - currently using the function for the vector length 
} 
function encrypt($data, $key, $cipher = 'AES-256-CBC') 
{ 
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher)); // Generate a random initialization vector 
    return base64_encode($iv) . '$' . openssl_encrypt($data, $cipher, base64_decode($key), false, $iv); // Return a base64 encoded string containing the iv and the encrypted data 
} 
function decrypt($data, $key, $cipher = 'AES-256-CBC') 
{ 
    $data = explode('$', $data); // Explode the previously encoded string 

    if(count($data) == 2) 
     return openssl_decrypt($data[1], $cipher, base64_decode($key), false, base64_decode($data[0])); // Decrypt the data given key and the iv 
    else 
     return false; 
} 

我使用這些函數這樣測試加密和解密:

$input = 'Hello world!'; 
echo 'Original data: ' . $input . '<br /><br />'; 

$key = generate_key(); 
$encrypted = encrypt($input, $key); 
echo 'Key used for encryption: ' . $key . '<br />'; 
echo 'Encrypted data: ' . $encrypted . '<br /><br />'; 

$decrypted = decrypt($encrypted, $key); 
echo 'Decrypted data: ' . $decrypted . '<br />'; 

問題:OpenSSL是否正確執行如上所示?它們也可以用於文件嗎?

這些是使用mcrypt的舊功能。 不要再使用它們了。

function generate_key($cipher = MCRYPT_RIJNDAEL_256) 
{ 
    return bin2hex(openssl_random_pseudo_bytes(mcrypt_get_key_size($cipher, MCRYPT_MODE_CBC))); // Generate a random key using OpenSSL with size given from mcrypt depending on cipher 
} 
function encrypt($data, $key, $cipher = MCRYPT_RIJNDAEL_256) 
{ 
    $iv = mcrypt_create_iv(mcrypt_get_iv_size($cipher, MCRYPT_MODE_CBC)); // Generate random initialization vector with size given from mcrypt depending on cipher 
    return bin2hex($iv) . '$' . bin2hex(mcrypt_encrypt($cipher, pack('H*', $key), $data, MCRYPT_MODE_CBC, $iv)); // Return the initialization vector and encrypted data as ASCII string 
} 
function decrypt($data, $key, $cipher = MCRYPT_RIJNDAEL_256) 
{ 
    $data = explode('$', $data); // Split the input data by $ to retrieve the initialization vector and the encrypted data 

    if(count($data) == 2) // Check if there are 2 parts after splitting by $ 
     return mcrypt_decrypt($cipher, pack('H*', $key), pack('H*', $data[1]), MCRYPT_MODE_CBC, pack('H*', $data[0])); // Return the decrypted string 
    else 
     return false; // Return false if the given data was not properly formatted (no $) 
} 
+1

你*問題*的含義有點模糊。你在尋找是/否的答案,這是否安全?你問是否mcrypt和openssl版本是相同的?你問如何確定openssl中的密鑰大小?請澄清你的問題。 StackOverflow不適用於是/否問題和討論。另外,請每個帖子堅持一個問題。 –

+2

我是使用另一個庫的第一個答案的作者。您可能還想看到[這個答案](http://stackoverflow.com/a/30189841/2224584),它解釋了在PHP中實現經過身份驗證的對稱密鑰加密的過程。它還演示瞭如何使用OpenSSL([請勿使用mcrypt](https://paragonie.com/blog/2015/05/if-you-re-typing-word-mcrypt-into-your-code-you-重新做-IT-錯))。 –

+0

@ArtjomB。你是對的。原來的問題有點失落。我會更新它。問題在於功能是否正確(它們不是),以及它們是否可以/應該如何用於文件。您的評論和Scott Arciszewskis評論已經幫助了很多人。我會考慮根據Scotts鏈接優化第二組函數。 – user1137183

回答

-1

目前最好的做法是avoid using mcrypt in favor of openssl

和速度基準,其中openssl is pretty much faster

+0

注意。我嘗試將上面的函數轉換爲純OpenSSL,但函數mcrypt_create_iv和mcrypt_get_key_size似乎沒有相同之處。我如何在OpenSSL中創建一個IV,併爲選定的密碼獲取適當的密鑰大小? PS:第二個鏈接是錯誤的。 – user1137183

+0

使用openssl_random_pseudo_bytes(最好將第二個參數設置爲TRUE)。這將產生具有適當隨機性特徵的IV。關於關鍵尺寸我不太確定,但它不會很難谷歌。 – venca

+0

我用OpenSSL版本更新了這個問題。我找不到確定密鑰大小的「OpenSSL-way」,因此我現在使用了矢量大小。爲什麼OpenSSL使用16字節作爲IV,而mcrypt使用32字節,儘管兩者都使用AES-256-CBC,是否有原因? – user1137183

相關問題