是否有線上方法可以使用分組密碼生成唯一的nnn保證無衝突的位2n2n2^n次?
$ n $ 是每次使用者執行實現時選擇的執行時變數。
我能想到的一種方法是使用任何分組密碼,比如 AES,作為種子 CSPRNG 來隨機打亂數字列表 $ 0, 1, \ldots, 2^n-1 $ . 這樣我就可以保證無碰撞 $ 2^n $ 數字。但是這種方法太貴了,因為它需要我交換 $ 2^n $ 數字。
我能想到的另一種方法是使用分組密碼生成密文 $ c = \mathrm{enc}(\mathrm{0x000}\ldots, \mathrm{key}) $ , 在哪裡 $ \mathrm{len}(c) \ge n $ . 然後拿第一 $ n $ 許多位 $ c $ ; 讓我們稱之為 $ c_n $ . 然後做: $ c_n \oplus 0, c_n \oplus 1, \ldots, c_n \oplus 2^n-1 $ . 這是有效的,但問題是,我認為,序列不是隨機的。例如 $ c_n \oplus 0 $ 通常會更接近 $ c_n \oplus 1 $ 比,說, $ c_n \oplus 100 $ .
***問題:***是否有更快的方法,我可以使用任何分組密碼大約一次,生成下一個數字,這樣,當我重複這個過程時,我得到 $ 2^n $ 許多唯一的數字沒有衝突?
從某種意義上說,我想我可以稱之為:洗牌的線上版本 $ 0, 1, \ldots, 2^n-1 $ ,而不需要在記憶體中維護一個列表 $ 2^n $ 長。
理想情況下,如果找到完美的線上 shuffle,它必須具有這個分佈(其中 $ i $ 是任何數字 $ {0, 1, \ldots, 2^n-1} $ 和 $ N_j $ 是一個隨機變數,它將取集合中的一個數字的值 $ j^{th} $ 理想的線上洗牌器的呼叫):
$$ \begin{split} \Pr(N_0 = i) &= 1/2^n \ \Pr(N_1 = i) &= 1/(2^n - 1) \ \Pr(N_2 = i) &= 1/(2^n - 2) \ \vdots & \ \Pr(N_{2^n-1} = i) &= 1/(2^n - (2^n-1)) = 1\ \end{split} $$
是否有線上方法可以使用分組密碼生成唯一的 $ n $ 保證無衝突的位 $ 2^n $ 次?
顯而易見的方法是選擇分組密碼的格式保留加密模式,例如FF1。這是一種採用任意長度塊的模式(在您的情況下, $ n $ 位);您將插入密鑰並加密計數器。使用固定密鑰(和隨機數),加密是可逆的,並且輸出的長度與輸入的長度完全相同 - 這正是您所要求的。
我能看到的唯一缺點是 FF1 可能對真正的小塊存在安全問題(在你的情況下, $ n \le 6 $ )。當然,如果使用者要求這麼小的 $ n $ ,您可以依靠“將值從 0 置換為 $ 2^n-1 $ 戰略…)