Encryption

關於SHA3密碼流加密方案的問題

  • February 13, 2016

**出於展示目的,**我編寫了一個使用散列作為密碼流的加密實現。我知道它比 AES 等更明智的選項要慢,但我對幾件事感興趣,我將在此消息的底部列出。

注意:我使用類似於 C++ 的偽語言編寫此程式碼,並為簡單起見使用字元串,我知道在實踐中流可以輸出空字元並導致字元串讀取出現問題。SHA3​​ 被假定為 512 位風格。

SHA3_Sym_Enc(key,message)
{
base_key=SHA3(key); //not really needed, but in case we will ever allow the key to be "anything", we'll standardize the initial value like this

keystream="";
int counter=0;

for(read_message=0;read_message<message_length;read_message+=base_key.length()) //work in blocks of SHA3 outputs
   {
   hash_block=SHA3(base_key+string(counter)); //H(base_key+#) -> block#
   keystream+=hash_block; //add blocks into one big pseudorandom output
   counter++;
   }

keystream=keystream.Left(message.length()); //our keystream works in blocks, and might output bigger than the message, so trim any excess

return message^keystream; //XOR the keystream with the message, output
}

void main()
{
scanf(key); //input user key

nonce=generate_random_bytes(sizeof(SHA3)); //generate a nonce, SHA3-length should be enough

message_key=SHA3(key+nonce); //build the actual key that is going to encrypt the message via concat and hash

ciphertext=SHA3_Sym_Enc(message_key,plaintext); //output the encrypted message via the function described earlier

final_message=ciphertext+SHA3(ciphertext+message_key)+nonce; //append a MAC and the nonce to the message, note that we are not doing HMAC because SHA3 is supposedly immune to length extension attacks
}

final_message[ciphertext][MAC][nonce]

解密:

  1. 分解 final_message,提取 MAC 和 nonce,它們的長度是預先確定的,並且已知它們在末尾,所以這很容易
  2. 取key+nonce和hash,到達message_key
  3. Hash ciphertext+message_key,如果它們=MAC,則消息未被篡改
  4. 通過函式將密文解析回來重建原始消息

現在我的問題:

  1. 如果給定一個足夠大的密碼,這個系統看起來安全嗎?
  2. 這裡使用的雜湊函式有一個 512 位的輸出和 1066 位的內部狀態;它真的提供 512 位的安全性嗎?此外,由於散列即使對於微小的增量更改也會產生截然不同且不相關的輸出,這是否意味著即使沒有隨機數,它也不會受到相關密鑰攻擊的影響?我問這些是因為 AES 只能達到 256 位,並且相關密鑰存在一些已知問題,就這兩點而言,這個流會更好嗎?
  3. 如果我只連結輸出的一半而不是完整的 H(base_key+counter),為了進一步隱藏攻擊者試圖獲取的有關密鑰流來源的任何重要資訊,我會失去多少安全性?我會降到511還是256?我認為這會非常好,因為理論上流可以在某些時候輸出一個與前一個塊相同的塊,而這在完全實現中意味著流已經達到一個間隔並開始重複,但是這個不會因為看不見的位仍然不同,進一步混淆了攻擊者。

TL;DR:這個想法很好,並且實施應該安全地工作(具有可靠的安全餘量),因為實施了一些調整。

它有多安全?

A) 如果給定一個足夠大的密碼,這個系統看起來安全嗎?

如果您將“密碼”替換為“密鑰”,那麼答案應該是肯定的。

出於分析目的,讓我們定義 $ E_K(M) = \operatorname{MAC}_K(\text{CTR} || \text{Nonce})\oplus M $ , 和 $ \operatorname{MAC}_K(M) = \operatorname{Keccak}(K||M) $ . nonce 是基於消息的,而計數器是基於呼叫的,即計數器每 512 位增加一。MAC 已經在這裡進行了分析。

讓我們進一步定義 $ E^A_K(M) = \text{Nonce}||E_{K1}(M)||MAC_K(E_{K2}(M)) $ 這是完全認證的加密模式。請注意,我在這裡使用了不同的密鑰進行身份驗證和加密。這消除了兩個組件之間潛在的危險依賴關係。更不用說密鑰和密文的順序被交換為身份驗證以獲得更多的一致性並且不做潛在的危險事情。

上面的加密組件基本上是 CTR 模式,有一個拆分計數器,其中一部分是“靜態的”,一部分是“動態的”,就像在 GCM 中所做的那樣。當您使用隨機數和計數器正確隨機化它時,這是一個適當的實例,因此是標準的安全界限 $ 2^{n/2} $ (對於非排列)成立,即加密強度為 256 位。這是因為您預計在大致經過雜湊後會發生衝突 $ 2^{n/2} $ 具有不同值的呼叫,從而可以從中獲取有關明文的資訊。至於身份驗證,至少需要衝突攻擊來破壞標準的 encrypt-then-mac,同時提供(至少)256 位安全性。

如果截斷散列函式的輸出,安全性會相應降低。SHA-3-256 只會產生 128 位的強度,正如您所期望的那樣 $ 2^{128} $ 呼叫而不是 $ 2^{256} $ .

潛在的改進

  1. 使鍵獨立。
  2. 使散列的參數順序一致(即始終是鍵在前)
  3. 將關聯數據 (AD) 考慮在內,特別是應始終對 nonce 進行身份驗證。

現實生活中的應用

如果這不是出於展示目的,您應該強烈避免使用自己的加密,而是使用AES-GCM(無論如何應該更快)、任何標準的 AES 身份驗證加密方案、Keyak或 otus 在評論中連結的方案:“雙工海綿:單通認證加密和其他應用程序”,Bertoni、Daemen 等。人。

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