Encryption

ChaCha 矩陣 - 由於錯誤的計數器編碼而未通過原始實現的測試?

  • June 26, 2020

大家好,已經感謝您抽出寶貴時間閱讀本文!

我目前正在為我的學士論文實施 ChaCha20(256 位密鑰)。我知道有兩個版本的 ChaCha;IETF 協議中使用的版本和 DJB 原始設計的版本。

據我了解,唯一的區別應該是原來的有一個 64 位隨機數和一個 64 位計數器,而另一個有一個 96 位隨機數和一個 32 位計數器。

我從RFC7539 的第 2.3 節中獲取了這些資訊:

另請注意,原始 ChaCha 具有 64 位隨機數和 64 位塊計數。我們在此處對其進行了修改,以更符合第 3.2 節中的建議

$$ RFC5116 $$. 這將單個(鍵、隨機數)組合的使用限制為 2^32 塊或 256 GB,但這對於大多數用途來說已經足夠了。

在本節的下方,顯示了以下 ChaCha 狀態矩陣,它闡明了 32 位計數器和 96 位隨機數的用法:

cccccccc  cccccccc  cccccccc  cccccccc
kkkkkkkk  kkkkkkkk  kkkkkkkk  kkkkkkkk
kkkkkkkk  kkkkkkkk  kkkkkkkk  kkkkkkkk
bbbbbbbb  nnnnnnnn  nnnnnnnn  nnnnnnnn

c=constant k=key b=blockcount n=nonce

我已經使用同一篇論文第 2.3.2 節中的測試向量來成功驗證我對塊函式的實現:

Key = 00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f
Nonce = (00:00:00:09:00:00:00:4a:00:00:00:00)
Block Count = 1

由於密鑰、計數器和隨機數不等於 0 並且測試通過,我可以說我對數字的編碼很可能是正確的。我已將所有它們(包括常量)編碼為 little-endian,但計數器除外,因為這是塊函式之前的狀態應如下所示,如同一部分所述:

After setting up the ChaCha state, it looks like this:

ChaCha state with the key setup.

  61707865  3320646e  79622d32  6b206574
  03020100  07060504  0b0a0908  0f0e0d0c
  13121110  17161514  1b1a1918  1f1e1d1c
  00000001  09000000  4a000000  00000000

然後我繼續使用測試向量來加密第 2.4.2 節中的消息,我也可以使用它成功驗證我的實現,因此我很確定我的實現根據 IETF 版本是正確的。

現在我也想實現DJB的原始版本。因為我假設只有計數器和隨機數大小發生了變化,所以我認為這將非常簡單。我使用了從這裡獲取的這個測試向量:

Key:    0xc4 0x6e 0xc1 0xb1 0x8c 0xe8 0xa8 0x78
       0x72 0x5a 0x37 0xe7 0x80 0xdf 0xb7 0x35
       0x1f 0x68 0xed 0x2e 0x19 0x4c 0x79 0xfb
       0xc6 0xae 0xbe 0xe1 0xa6 0x67 0x97 0x5d
IV:     0x1a 0xda 0x31 0xd5 0xcf 0x68 0x82 0x21
Rounds: 20

Keystream block 1:
0xf6 0x3a 0x89 0xb7 0x5c 0x22 0x71 0xf9
0x36 0x88 0x16 0x54 0x2b 0xa5 0x2f 0x06
0xed 0x49 0x24 0x17 0x92 0x30 0x2b 0x00
0xb5 0xe8 0xf8 0x0a 0xe9 0xa4 0x73 0xaf
0xc2 0x5b 0x21 0x8f 0x51 0x9a 0xf0 0xfd
0xd4 0x06 0x36 0x2e 0x8d 0x69 0xde 0x7f
0x54 0xc6 0x04 0xa6 0xe0 0x0f 0x35 0x3f
0x11 0x0f 0x77 0x1b 0xdc 0xa8 0xab 0x92

Keystream block 2:
0xe5 0xfb 0xc3 0x4e 0x60 0xa1 0xd9 0xa9
0xdb 0x17 0x34 0x5b 0x0a 0x40 0x27 0x36
0x85 0x3b 0xf9 0x10 0xb0 0x60 0xbd 0xf1
0xf8 0x97 0xb6 0x29 0x0f 0x01 0xd1 0x38
0xae 0x2c 0x4c 0x90 0x22 0x5b 0xa9 0xea
0x14 0xd5 0x18 0xf5 0x59 0x29 0xde 0xa0
0x98 0xca 0x7a 0x6c 0xcf 0xe6 0x12 0x27
0x05 0x3c 0x84 0xe4 0x9a 0x4a 0x33 0x32

由於 IV 是 64 位的,我假設這確實是原始 ChaCha 實現的測試向量。

現在我的問題是(幾乎與兩週前的另一個問題一樣)我可以重現第一個鍵塊,計數器設置為 0,但不能重現第二個鍵塊(計數器設置為 1)。由於我可以通過第一個關鍵塊的測試(以及計數器設置為 0 的所有其他測試),我假設我對除計數器之外的所有內容的編碼都是正確的。

因此我的問題是:在 ChaCha 的原始實現中,計數器的正確編碼是什麼?

我試過用 little-endian 寫它,但沒有成功。

讓我感到困惑的是——我在這裡提到它是因為它可能與我的反問題有關——在DJB 的 ChaCha 規範中,如下所述:

細節上有3個不同

$$ in contrast to Salsa20 $$. 首先,ChaCha 排列輸出塊中的單詞順序以匹配上述排列。$$ … $$ 其次,ChaCha 在底部建構所有攻擊者控制的輸入詞的初始矩陣:

constant constant constant constant
key      key      key      key
key      key      key      key
input    input    input    input

關鍵字只是按順序複製;輸入字是塊計數器,後跟隨機數;常數與 Salsa20 中的相同。

既然說“關鍵字只是按順序複製”,我會假設它必須是大端的,因為這是人們閱讀關鍵字的順序;但是我的測試通過了計數器設置為 0 並且 key != 0 in little-endian (對於 nonce 相同)所以我認為我只是誤解了這一點,他實際上意味著一切都是用 little-endian 編寫的?(上面提到的 counter != 0 對我不起作用。)

我終於解決了我的問題:

我需要將計數器轉換為 little-endian,然後將其拆分為 4 字節塊,再次將每個塊格式化為 little-endian:

1. 00:00:00:00:00:00:00:01 ("raw" counter value)
2. 01:00:00:00:00:00:00:00 (as little-endian)
3. 01:00:00:00 00:00:00:00 (split into 4 byte chunks)
4. 00:00:00:01 00:00:00:00 (each chunk as little-endian)

也許這將有助於將來的某人。

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