对称加密(4) NET对称加密实践
對稱加密(4) NET對稱加密實踐
?
在使用.NET框架提供的加密算法實現類來執行加密任務時,需要準備加密密鑰和初始化向量(Initialization Vector,IV)。基于對稱加密的特點,在加密數據之后一定要保存好密鑰和初始化向量,因為解密要用到它們。但是對于不同的數據加密,要使用不同的密鑰和初始化向量,理論上每次新的加密過程都應該使用全新的密鑰和初始化向量。
通常需要將加密密鑰和初始化向量傳遞給另一個人,這時候需要使用非對稱加密算法來加密密鑰和初始化向量,然后在網絡上傳輸。本節主要演示如何使用加密實踐類,更多的應用內容會在本書的第四部分介紹。
那么如何創建加密密鑰和初始化向量呢?有兩種基本方法,一種是使用加密算法實現類的構造函數,另一種是使用GenerateIV()和GenerateKey()方法生成密鑰和初始化向量。
使用構造函數創建密鑰和初始化向量
先測試構造函數的方法,如代碼清單6-5。
代碼清單6-5? 使用構造函數創建密鑰和初始化向量
using System;
using System.Text;
using System.Security.Cryptography;
namespace Encription
{
??? classProgram
??? {
??????? staticvoid Main(string[] args)
??????? {
??????????? AesCryptoServiceProvider acsp = new AesCryptoServiceProvider();
??????????? WriteKeyAndIV(acsp);
??????????? AesManaged am = newAesManaged();
??????????? WriteKeyAndIV(am);
??????????? DESCryptoServiceProvider dsp = new DESCryptoServiceProvider();
??????????? WriteKeyAndIV(dsp);
??????????? TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider();
??????????? WriteKeyAndIV(tdsp);
??????????? RijndaelManaged rm = new RijndaelManaged();
??????????? WriteKeyAndIV(rm);
??????????? Console.Read();
??????? }
??????? staticvoid WriteKeyAndIV(SymmetricAlgorithm sa)
??????? {
??????????? Console.WriteLine(GetStringFromByte(sa.Key));
??????????? Console.WriteLine("*******");
??????????? Console.WriteLine(GetStringFromByte(sa.IV));
??????????? Console.WriteLine("--------------------------");
??????? }
??????? staticstring GetStringFromByte(byte[] bytes)
??????? {
??????????? string s="";
??????????? for (int i = 0; i < bytes.Length; i++)
??????????? {
??????????????? s += bytes[i].ToString()+" ";
??????? ????}
??????????? return s;
??????? }
??? }
}
以上代碼中一共有三個方法,Main方法用來初始化.NET提供的5種對稱加密實例;WriteKeyAndIV方法用來輸出每個實例的密鑰和初始化向量;GetStringFromByte方法用來輸出byte數組的原始值。現在看輸出結果,是不是如預料的,已經初始化了加密密鑰和初始化向量呢?如圖6-11所示。
?
圖6-11? 代碼清單6-5輸出結果
如圖6-11所示,在控制臺輸出了每個加密實例的密鑰和初始化向量。
使用GenerateIV()和GenerateKey()方法
當需要多個密鑰或者多個初始化向量的時候,就要采用GenerateIV()和GenerateKey()方法。下面對代碼清單6-5做簡要的修改,如代碼清單6-6所示。
代碼清單6-6? 使用GenerateIV()和GenerateKey()方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
namespace Encription
{
??? classProgram
??? {
??????? staticvoid Main(string[] args)
??????? {
??????????? AesCryptoServiceProvider acsp = new AesCryptoServiceProvider();
??????????? WriteKeyAndIV(acsp);
??????????? acsp.GenerateIV();
???? ???????acsp.GenerateKey();
??????????? WriteKeyAndIV(acsp);
??????????? Console.Read();
??????? }
??????? staticvoid WriteKeyAndIV(SymmetricAlgorithm sa)
??????? {
??????????
??????????? Console.WriteLine(GetStringFromByte(sa.Key));
??????????? Console.WriteLine("*******");
??????????? Console.WriteLine(GetStringFromByte(sa.IV));
??????????? Console.WriteLine("--------------------------");
??????? }
??????? staticstring GetStringFromByte(byte[] bytes)
??????? {
??????????? string s="";
??????????? for (int i = 0; i < bytes.Length; i++)
??????????? {
??????????????? s += bytes[i].ToString()+" ";
??????????? }
??????????? return s;
??????? }
??? }
}
?? 修改很簡單,Main方法中只保留了AesCryptoServiceProvider實例,再初始化該實例后,又調用它的GenerateIV和GenerateKey方法,看是否產生了新的加密密鑰和初始化向量。結果如圖6-12所示。
圖6-12? 代碼清單6-6運行結果
如圖6-12所示,可以看到使用GenerateIV和GenerateKey方法后,生成了新的密鑰和初始化向量。
?? 準備工作完成了,下面要開始真正的加密之旅了。對稱加密需要和CryptoStream類的實例配合,使用加密流來實現數據加密(.NET中的內存流、文件流、網絡流都可以使用)。為了示例更明了,以AesCryptoServiceProvider類為例,使用內存流來演示如何使用對稱加密類加密、解密數據。先看代碼清單6-7。
代碼清單6-7? 加密解密數據示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
namespace Sample
{
??? classProgram
??? {
??????? staticAesCryptoServiceProvider acsp = newAesCryptoServiceProvider();
??????? staticvoid Main(string[] args)
??????? {
??????????? byte[] key = acsp.Key;
??????????? byte[] iv = acsp.IV;
??????????? string s = @"xuanhun加密測試";
??????????? byte[] sbyt = Encoding.Default.GetBytes(s);
??????????? byte []Enb = Encript(sbyt, key, iv);
??????????? byte []Deb = Decript(Enb, key, iv);
??????????? Console.WriteLine(Encoding.Default.GetString(Enb));
??????????? Console.WriteLine(Encoding.Default.GetString(Deb));
??????????? Console.Read();
??????? }
?
??????? publicstaticbyte[] Encript(byte[] s1, byte[] key, byte[] iv)
??????? {
?????????
???using?(MemoryStream?msEncrypt?=?new?MemoryStream()) ????????????
{ ????????????????using?(CryptoStream?csEncrypt?=?new?CryptoStream(msEncrypt,?acsp.CreateEncryptor(key,?iv),?CryptoStreamMode.Write)) ????????????????{ ???????????????????
?using?(StreamWriter?swEncrypt?=?new?StreamWriter(csEncrypt)) ???????????????????
?{ ????????????????????????//Write?all?data?to?the?stream. ???????????????????????
?var?s?=?Convert.ToBase64String(s1); ??????????????????????
??swEncrypt.Write(s); ????????????????????
} ????????????????????
??byte[]?outb1??=?msEncrypt.ToArray(); ?????????????????????
?return?outb1; ?????????????
???} ???????????
?}
??????? }
?
??????? publicstaticbyte[] Decript(byte[] s2, byte[] key, byte[] iv)
??????? {
???????????
????using?(MemoryStream?msDecrypt?=?new?MemoryStream(s2)){using?(CryptoStream?csDecrypt?=?new?CryptoStream(msDecrypt,?acsp.CreateDecryptor(key,?iv),?CryptoStreamMode.Read)){using?(StreamReader?srDecrypt?=?new?StreamReader(csDecrypt)){var?s=?Convert.FromBase64String(srDecrypt.ReadToEnd());return?s;}}}??????? }
?
??????? publicstaticbyte[] GetByteFromstring(string s)
??????? {
??????????? returnEncoding.Default.GetBytes(s);
??????? }
??? }
}
以上代碼首先創建了AesCryptoServiceProvider實例,然后在Main方法中使用了局部變量key和iv來保存該實例的加密密鑰和初始化向量,字符串s是要加密的原始字符串。局部變量sbyte保存了將字符串s轉化為byte數組后的結果。加密解密過程都是圍繞該byte數組進行的。
? Main方法中調用兩個靜態方法Encript和Decript方法,分別用來實現加密和解密。在Encript方法中,首先初始化內存流MemoryStream的實例mstream,然后以mstream為參數創建CryptoStream實例。CryptoStream構造函數需要3個參數:第一個是流實例,第二個是加密或者解密器,在加密函數中使用CreateEncryptor方法做參數,在解密方法中使用CreateDecryptor做參數;CreateEncryptor和CreateDecryptor方法需要傳入準備好的加密密鑰和初始化向量。第三個參數是CryptoStreamMode枚舉,該枚舉有兩個值Write和Read,用來指示流的操作。比如在網絡流中,加密并輸出數據時要設置Write屬性,接收并解密的一方要設置Read屬性。本例中把加密和解密的數據都寫入內存流,所以都設置了Write屬性。在初始化CryptoStream實例之后,調用該實例的Write方法,將加密后的數據寫入內存流。然后再調用內存流的ToArray方法讀出加密數據,返回到Main方法中,通過Encoding.Default.GetString方法,獲得加密后的字符串。解密過程與此類似,不再贅述。
現在看改程序的運行結果,如圖6-13所示。
圖6-13? 代碼清單6-7運行結果
如圖6-7所示,已經成功實現了簡單的對稱加密解密過程。.NET中的其他對稱加密實現類的使用方法與此類似。
?
----------------------注:本文部分內容改編自《.NET安全揭秘》
?
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的对称加密(4) NET对称加密实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#基础知识整理:基础知识(1) Mai
- 下一篇: ASP数据库插马小议