Entropy

BouncyCastle 風格的 ThreadedSeedGenerator

  • December 8, 2018

我編寫了一個 BouncyCastle 風格的執行緒播種器,並且想知道程序生成的數據的可預測性。

我不簡單地使用 BouncyCastle 的原因是安全性不是問題,我不想只為一個函式使用整個庫,而且這段程式碼要快得多。

這個想法是讓幾個執行緒在循環緩衝區(一個簡單的數組)上執行,其中每個執行緒對緩衝區中的數據執行不同的操作。隨機性來自作業系統中的執行緒調度不規則性。

我可以從這樣的機制中獲得多少隨機性?

C#程式碼:

using System;
using System.Threading;

class ThreadedSeeder
{
   static public ulong[] buffer = new ulong[1024];
   static public bool doThread = true;

   public ThreadedSeeder()
   {
       MakeThread(Add);
       MakeThread(Multiply);
       MakeThread(Xorshift);

       Thread.Sleep(10);

       doThread = false;
   }

   static private void MakeThread(ThreadStart a)
   {
       Thread b = new Thread(a)
       {
           Priority = ThreadPriority.Lowest
       };

       b.Start();
   }

   static private void Add()
   {
       int i = 0;

       while (doThread)
       {
           buffer[i & 1023] += (ulong)DateTime.UtcNow.Ticks;
           i++;
       }
   }

   static private void Multiply()
   {
       int i = 0;

       while (doThread)
       {
           buffer[i & 1023] *= 6364136223846793005;
           i++;
       }
   }

   static private void Xorshift()
   {
       int i = 0;

       while (doThread)
       {
           ulong y = buffer[i & 1023];

           y ^= (y << 13);
           y ^= (y >> 17);
           y ^= (y << 5);
           buffer[i & 1023] = y;

           i++;
       }
   }
}

這種方法在許多方面都存在嚴重缺陷。

  1. 在重負載下,整體返回為零是非常合理的buffer,這是攻擊者經常可以故意造成的(例如,需要高 CPU 負載的網路流量氾濫;會想到啟動多個 https 連接)。這很可能是一場實際的災難。

機制:啟動的三個執行緒ThreadedSeeder都設置為Lowest-priority,所以在Thread.Sleep(10). Lowest如果機器在暫停期間的優先級高於執行的操作,則可以在執行緒測試doThread = false之前繼續執行,因此不執行與 相關的任何操作。這同樣適用於和Add``doThread``Add``buffer``Multiply``Shift``buffer也是,但這無關緊要,因為這些執行緒即使執行也不能歸零。 2. DateTime.UtcNow.Ticks更一般地說,呼叫次數幾乎沒有保險;這可能很少,包括每個buffer條目少於一次,因此所有其他條目總是為零。機器越忙,一個buffer條目就越有可能沒有、一個或很少的讀數DateTime.UtcNow.Ticks影響它。 3. 我沒有看到任何機制阻止MultiplyXorshift競爭它的操作Add元素,buffer因此Add同時進行的更改無效。這是一種不受控制的競爭條件,它可能會失去一些收集到的熵。 4. DateTime.UtcNow.Ticks可以被對手非常接近。那應該是UTC時間,這不是秘密。此外,諸如RFC 7323高解析度 TCP 時間戳之類的常見機制允許找到特定機器認為的 UTC 時間,即使它的同步性很差。當機器處於輕負載狀態時,一個 CPU 執行每個執行緒,包括Add全速執行,讀數之間的差異將是可重複的。 5. 從DateTime.UtcNow.Ticks緩衝區到每個元素中的內容的轉換是相對較少的公共轉換之一。並且這些可能的轉換中的每一個都是可逆的(通過奇數常數模乘以 2 的冪的模乘是可逆的Multiply,以及 中的三個按位運算中的每一個都是可逆的Xorshift)。結合 4,buffer只要只有一個DateTime.UtcNow.Ticks影響它的元素輸出,它就可以輕鬆地在每個元素輸出上使用一個非常有選擇性的區分器,還可以揭示發生了哪個轉換。看起來這可以擴展到一些這樣的影響。 6. 程式碼和問題的文本都沒有顯示任何努力創建收集的熵的顯式擴散:元素buffer永遠不會混合。如果在使用前沒有這種混合或/和後處理,2/4/5 的buffer某種程度可能是一場實際的災難。 7. 定時執行不會在某些精確控制的執行環境中收集任何熵,包括硬體工程師使用的虛擬機/模擬器或惡意軟體的逆向工程。最終,buffer輸出的狀態,以及由此確定的任何東西,將僅取決於任務何時啟動。

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