隨機存取流密碼
前段時間,我在一個寵物項目中為一種數據庫引擎工作。而且我考慮過用加密來保護磁碟中的數據..並且由於主要程式碼已經開發..我有一些要求..
- 一個簡單的流類,我可以掛鉤而不是我的文件流
- 支持隨機訪問(在隨機位置讀/寫)
- 能夠在任何字節位置工作(因為數據可能未對齊)
- 僅加密/解密請求的數據,而不是所有文件,(因為文件可能有幾 MB)
- 快速加密/解密,因為這是針對數據庫系統的
我在網上沒有找到有關此的資訊或此類程式碼的實現。普通流密碼不支持隨機訪問/查找,分組密碼要求數據對齊並固定在塊中。所以我考慮開發自己的。我知道開發自己的加密總是一個糟糕的選擇..但這是一種理論練習..
所以我想向您展示程式碼..只是從安全的角度來看我有多遠
首先,使用密碼初始化流。但該密碼本身不用於加密。它被用作種子來打亂一個包含 256 個值的數組,以希望增加密鑰空間
public CipherStream(String sKey,Stream oStream) { _oStream = oStream; //initialize key space _oVector = new byte[256]; for(int i = 0; i <= 255; i++) _oVector[i] = (byte)i; //shuffle the keyspace for (int i = 0; i <= 255; i++)//shuffle the box { //shuffle this item with other //other is chosen by char(i) of password //and the currently shuffling vector(I) // this means that even repeating passwords 'aaaaaa' will produce random results int j = ((sKey[i % sKey.Length]) + _oVector[i]) % 256; byte cTemp = _oVector[i]; _oVector[i] = _oVector[j]; _oVector[j] = cTemp; } }
在此之後,我們所要做的就是為我們試圖讀/寫的位置選擇密碼字節。在我的實現中,我使用了 xor,我知道這不是最安全的。但這是可以改變的不是算法的核心..
public override void Write(byte[] buffer, int offset, int count) { long nPosition = this.Position; for (int i = offset; i < count; i++) { byte oPlain = buffer[i]; byte nKey = GetKey(nPosition); byte oCypher = (byte)(oPlain ^ nKey); buffer[i] = oCypher; nPosition++; } _oStream.Write(buffer, offset, count); }
字節的“密鑰”是根據我們嘗試訪問的位置從密鑰向量中選擇的。進行計算以便沒有重複,並且選擇的值盡可能隨機
private byte GetKey(long nPosition) { byte nOffset = _oVector[nPosition % _oVector.Length]; byte nOffset2 = _oVector[(nPosition / (nOffset + 1)) % _oVector.Length]; int nDif = nOffset - nOffset2; if (nDif < 0) nDif += 255; byte nKey = (Byte)(nDif % 256); return nKey; }
我確實嘗試將流渲染為點陣圖..只是確保沒有明顯的模式..並在那裡做了一些微調..看起來沒問題..
我能描述的最好的算法是一個“確定性可預測的偽隨機生成器”,我可以問“給我第 n 個隨機數”,種子是一個 2048 位向量,用密碼隨機初始化。
我離解決方案還有多遠?這完全不安全嗎?或者甚至沒有嘗試的意義,因為這個“隨機訪問流”問題沒有解決方案?
這個想法
‘確定性可預測的偽隨機生成器’,我可以問’給我第 n 個隨機數’
是已知的,並且有一些像這樣工作的流密碼(如分組密碼的 CTR 模式,或Salsa /ChaCha 流密碼系列)。通常它們不會產生單個字節,而是一些更大的連續密鑰流字節塊,如果您沒有要加密的單個字節,效率會更高,並且(如 user4982 的回答所述)不會限制您,因為您不必使用所有這些密鑰流字節來加密/解密您的數據。
我不會查看您的特定密碼(對我來說程式碼級別太多了),但它可能不是一個安全的密碼。
這個想法本身(即使使用完全安全的流密碼實現)在用於隨機訪問文件加密時存在問題:您將(在幾個時間點)使用相同的密鑰流加密不同的數據,然後如果潛在的攻擊者可以在不同的時間點查看您的加密文件,則會導致兩次填充問題。
您需要使用新的初始化向量重新加密較大的塊以避免這種情況。