[C#.NET] 利用 DES / AES 演算法加解密
来源:互联网 发布:网络mg老虎机技巧 编辑:程序博客网 时间:2024/05/21 19:49
維基對這兩種演算法的說明
http://zh.wikipedia.org/zh-hant/%E8%B3%87%E6%96%99%E5%8A%A0%E5%AF%86%E6%A8%99%E6%BA%96
在.NET裡
DES 演算法會用到 DSACryptoServiceProvider 類別
AES 演算法
2.0:RijndaelManaged 類別 (AES又叫Rijndael)
3.5:除了原本的 RijndaelManaged 類別 還多了 AesCryptoServiceProvider 類別,這兩個類別產生的結果相同。
AES與DES這兩種加密演算法都需要KEY與IV,AES/DES類別都有以下兩種屬性,必需要依照規則丟固定長度的Bit
- LegalBlockSizes是表示IV的容許長度,單位Bit
- LegalKeySizes表示KEY的容許長度,單位Bit
為了方便講解,我整理出下表:
PS.1 Byte=8 Bit, 所以 128 Bit = 16 Byte, 256 Bit = 32 Byte
所以我們在餵KEY跟IV的時候,就會有長度限制的問題要注意
接下來我們來看範例
下段比較值得注意的是編碼的部份,
1.下段是用Encoding.UTF8.GetBytes(source)來取得原始資料的Byte,所以解密的時候也要用Encoding.UTF8
2.另外加密後的Byte Convert String是用Convert.ToBase64String所以解密的時候也要用相對應的方式來處理
總之,要對應就對了
private string desEncryptBase64(string source){ DESCryptoServiceProvider des = new DESCryptoServiceProvider(); byte[] key = Encoding.ASCII.GetBytes("12345678"); byte[] iv = Encoding.ASCII.GetBytes("87654321"); byte[] dataByteArray = Encoding.UTF8.GetBytes(source); des.Key = key; des.IV = iv; string encrypt = ""; using (MemoryStream ms = new MemoryStream()) using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)) { cs.Write(dataByteArray, 0, dataByteArray.Length); cs.FlushFinalBlock(); encrypt = Convert.ToBase64String(ms.ToArray()); } return encrypt;}private string desDecryptBase64(string encrypt){ DESCryptoServiceProvider des = new DESCryptoServiceProvider(); byte[] key = Encoding.ASCII.GetBytes("12345678"); byte[] iv = Encoding.ASCII.GetBytes("87654321"); des.Key = key; des.IV = iv; byte[] dataByteArray = Convert.FromBase64String(encrypt); using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(dataByteArray, 0, dataByteArray.Length); cs.FlushFinalBlock(); return Encoding.UTF8.GetString(ms.ToArray()); } }}
執行結果如下:
再來看另外一資資料格式輸出,加密過程都一樣,只是資料產出的方式不一樣,也就是說,你可以依個人喜好選用不同的資料輸出樣式,參考之前寫過的,http://www.dotblogs.com.tw/yc421206/archive/2009/08/11/9984.aspx
private string desEncrypt(string source){ StringBuilder sb = new StringBuilder(); DESCryptoServiceProvider des = new DESCryptoServiceProvider(); byte[] key = Encoding.ASCII.GetBytes("12345678"); byte[] iv = Encoding.ASCII.GetBytes("87654321"); byte[] dataByteArray = Encoding.UTF8.GetBytes(source); des.Key = key; des.IV = iv; string encrypt = ""; using (MemoryStream ms = new MemoryStream()) using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)) { cs.Write(dataByteArray, 0, dataByteArray.Length); cs.FlushFinalBlock(); //輸出資料 foreach (byte b in ms.ToArray()) { sb.AppendFormat("{0:X2}", b); } encrypt = sb.ToString(); } return encrypt;}private string desDecrypt(string encrypt){ byte[] dataByteArray = new byte[encrypt.Length / 2]; for (int x = 0; x < encrypt.Length / 2; x++) { int i = (Convert.ToInt32(encrypt.Substring(x * 2, 2), 16)); dataByteArray[x] = (byte)i; } DESCryptoServiceProvider des = new DESCryptoServiceProvider(); byte[] key = Encoding.ASCII.GetBytes("12345678"); byte[] iv = Encoding.ASCII.GetBytes("87654321"); des.Key = key; des.IV = iv; using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(dataByteArray, 0, dataByteArray.Length); cs.FlushFinalBlock(); return Encoding.UTF8.GetString(ms.ToArray()); } }
}
加密字串跟Base64有很大的不同
接下來看看怎麼處理檔案,先準備好要處理的檔案
private void desEncryptFile(string sourceFile, string encryptFile){ if (string.IsNullOrEmpty(sourceFile) || string.IsNullOrEmpty(encryptFile)) { return; } if (!File.Exists(sourceFile)) { return; } DESCryptoServiceProvider des = new DESCryptoServiceProvider(); byte[] key = Encoding.ASCII.GetBytes("12345678"); byte[] iv = Encoding.ASCII.GetBytes("87654321"); des.Key = key; des.IV = iv; using (FileStream sourceStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read)) using (FileStream encryptStream = new FileStream(encryptFile, FileMode.Create, FileAccess.Write)) { //檔案加密 byte[] dataByteArray = new byte[sourceStream.Length]; sourceStream.Read(dataByteArray, 0, dataByteArray.Length); using (CryptoStream cs = new CryptoStream(encryptStream, des.CreateEncryptor(), CryptoStreamMode.Write)) { cs.Write(dataByteArray, 0, dataByteArray.Length); cs.FlushFinalBlock(); } }}private void desDecryptFile(string encryptFile, string decryptFile){ if (string.IsNullOrEmpty(encryptFile) || string.IsNullOrEmpty(decryptFile)) { return; } if (!File.Exists(encryptFile)) { return; } DESCryptoServiceProvider des = new DESCryptoServiceProvider(); byte[] key = Encoding.ASCII.GetBytes("12345678"); byte[] iv = Encoding.ASCII.GetBytes("87654321"); des.Key = key; des.IV = iv; using (FileStream encryptStream = new FileStream(encryptFile, FileMode.Open, FileAccess.Read)) using (FileStream decryptStream = new FileStream(decryptFile, FileMode.Create, FileAccess.Write)) { byte[] dataByteArray = new byte[encryptStream.Length]; encryptStream.Read(dataByteArray, 0, dataByteArray.Length); using (CryptoStream cs = new CryptoStream(decryptStream, des.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(dataByteArray, 0, dataByteArray.Length); cs.FlushFinalBlock(); } }}
檔案加密的效果
解密後的效果,基本上要跟source.txt一樣
若你看到這裡還不太懂,只要記住一點不管加解密什麼都是處理Byte就對了。
Q:加密的KEY或IV能用中文嗎?
A:當然可以呀,只要能符合長度就可以
Q:每次都要計算byte的長度,很煩人,怎麼辦?
A:可以利用以下類別產生符合規格的Byte
Rfc2898DeriveBytes 類別 / PasswordDeriveBytes 類別:不管你打再長的密碼都會經過 Salt 亂數處理,以符合規則
private void generatorRfc(){ byte[] salt = new byte[] { 0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xF1 }; byte[] key = Encoding.UTF8.GetBytes("我跟你說你不要跟別人說,你若跟別人說,不要跟別人說是我叫你不要跟別人說"); Rfc2898DeriveBytes rfcKey = new Rfc2898DeriveBytes(key, salt, 8); Rfc2898DeriveBytes rfcIv = new Rfc2898DeriveBytes("0987654321", salt, 8); byte[] keyData = rfcKey.GetBytes(8); byte[] IVData = rfcIv.GetBytes(8);}
RNGCryptoServiceProvider 類別:用它來幫你產生符合規則的長度
public static byte[] generatorRng(int length){ byte[] randBytes; if (length >= 1) { randBytes = new byte[length]; } else { randBytes = new byte[8]; } RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider(); rand.GetBytes(randBytes); return randBytes;}
Q:為什麼沒有AES的範例?
A:AES的用法跟DES一模一樣,在這裡就不多佔篇幅,AES比DES支援的長度還要長,所以它有比較多的選擇來處理KEY/IV,比如
SHA256CryptoServiceProvider 類別:將資料雜湊後產生32 Byte的資料
MD5CryptoServiceProvider 類別:將資料雜湊後產生16 Byte的資料
private void aes(){ MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider(); AesCryptoServiceProvider provider = new AesCryptoServiceProvider(); byte[] keyData = sha256.ComputeHash(Encoding.UTF8.GetBytes("我跟你說你不要跟別人說,你若跟別人說,不要跟別人說是我叫你不要跟別人說")); byte[] IVData = md5.ComputeHash(Encoding.UTF8.GetBytes("我跟你說你不要跟別人說,你若跟別人說,不要跟別人說是我叫你不要跟別人說")); provider.Key = keyData; provider.IV = IVData;}
這樣一來也就能處理掉長度的問題
Q:有更簡單的方法嗎?
A:當時可以,AES/DES初始化的時候就會自己產生KEY跟IV,只要將它產生的KEY/IV記下就好了
public void generatorKey(){ //var provider = new DESCryptoServiceProvider(); var provider = new AesCryptoServiceProvider(); var key = Convert.ToBase64String(provider.Key); var iv = Convert.ToBase64String(provider.IV);}
後記:
這篇主要是在介紹怎麼使用AES/DES,所以程式碼寫的很亂,重覆的地方相當的多,瞭解了AES跟DES的來龍去脈後,就能寫出屬於自己的加解密類別,當然,這部份重構就得靠自己來了。
- [C#.NET] 利用 DES / AES 演算法加解密
- AES/DES c加解密收藏
- iOS Objective-C 與 PHP DES 加解密演算法實作
- 对称加解密(DES+DES+AES)
- C#DES加解密
- C++DES加解密
- C#-DES加解密
- C#.NET 加密解密:AES/DES/Base64/RSA/MD5/SHA256
- C#.NET 加密解密:AES/DES/Base64/RSA/MD5/SHA256
- C#.NET 加密解密:AES/DES/Base64/RSA/MD5/SHA256
- c 实现aes加解密
- Objective-C AES加解密
- DES加解密+C实现
- 利用openssl中AES进行加解密
- android平台上AES,DES加解密及问题
- [JAVA加解密]DES,AES,Base64编码,PBE
- .net使用des方式加解密
- C 语言版 DES加解密算法
- 教你如何迅速秒杀掉:99%的海量数据处理面试题
- firewalld firewall-cmd
- Java中static
- 电容充放电
- BEGINNING SHAREPOINT® 2013 DEVELOPMENT 第13章节--使用业务连接服务创建业务线解决方案 SP Apps中的BCS
- [C#.NET] 利用 DES / AES 演算法加解密
- C语言各运算符优先级比较列表
- JQueryEasyUI信息管理实例
- iOS APNS远程推送证书的申请和制作——详细解析
- 搜索业务增速下滑 Google廉颇老矣?
- 在Ubuntu终端彻底删除软件方法
- Linux 进程操作细节
- 第四章 Backbonejs中的Router实践
- 随想录(强大的kprobe)