2010-07-11 48 views
4

被加密玩弄和解密文件在VC#速成2010年C#文件加密和解密的問題

我見過的所有教程和文件要求,以加密文件2個FileSteams。一個用於讀取未加密的版本,另一個用於加密。當我實際編寫代碼時,它一直拋出一個錯誤,告訴我它無法打開文件,因爲它是由輸出文件流中的另一個進程打開的。

我假設這是因爲該文件是由輸入文件流打開。那意味着我必須指定一個不同的文件名?所以,即使操作成功後,我會知道目錄中有原始未加密文件和單獨的加密版本嗎?這是否不利於這一點?或者我在這裏做錯了什麼?我的代碼與此類似...

public string filename = "test.xml"; 
using(FileStream input = new FileStream(filename, FileMode.Open, FileAccess.Read)) 
using(FileStream output = new FileStram(filename, FileMode.Open, FileAccess.Write)) 
using(....all the crypto stream and transform stuf...) 
{ 
    ...do the encryption.... 
} 

回答

0

使用File.ReadAllBytes。然後這些字節發佈到您的加密器,必須工作。

3

你是對的,但它並沒有破壞這一點。 (流式)加密API旨在從Src加密到Dst。認爲通過網絡發送/接收時對輸出進行加密等。這使得它們變得簡單,就像它們應該那樣。

您通過對Src和Dst使用相同的文件使問題複雜化。這並非完全不可能,但像拷貝文件一樣,它需要特別小心。

考慮到通常情況下,加密會增加文件大小。所以加密文件是不安全的。解密可能會,但我不會冒險。

你需要的是一個Temp文件和完成後的重命名操作。

+0

這引發了另一個問題:如果攻擊者可以訪問正在運行的計算機,則您的文件不安全。如果要加密文件,則必須確保未加密的字節不會觸碰硬盤。如果你用單詞開啓你的超級祕密商業計劃,那麼各種臨時文件將被寫入你永遠無法清理的驅動器中。如果你正在尋找保護文件,你真的需要整個驅動器加密。 – TwentyMiles 2010-07-12 15:38:51

1

在你的例子中,你不能在同一個文件上爲輸入和輸出創建一個單獨的文件流,但你可以創建一個將讀寫的句柄。 FileAccess枚舉具有flags屬性,所以你只能說var handle = new FileStream(filename, FileAccess.Read | FileAccess.Write);這個明顯的缺點是如果你的加密沒有成功完成,你將會丟失數據。

我建議爲輸出提供一個單獨的文件,但至少如果程序意外斷開,您不會丟失數據。如果加密成功完成,則刪除原始文件並用原始文件名重命名加密文件。

+0

這是其他文件加密應用程序的工作原理嗎?在加密操作之後,我從未看到未加密源的殘餘副本。我應該輸出到臨時文件....創建一個if語句來監視操作是否成功,然後如果成功,那麼刪除原始文件並重命名臨時文件以替換它?這確保數據不會丟失? – Stev0 2010-07-11 17:26:19

+0

這是大多數應用程序在當天工作的方式。我現在不確定。臨時文件通常會被設置爲隱藏,並且可能位於磁盤上的臨時文件夾中。文件系統加密中使用了同樣的想法 - 如果要將文件移動到加密文件系統,則在移動成功完成之前,原始文件不會被刪除。您必須以某種方式保留原始數據,直到您知道加密成功完成爲止,因爲它可能很簡單,比如內存不足或導致應用程序失敗的完整磁盤。 – 2010-07-11 18:11:15

+0

如果你真的需要回收現有的文件,我建議讀取固定的塊大小(比如4096kb的東西 - 這將很容易適應內存)。如果,並且只有每個塊成功完成,纔會覆蓋原始塊,但是如果不是,則將日誌文件輸出到文件加密位置,以及任何可能的數據以幫助恢復。 (即初始化向量,鍵,錯誤原因)。 – 2010-07-11 18:13:52

0

還有另外一個參數,你可以指定是否允許其他進程讀取或寫入文件

中openFile是文件名,字符串類型。

using (FileStream fileIn = new FileStream(openFile, FileMode.Open, FileAccess.Read, FileShare.Write)) 
using (FileStream fileOut = new FileStream(openFile, FileMode.Open, FileAccess.Write, FileShare.Open)) 

這樣,您可以讀取和寫入同一個文件。

while (myfileStream.Position < fileLength) 
{ 

    fileIn .Read(buffer, 0, 51200); 

    buffer = encrypt(buffer); 

    fileOut .Write(buffer, 0, 51200);     


} 

雖然這是容易的,你不必寫一個臨時文件或具有移動/重命名等,這可能是非常危險的地方,如果加密斷裂突然因爲某種原因,你會丟失數據! A

此外,加密功能是我實施的東西。可以使用AesCryptoServiceProvider以及CryptoStream :)

+1

我認爲你的條件已經壞了。但更糟糕的是,fileOut的位置將開始超過fileIn的位置,並且您的文件將無法修復而出現亂碼。 – 2010-07-11 08:37:42

+0

@亨克:是的。你是對的。但問題出在移動設備上,如果有人想要加密一個500MB文件,由於資源限制,創建另一個500MB文件將是不可能的。我承認這是危險的,可能是錯誤的,但這種情況必須爲資源受限設備完成,對吧?還有其他方法嗎? :) – 2010-07-11 08:41:27

+1

該OQ不提移動,所以你在這裏延伸問題。您可以通過向混音添加壓縮來解決沒有臨時文件的情況。但這並不能保證(如果Src文件不夠可壓縮,即已經壓縮,它將會中斷)。 – 2010-07-11 08:46:24