簡體   English   中英

使用.NET中的OpenSSL加密和解密文件

[英]Encrypting & Decrypting files using OpenSSL in .NET

我在我的C#項目中使用OpenSSL Crypto庫來加密/解密文件。 這是我的代碼:

byte[] key = System.Text.Encoding.ASCII.GetBytes("password");

byte[] iv = System.Text.Encoding.ASCII.GetBytes("1234");


OpenSSL.Crypto.CipherContext cc = new OpenSSL.Crypto.CipherContext(
    OpenSSL.Crypto.Cipher.AES_256_ECB);

FileStream fIn = new FileStream("C:\\file.txt", FileMode.Open, 
    FileAccess.Read);
FileStream fOut = new FileStream("C:\\encrypted.txt", FileMode.OpenOrCreate,
    FileAccess.Write);
fOut.SetLength(0);

byte[] bin = new byte[100];
long rdlen = 0;
long totlen = fIn.Length;
int len;

DateTime start = DateTime.Now;
while (rdlen < totlen)
{
    // argument 1
    len = fIn.Read(bin, 0, 100);         
    // argument 2
    fOut.Write(cc.Crypt(bin,key,iv,true),0,100);                 
    rdlen = rdlen + len;
}

fOut.Flush();  
fOut.Close();
fIn.Close();

結果我得到了這個例外:

偏移量和長度超出了數組的范圍,或者計數大於從索引到源集合末尾的元素數。

當我將參數1和2的值從100更改為64(bin仍然總是字節[100])它工作時,文件被加密和解密但是解密文件的大小比原始文件大並且包含1或2文本文件末尾有更多行。

我不知道庫,但這里的一個問題是你用256位= 32字節的塊大小加密100字節的塊。 你的塊應該是32個字節的倍數。 文件末尾的額外字節可能只是將最后一個塊舍入到32個字節。

正如Philip的回答一樣,崩潰的可能原因是Write中的硬編碼100。 Crypt函數將從它正在加密的最后一個塊中撤回32,64或96個字節中的一個,這些都是100個。(在100字節的情況下,有可能你的數據被填充到128字節加密和所以當你只寫100時,你會丟失最后一個塊的最后28個字節。)

  1. 你在ECB模式下傳入IV - 你不需要這個
  2. 通過反復調用Crypt你可能每100個字節進行一次密鑰設置。 這是低效的; 你只需要在加密開始時做一次。 您應該尋找一種方法來使用密鑰(以及其他模式中的IV)初始化類,然后將其提供給數據塊以立即加密,而不是每次都使用密鑰來調用Crypt。 我不知道這個庫中會有什么,但它應該存在。 就目前而言,你也不能使用CBC或任何類似的模式,因為你將每隔100個字節而不是一次寫入IV而不是在相鄰的100字節塊之間鏈接最后一個塊。
  3. 如果你想使用Crypt,為什么不立刻將文件加載到內存中? 我意識到這不會擴展到千兆字節的數據,但它可能在您的正常用例中。 或者至少選擇更大的數據大小,例如256k。 但是,如果你超過一個街區,你仍然會面對重復的關鍵設置/破壞的CBC。

當您對fIn.Read(...)調用指定100時,您說“讀取最多 100個字節” - 請注意實際的字節數可能不同; 您應該使用返回值來確定實際讀取的數量。

在調用fOut.Write ,假設cc.Crypt(bin,key,iv,true)的輸出正好是100個字節,這不是一個有效的假設。 另請注意,即使您只從文件中讀取1,也始終加密所有100個字節的bin 如果你的讀數低於100,那么你將加密bin中的“遺留”(可能是0,除非以前使用過)。

解決這些長度問題,你應該走在正確的軌道上。 就像是:

while (rdlen < totlen)
{
    len = fIn.Read(bin, 0, 100);         
    // note that we are encrypting all of "bin" here, may want to only 
    // encrypt "len" bytes..
    byte[] encrypted = cc.Crypt(bin, key, iv, true);
    fOut.Write(encrypted, 0, encrypted.Length);                 
    rdlen = rdlen + len;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM