Hash

PHP AES-256 CBC 比 AES-128 CBC 快?

  • September 17, 2019

在過去的幾天裡,我一直在學習一些關於在 PHP 中加密數據的知識,因為我需要一個好的加密/解密函式來將使用者的密碼儲存在數據庫中。我openssl_random_pseudo_bytes()用於 IV,hash_hmac帶有 SHA256 和openssl_encrypt(). 這是加密的功能:

// 32 bytes (256-bit) (64 char) encryption key
define('ENCRYPTION_KEY', 'd027e7*+7b6d5fcd55f4b5c32611b87cd923e88837b63bf2941ef819dc8ca282');
// 16 bytes (128-bit) (32 char) encryption key
define('ENCRYPTION_KEY2', 'b6d5fcd55f4b5c32611b87cd923e88ae');
function pw_encrypt($encrypt, $key, $type){

   $hmac_key = 'd027e7*+7b6d5fcd55f4b57su921b87cd923e88837b63bf2941ef819dc8ca282';

   $encrypt = serialize($encrypt);

   $method = "AES-$type-CBC";

   $isCryptoStrong = false; // Will be set to true by the function if the algorithm used was cryptographically secure
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($method), $isCryptoStrong);

   if(!$isCryptoStrong)
       throw new Exception("Non-cryptographically strong algorithm used for iv generation. This IV is not safe to use.");

   $mac = hash_hmac('sha256', $encrypt, $hmac_key);

   $passcrypt = openssl_encrypt($encrypt.$mac,$method,$key,OPENSSL_RAW_DATA,$iv);
   $encoded = base64_encode($passcrypt).'|'.base64_encode($iv);

   return $encoded;
}

所以我執行這段程式碼來測試 AES-128/-256 與 128 位/256 位加密密鑰。現在困擾我的是 AES-256 似乎比 AES-128 更快,這正常嗎?

以下是結果——時間通常與此類似:

$data = '&>tsX@(3BjsAepZW';
Encrypted Data AES-128 128bit key: Length: 153 Total Execution Time: 2.6027361551921E-6 Mins
Encrypted Data AES-128 256bit key: Length: 153 Total Execution Time: 1.8000602722168E-6 Mins
Encrypted Data AES-256 128bit key: Length: 153 Total Execution Time: 1.7166137695313E-6 Mins
Encrypted Data AES-256 256bit key: Length: 153 Total Execution Time: 1.7166137695313E-6 Mins

那麼,讓我煩惱的是:

  1. 我在這裡做錯了什麼,還是 AES-128 真的比 AES-256 慢?
  2. 為什麼編碼字元串的長度在所有 4 種情況下都相同?
  3. 加密密鑰必須是十六進制格式還是我可以使用*+/-_.,'
  4. 的密鑰has_hmac,它應該是隨機生成的還是就像我擁有的一樣,是預定義的?如果是隨機的,創建隨機密鑰的最佳做法是什麼?它應該是什麼長度和類型(十六進製或+*/-'.?)?

我按順序回答:

  1. 不,你可能沒有做錯什麼。這只是編譯器預熱和執行優化。第二次執行您會看到 AES-128 已經快到了,這是您所期望的(它最終應該會稍微快一點,但這甚至可能不明顯)。
  2. 不知道,你必須調試,因為那肯定是錯誤的。
  3. 密鑰不應採用任何類型的編碼。OpenSSL 使用的密鑰應該由與隨機無法區分的字節組成。您可以使用十六進制將密鑰儲存在字元串中(這也是相當有問題的),但您應該在使用它之前對其進行解碼。
  4. 與加密密鑰相同;您將使用openssl_random_pseudo_bytes或其他安全的隨機數生成器。然後,您可以將其編碼為十六進製或基數 64,只要在使用之前再次將其解碼為二進制即可。

請注意,如果您提供 16 字節密鑰作為 32 個十六進制數,您可能正在使用 AES-256,而您自己卻沒有意識到這一點。針對另一個框架/加密庫(但不是mcrypt)的最佳測試。


您不應該加密儲存您的使用者密碼。相反,您應該使用密碼雜湊,例如bcrypt.

引用自:https://crypto.stackexchange.com/questions/32923