2011-11-17 26 views
2

我試圖加密XML,並解密後,我結束了1個字節太多 - 可能是因爲填充。這是我的代碼。我怎樣才能改變這個使它工作?解密後無法打開xml 1個字節到很多?

public byte[] encryptData(byte[] source,string key) 
{ 
    byte[] btKeyInBytes = UTF8Encoding.UTF8.GetBytes(key); 
    Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(key, btKeyInBytes); 

    AesManaged encryptor = new AesManaged(); 
    encryptor.Padding = PaddingMode.Zeros; 

    using (MemoryStream encryptStream = new MemoryStream()) 
    { 
     using (CryptoStream encStream = new CryptoStream(encryptStream, encryptor.CreateEncryptor(rfc.GetBytes(16), rfc.GetBytes(16)), CryptoStreamMode.Read)) 
     { 
      //Read from the input stream, then encrypt and write to the output stream. 
      encStream.Write(source, 0, source.Length); 
      encStream.FlushFinalBlock(); 
      encryptor.Clear(); 
     } 
     encryptStream.Flush(); 
     encryptedSource = encryptStream.ToArray(); 
    } 
    return encryptedSource; 
} 

public byte[] decryptData(byte[] source, string key) 
{ 
    byte[] encryptedSource = null; 

    byte[] btKeyInBytes = UTF8Encoding.UTF8.GetBytes(key); 
    Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(key, btKeyInBytes); 

    AesManaged encryptor = new AesManaged(); 
    encryptor.Padding = PaddingMode.Zeros; 

    using (MemoryStream encryptStream = new MemoryStream()) 
    { 
     using (CryptoStream encStream = new CryptoStream(encryptStream, encryptor.CreateDecryptor(rfc.GetBytes(16), rfc.GetBytes(16)), CryptoStreamMode.Write)) 
     { 
      //Read from the input stream, then encrypt and write to the output stream. 
      encStream.Write(source, 0, source.Length); 
      encStream.FlushFinalBlock(); 
      encryptor.Clear(); 
     } 
     encryptStream.Flush(); 
     encryptedSource = encryptStream.ToArray(); 
    } 

    return encryptedSource; 
} 

看來,填充給我解密

+0

一個字節是否爲''\ 0''?你不能把這些剝掉嗎?我認爲,否則你將不得不在某個地方,整個文件或最後一個加密塊中存儲一個預期的長度。或者你可以將數據包裝在其他東西中,例如一個gzip流,它將包含正確的長度。爲什麼這一個字節會阻止你打開XML? – Rup

回答

1

我明白了!

現在讓我們試着解釋。

比方說,我有一個927字節的文件。

我所做的就是讀取這個文件並將其分成656個字節。這個656字節的字節數組正在被加密。第二個數組將是271個字節。

在每個加密塊中,我都使用了padding。解密時,您將無法知道使用哪個塊填充,因爲每個塊現在可以被16除(因爲加密填充)。基本上我只想要填充用於最後一個塊(271)。

,所以這是我的新代碼:

public byte[] encryptData(byte[] source, string key, bool padding) 
{ 
    byte[] encryptedSource = null; 


    byte[] btKeyInBytes = UTF8Encoding.UTF8.GetBytes(key); 
    Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(key, btKeyInBytes); 

    AesManaged encryptor = new AesManaged(); 
    //encryptor.Mode = CipherMode.CFB; 
    encryptor.KeySize = 128;   // in bits  
    encryptor.Key = new byte[128/8]; // 16 bytes for 128 bit encryption  
    encryptor.IV = new byte[128/8]; 
    if (padding) { encryptor.Padding = PaddingMode.PKCS7; } 
    else { encryptor.Padding = PaddingMode.None; } 


    using (MemoryStream encryptStream = new MemoryStream()) 
    { 
     using (CryptoStream encStream = 
        new CryptoStream(encryptStream, 
            encryptor.CreateEncryptor(rfc.GetBytes(16), 
                   rfc.GetBytes(16)), 
            CryptoStreamMode.Write)) 
     { 
      //Read from the input stream, then encrypt and write to the output stream. 
      encStream.Write(source, 0, source.Length); 
     } 
     encryptStream.Flush(); 
     encryptedSource = encryptStream.ToArray(); 
    } 
    return encryptedSource; 
} 

public byte[] decryptData(byte[] source, string key,bool padding) 
{ 
    byte[] encryptedSource = null; 

    byte[] btKeyInBytes = UTF8Encoding.UTF8.GetBytes(key); 
    Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(key, btKeyInBytes); 

    AesManaged encryptor = new AesManaged(); 
    encryptor.Key = new byte[128/8]; // 16 bytes for 128 bit encryption  
    encryptor.IV = new byte[128/8]; 
    if (padding) { encryptor.Padding = PaddingMode.PKCS7; } 
    else { encryptor.Padding = PaddingMode.None; } 


    using (MemoryStream encryptStream = new MemoryStream()) 
    { 
     using (CryptoStream encStream = 
       new CryptoStream(encryptStream, 
            encryptor.CreateDecryptor(rfc.GetBytes(16), 
                  rfc.GetBytes(16)), 
            CryptoStreamMode.Write)) 
     { 
      //Read from the input stream, then encrypt and write to the output stream. 
      encStream.Write(source, 0, source.Length); 
     } 
     encryptStream.Flush(); 
     encryptedSource = encryptStream.ToArray(); 

    } 

    return encryptedSource; 
} 

我希望這有助於!

+0

好的,**爲什麼**你是否將文件分割成656字節的塊? (爲什麼這個奇怪的數字是16·41,爲什麼呢?) –

+0

我在biztalk中使用這個代碼作爲管道組件。爲了避免內存不足的情況,我會以塊的形式加密和解密。基本上它可以是任何數字,你可以用16除。 – user1052042

+0

你可以使用流形式的CryptoStream類(即不與MemoryStream底層的)並且總是隻寫一些字節,你不必爲每個字節創建一個新的塊。然後,流本身將負責僅發送完整塊。或者,對每條消息使用PKCS#7填充(並使用MAC)。 –

1

在1個額外的字節。如果你的問題是填充,然後PaddingMode.Zeros是關於最糟糕的選擇,因爲零不能總是被可靠地去除。最好使用PKCS7填充。

系統之間的行尾編碼也可能發生改變。有些系統使用一個字節,而其他系統使用兩個字節。正如@Rup所建議的,您真的需要逐字節地查看解密文件中的內容。

+0

對於XML加密,刪除尾部零應該沒有問題,因爲它們在最後不被允許。雖然你是對的,但PKCS#7填充是一個更好的主意。 –

+0

感謝您的幫助!最後一個字節是0.當我更改代碼填充PKCS7我得到:填充是無效的,不能用PaddingMode.Zeros刪除我沒有得到任何異常。 – user1052042

+0

什麼填充模式用於加密?兩端填充必須相同。 – rossum