關於Windows Phone 中加密算法使用.最近一段時間很多做Windows Phone應用同學在微博上提了不少問題.其實在客戶端實際需求中大多都會涉及到數據基於加密算法的解析和加密.本篇幅針對Windows Phone數據加密算法的問題.給出一些解決方案.
首先有必要來說說為何會存在Windows Phone數據加密的問題.做過Silverlight的同學應該知道.在Silverlight 4版本 .NET類庫中基於System.Security.Cryptography命名空間下.保留了Aes加密算法.關於數據DES和TripleDES[3DES]加密算法已經不存在了.同樣在Windows Phone SDK 7.1.1最新版本中.也能夠看出除了SHA1和HMAC_SHA1對稱算法外.如果我們嘗試做MD5或對稱的HMAC_MD5加密操作發現官方的SDK並沒有提供類似支持的類. 如是問題就這么出現了.
如果需要在服務器端和和客戶端傳遞類似MD5、HMAC_MD5或是解析服務器端傳遞的DES、TripleDES[3DES]數據是發現現在Windows Phone針對數據加密和解析並沒有對應的支持.其實這些問題.原來都在我們團隊實際Coding過程都碰到過.也算是找到一些比較成熟的解決方案.如下.
本篇幅針對MD5,HMAC_MD5,DES,TripleDES[3DES]算法給出Windows Phone移植版本.
首先來說說MD5.
MD5[Message Digest Algorithm MD5]用於確保信息傳輸完整一致,在計算機廣泛使用的雜湊算法之一[又譯摘要算法、哈希算法].比較常見使用於保證數據完整性.MD5或者說HASH值是一種不可逆的算法.在.NET 4中也提供類似在System.Security.Cryptography.MD5命名空間下MD5CryptoServiceProvider 類的對應實現.針對Silverlight和WP對應版本不支持MD5的情況,微軟官方在archive.msdn上給出對應的MD5 Silverlight移植版本.[同樣使用於Windows Phone]:
Silverlight MD5 Implementation:
具體實現Code也可以參考GitHub上地址.這里不再贅述.
HMAC_MD5.
使用 MD5 哈希函數計算基於哈希值的消息驗證代碼 [HMAC].
HMACMD5 是從 MD5 哈希函數構造的一種鍵控哈希算法,被用作基於哈希的消息驗證代碼 [HMAC].此 HMAC 進程將密鑰與消息數據混合,使用哈希函數對混合結果進行哈希計算,將所得哈希值與該密鑰混合,然后再次應用哈希函數。輸出的哈希值長度為 128 位.
關於HMAC_MD5算法除了在Codeplex 上[http://hmacmd5.codeplex.com/] 找到HMACmd5 Codeplex已經在Windows Phone驗證通過外:
HMACMD5 For Silverlight/Windows Phone:
其他第三方方式均沒有驗證過.考慮該算法核心並不復雜.於是自己動手重寫一個基於Windows Phone 版本HMACMD5的實現[驗證通過]. 核心類如下:
1: using System;
2: using System.Net;
3: using System.Windows;
4: using System.Windows.Controls;
5: using System.Windows.Documents;
6: using System.Windows.Ink;
7: using System.Windows.Input;
8: using System.Windows.Media;
9: using System.Windows.Media.Animation;
10: using System.Windows.Shapes;
11:
12: namespace DataEncryptBuildDemo.DataEncryptCommon
13: {
14: /// <summary>
15: /// HMACMD Data Encrypt Operator
16: /// Author:chenkai Data:6/7/2011
17: /// </summary>
18: public class HMACMD5DataEncrypt
19: {
20: /// <summary>
21: /// HMAC_MD5 DataEncrypt
22: /// </summary>
23: /// <param name="original">明文</param>
24: /// <param name="key">密鑰</param>
25: /// <returns>返回加密的字符串</returns>
26: public static string HMAC_MD5(string original, string key)
27: {
28: byte[] b_tmp;
29: byte[] b_tmp1;
30: if (key == null)
31: {
32: return null;
33: }
34: byte[] digest = new byte[512];
35: byte[] k_ipad = new byte[64];
36: byte[] k_opad = new byte[64];
37:
38: byte[] source = System.Text.UTF8Encoding.UTF8.GetBytes(key);
39: //System.Security.Cryptography.MD5 shainner = new MD5CryptoServiceProvider();
40:
41: for (int i = 0; i < 64; i++)
42: {
43: k_ipad[i] = 0 ^ 0x36;
44: k_opad[i] = 0 ^ 0x5c;
45: }
46:
47: try
48: {
49: if (source.Length > 64)
50: {
51: //shainner = new MD5CryptoServiceProvider();
52: source = MD5Core.GetHash(source);//shainner.ComputeHash(source);
53: }
54:
55: for (int i = 0; i < source.Length; i++)
56: {
57: k_ipad[i] = (byte)(source[i] ^ 0x36);
58: k_opad[i] = (byte)(source[i] ^ 0x5c);
59: }
60:
61: b_tmp1 = System.Text.UTF8Encoding.UTF8.GetBytes(original);//內容
62: b_tmp = Adding(k_ipad, b_tmp1);
63:
64:
65: //shainner = new MD5CryptoServiceProvider();
66: digest = MD5Core.GetHash(b_tmp); //shainner.ComputeHash(b_tmp);
67: b_tmp = Adding(k_opad, digest);
68:
69:
70: //shainner = new MD5CryptoServiceProvider();
71: digest = MD5Core.GetHash(b_tmp); //shainner.ComputeHash(b_tmp);
72: return ByteToString(digest);
73: }
74: catch (Exception e)
75: {
76: throw e;
77: }
78: }
79:
80: /// <summary>
81: /// 填充byte
82: /// </summary>
83: /// <param name="a"></param>
84: /// <param name="b"></param>
85: /// <returns></returns>
86: private static byte[] Adding(byte[] a, byte[] b)
87: {
88: byte[] c = new byte[a.Length + b.Length];
89: a.CopyTo(c, 0);
90: b.CopyTo(c, a.Length);
91: return c;
92: }
93:
94: /// <summary>
95: /// Byte To String
96: /// </summary>
97: /// <param name="buff"></param>
98: /// <returns></returns>
99: private static string ByteToString(byte[] buff)
100: {
101: string sbinary = "";
102:
103: for (int i = 0; i < buff.Length; i++)
104: {
105: sbinary += buff[i].ToString("X2"); // hex format
106: }
107: return (sbinary);
108: }
109: }
110: }
具體代碼也可以從HMACMD5 For Windows Phone GitHub上可以查看.如上代碼驗證通過.
TripleDES[3DES]
Triple DES又稱3DES,是DES加密算法的一種模式.[TDEA,Triple Data Encryption Algorithm]塊密碼的通稱。它相當於是對每個數據塊應用三次DES加密算法.現在計算機運算能力的增強,原版DES密碼的密鑰長度變得容易被暴力破解;3DES即是設計用來提供一種相對簡單的方法,即通過增加DES的密鑰長度來避免類似的攻擊,而不是設計一種全新的塊密碼算法.
一開始我大概看了DES 算法在C下面的實現很簡單.費了點時間很快就移植Windows Phone DES算法版本. DES算法的核心采用位運算的. 每次8個字節也就是64位內容.密鑰key也為64位.然后經過16輪置換. 可惜 TripleDES[3DES]始終沒有移植成功.重復造輪子無果后.果斷尋求第三方解決方案.
在Silverlight和Windows Phone 在CodePlex值得推薦開源第三方庫是SSH.NET Library
SSH.NET Library:
SSH.NET Library庫移植靈感是來源於Java版本.不過SSH。NET是完全基於.NET 沒有采用任何第三方組件和引用. 其中實現也包含同步和異步的封裝. Socket通信庫. HTTP代等.其中最為重要的是基於.NET 實現DES和TripleDES[3DES] 兩種核心算法. 並且支持.NET 3.5 、Silverlight、Windows Phone.
當然除了Codeplex上這個比較成熟SSH.NET Library開源組件外.關於DES和TripleDES[3DES] 還可以找到其他類似可選的開源組件.針對Windows Phone 缺乏3DES支持.國外一個WP 開發者Nicolas Humann[Link in] 基於broccoliproducts 的DES, TripleDES and BlowFish in Silverlight 版本庫做了進一步的集成和封裝. 並成功移植DES和TripleDES[3DES]Windows phone版本:
Nicolas Humann[Link in] DES And TripleDES[3DES] Component:
針對Nicolas Humann[Link in] 這個3DES版本移植ku.在其基礎做了進一步的封裝.為了是實現對TripleDESCryptoServiceProvider 類[3DES核心實現類]對數據加密和解密的操作. 大概分為兩種情況.一種是需要IV密鑰Key 另外一種不需要密鑰Key 數據基於3DES和DES 加密和解密的封裝. 核心Code如下:
1: using System;
2: using System.Net;
3: using System.Windows;
4: using System.Windows.Controls;
5: using System.Windows.Documents;
6: using System.Windows.Ink;
7: using System.Windows.Input;
8: using System.Windows.Media;
9: using System.Windows.Media.Animation;
10: using System.Windows.Shapes;
11:
12: using System.Text;
13: using System.Security.Cryptography;
14: using DataEncryptBuildDemo.DataEncryptCommon.DESDataEncrypt;
15:
16: namespace DataEncryptBuildDemo.DataEncryptCommon
17: {
18: /// <summary>
19: /// Des And TripleDES DataEncrypt Operator
20: /// Author:chenkai Date:14/5 2012
21: /// </summary>
22: public class Des_DataEncrypt
23: {
24: /// <summary>
25: /// TripleDes Data Encrypt With Ot Encrypt Key Operator
26: /// </summary>
27: /// <param name="sourceContent">Source Need to TripleDes Encrpt Data</param>
28: /// <returns>Encrypt Data Byte[] String</returns>
29: public static byte[] TripleDesEncryptWithOutKey(string sourceContent)
30: {
31: if (string.IsNullOrEmpty(sourceContent))
32: return null;
33:
34: var toEncryptSourceStr = Encoding.UTF8.GetBytes(sourceContent);
35: TripleDESCryptoServiceProvider tripleDesEncryptProvider = new TripleDESCryptoServiceProvider();
36: ICryptoTransform encryptTransform=tripleDesEncryptProvider.CreateEncryptor();
37: byte[] encryptToBytes = encryptTransform.TransformFinalBlock(toEncryptSourceStr, 0, toEncryptSourceStr.Length);
38:
39: return encryptToBytes;
40: }
41:
42: /// <summary>
43: /// TripleDes Data DeEncrypt With Out Encrypt Key Operator
44: /// </summary>
45: /// <param name="encryptBytes">Encrypt Byte Array</param>
46: /// <returns>DeEncrypt SourceContent String</returns>
47: public static string TripleDesDeEncryptWithOutKey(byte[] encryptBytes)
48: {
49: if (encryptBytes == null || encryptBytes.Length <= 0)
50: return string.Empty;
51:
52: TripleDESCryptoServiceProvider tripleDesProvider = new TripleDESCryptoServiceProvider();
53: ICryptoTransform deEncryptTransform = tripleDesProvider.CreateDecryptor();
54: var deEncryptBytes = deEncryptTransform.TransformFinalBlock(encryptBytes, 0, encryptBytes.Length);
55: var deEncryptFormatStr = Encoding.UTF8.GetString(deEncryptBytes, 0, deEncryptBytes.Length);
56:
57: return deEncryptFormatStr;
58: }
59:
60: /// <summary>
61: /// TripleDes Data Encrypt Use IVKey Operator
62: /// </summary>
63: /// <param name="sourceContent">Source Content</param>
64: /// <param name="encryptKey">Encrypt Key</param>
65: /// <returns>Encrypt Bytes Array</returns>
66: public static byte[] TripleDesEncryptUseIvKey(string sourceContent, byte[] encryptIVKey)
67: {
68: if (string.IsNullOrEmpty(sourceContent) || encryptIVKey == null || encryptIVKey.Length <= 0)
69: return null;
70:
71: var toEncryptSourceStr = Encoding.UTF8.GetBytes(sourceContent);
72: TripleDESCryptoServiceProvider tripleDesProvider = new TripleDESCryptoServiceProvider();
73:
74: //No Seting Pading
76: var key = tripleDesProvider.Key; //Save Key
77: IsolatedStorageCommon.IsolatedStorageSettingHelper.AddIsolateStorageObj("EncryptKey", key);
78: ICryptoTransform encryptTransform = tripleDesProvider.CreateEncryptor(key, encryptIVKey);
79: var encryptBytes = encryptTransform.TransformFinalBlock(toEncryptSourceStr, 0, toEncryptSourceStr.Length);
80:
81: return encryptBytes;
82: }
83:
84:
85:
86: /// <summary>
87: /// Triple Des DeEncrypt Operator Use IvKey
88: /// </summary>
89: /// <param name="encryptKey">Encrypt key can be null</param>
90: /// <param name="ivKey">Iv</param>
91: /// <param name="encryptBytes">EncryptBytes</param>
92: /// <returns>Return String </returns>
93: public static string TripleDesDeEncryptUseIvKey(byte[] encryptKey, byte[] ivKey, byte[] encryptBytes)
94: {
95: if (encryptBytes == null || encryptBytes.Length <= 0)
96: return string.Empty;
97:
98: TripleDESCryptoServiceProvider tripleDesProvider = new TripleDESCryptoServiceProvider();
99:
100: if (encryptKey == null)
101: encryptKey = IsolatedStorageCommon.IsolatedStorageSettingHelper.GetIsolateStorageByObj("EncryptKey") as byte[];
102: ICryptoTransform deEncryptTransform = tripleDesProvider.CreateDecryptor(encryptKey, ivKey);
103: var DecryptBytes = deEncryptTransform.TransformFinalBlock(encryptBytes, 0, encryptBytes.Length);
104: string unDecryptFomatStr = Encoding.UTF8.GetString(DecryptBytes, 0, DecryptBytes.Length);
105:
106: return unDecryptFomatStr;
107: }
108: }
109: }
當然這個只是Nicolas Humann[Link in] 對3DEs Windows Phone版本進一步封裝. 目的方便能夠形成一套API.無需關心TripleDESCryptoServiceProvider 類具體如何實現.至於這段代碼可以GitHub上找到.驗證通過.
至此關於應用開發常見的MD5、MAC_MD5、DES、3DES Windows Phone移植版本算法可用庫如上.如上代碼均實際項目中驗證通過.對於還在苦苦重復造輪子同學.如果覺得為了使用效率.還是值得參考的.
關於本片全部源碼可以GitHub下載到[ https://github.com/chenkai/DataEncryptWindowsPhoneDemo ].如有Bug請即時反饋 Email:chenkaiHome@live.cn
或通過Sina 微博:[http://weibo.com/chenkaihome] 即時溝通.
參考鏈接: