說起雙向加密,如果以前在.NET開發中弄過加/解密的朋友都不會陌生,常用的算法有DES、AES等。在RT應用程序中,也提供了加密相關的API,算法自然是一樣的,只是API的封裝方式不同罷了,因為RT不完全是托管代碼,而又類似於COM的形式公開,這對於低端設備來說,性能可以提升,當然了,對於高端設備來說無所謂。
在WP的RT應用中,涉及到加/解密的API都在以下幾個命名空間里,大家要用的就在里面找,也不是所有類都會用得上,加密一般就用兩大類:需要恢復內容時選用雙向加密,如DES、AES等算法;如果不需要還原被加密的內容,就用大家嚴重熟悉的MD5等哈希算法。比如密碼。
1、Windows.Security.Cryptography
2、Windows.Security.Cryptography.Core
3、Windows.Security.Cryptography.DataProtection
其中,DataProtection下所用的是系統實現的算法來加密和解密數據,比較方便,但不方便傳輸,比較適合在本機使用,不適宜加密和解密通過網絡傳輸的加密數據,通用性不那么強。
今天先給大家簡單介紹一下雙向加密,我這個人性格比較壞,不喜歡一個類一個類地去介紹,然后列個表格說這個類有哪些屬性,方法之類的寫作方式。我比較BS那些老是抄MSDN的人。因此,不要指望我會機械式地給你講解,老周不喜歡這樣,老周向來對實例講述情有獨衷。
不過呢,一些必要的口水還是要的,不管你使用哪種算法來加密和解密數據,都要用到CryptographicEngine類,這個類人品值很高,是靜態的,加密解密時直接調用它的方法即可,不用new它的實例。加密時調用Encrypt方法,解密時調用Decrypt方法。
雙向加密通常要准備兩個東西,一個是密鑰Key,一個是初始向量iv,iv不是必須的,但key是不可少的。加密時用的key和iv,而在解密時也要用與加密時相同的key和iv才能解密。這個相信不用我廢話了,這是小學一年級的常識。
接下來說說步驟:
第一步,通過SymmetricKeyAlgorithmProvider的靜態方法OpenAlgorithm()得到一個SymmetricKeyAlgorithmProvider實例,方法參數是要使用的加/解密算法的名字,這個字符串不用我們去猜怎么寫,直接通過SymmetricAlgorithmNames的靜態屬性就能返回算法的相應名字。
SymmetricKeyAlgorithmProvider syprd = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.DesCbc);
第二步,創建key,其實key是一組字節,我這個例子是以DES算法為例,key是64位,即8個字節,這些字節怎么生成,大家自己發揮個人想象力吧,為了簡單,我直接用12345678來充當這8個字節。
// 表示Key的字節數組 byte[] keyBtArray = { 1, 2, 3, 4, 5, 6, 7, 8 }; // 表示初始向量(iv)的字節數組 byte[] ivBtArray = { 1, 2, 3, 4, 5, 6, 7, 8 }; // 表示加/解密的密鑰的對象 CryptographicKey myKey = null;
產生key的方法是調用剛才創建的SymmetricKeyAlgorithmProvider實例的CreateSymmetricKey方法。這里我先給大家說明一個情況。由於RT API里面在處理字節緩沖區時常用到IBuffer,實現接口類型為Buffer類。故.net的API中為byte[]定義了一個擴展方法,通過AsBuffer方法可以產生Buffer對象。
IBuffer keybuffer = keyBtArray.AsBuffer();
myKey = syprd.CreateSymmetricKey(keybuffer);
第三步,加密。加密很簡單,直接調用CryptographicEngine.Encrypt方法就可以了,返回的是加密后的數據。
// 進行加密 this.cryptBuffer = CryptographicEngine.Encrypt(myKey, txtBuffer, ivBtArray.AsBuffer());
第四步,解密。解密也是簡單地調用。
// 解密 IBuffer decryptBuffer = CryptographicEngine.Decrypt(myKey, this.cryptBuffer, ivBtArray.AsBuffer());
本例子是讓用戶在TextBox中輸入文本,先將文本加密,然后再解密,並顯示解密后的文本。
<StackPanel> <StackPanel.Resources> <Style TargetType="TextBlock"> <Setter Property="FontSize" Value="22"/> </Style> </StackPanel.Resources> <TextBlock Text="請輸入待加密內容:"/> <TextBox Name="txtInput"/> <Button Margin="0,25,0,0" Content="加密" Click="OnEncryptClick"/> <Button Click="OnDecryptoClick">解密</Button> <TextBlock Margin="0,25,0,0" Text="解密后:"/> <TextBlock Name="tbDecrypto" FontSize="28" Foreground="SkyBlue"/> </StackPanel>
private async void OnEncryptClick(object sender, RoutedEventArgs e) { // 將輸入的文本轉換為字節緩沖區 IBuffer txtBuffer = CryptographicBuffer.ConvertStringToBinary(txtInput.Text, BinaryStringEncoding.Utf8); Button b = sender as Button; b.IsEnabled = false; // 進行加密 this.cryptBuffer = CryptographicEngine.Encrypt(myKey, txtBuffer, ivBtArray.AsBuffer()); Windows.UI.Popups.MessageDialog msgdlg = new Windows.UI.Popups.MessageDialog("加密完成。"); await msgdlg.ShowAsync(); b.IsEnabled = true; } private async void OnDecryptoClick(object sender, RoutedEventArgs e) { Button b = sender as Button; b.IsEnabled = false; // 解密 IBuffer decryptBuffer = CryptographicEngine.Decrypt(myKey, this.cryptBuffer, ivBtArray.AsBuffer()); tbDecrypto.Text = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, decryptBuffer); Windows.UI.Popups.MessageDialog msgbox = new Windows.UI.Popups.MessageDialog("解密完成。"); await msgbox.ShowAsync(); b.IsEnabled = true; }
要將文本轉換為Buffer,可以用CryptographicBuffer.ConvertStringToBinary方法;反過來可以用CryptographicBuffer.ConvertBinaryToString,編碼方式一般用utf-8,這樣通用性好。
似乎一切就緒,但動行后,在加密時會發生異常,提示輸入的緩沖區無效。這個錯誤很多人都遇到,我看到在MSDN社區上有不少朋友提問,其他社區上也有,不管用的DES還是AES算法。為什么加密時會出錯呢?
那是因為加密處理的字節塊沒有對齊導致的。可以用以下代碼來獲得某種加密算法的塊大小。
System.Diagnostics.Debug.WriteLine("塊大小:" + syprd.BlockLength);
就是SymmetricKeyAlgorithmProvider實例的BlockLength屬性,DES算法輸出以下結果:
8就是8個字節,如果要加密的數據的字節總數不是8的倍數的話就會出錯,如果被加密的數據大小為16字節,可以被8整除,不會出錯,如果是23,不能被8整除,就會發生異常。
好,找到原因了,解決起來就有針對性了,一種方法是你自己動手,想辦法把被加密的數據的長度弄成8的倍數。比如23字節,你就想辦法加一個字節,讓它變成24個字節。
其實嘛,有一種方法更簡單,就是讓算法自己去填充,方法是在new出SymmetricKeyAlgorithmProvider實例,我們原來用的是SymmetricAlgorithmNames.DesCbc,把它改為SymmetricAlgorithmNames.DesCbcPkcs7就行了。因為Pkcs7模式會自動填充字節塊。
SymmetricKeyAlgorithmProvider syprd = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.DesCbcPkcs7);
這樣一改,加密時就不會出錯,因為字節塊被自動填充。
看看運行結果:
AES的加密解密也與DES類似。
看看時間,差不多開飯了,先說到這里吧,下一篇咱們聊聊單向加密吧。
源碼下載:http://files.cnblogs.com/files/tcjiaan/CryptoApp.zip