C#入門實(shí)踐:Windows桌面加密器 CryptoSharp
Step 1 BASE64/編碼/DLL
by Pixel Frame
GitHub: CryptoSharp
源碼在文中基本不再出現(xiàn)。
0x00 前期準(zhǔn)備
本著由淺入深柬赐、由簡入繁、Top Down的原則菱属,首先為Visual Studio選擇一個(gè)好看的配色方案和合適的字體(什么狗P邏輯)。
個(gè)人還是比較喜歡深色配色舰罚,奈何Color Theme Editor插件中沒有Monokai配色纽门,自己改一個(gè)又太累了(),所以直接選擇了Dark with Light Editor营罢。
字體上的話赏陵,用Font Link把Consolas和微軟雅黑鏈接是一個(gè)簡單快捷的選擇。思源的等寬字體感覺太寬了饲漾,和中文混排看起來十分詭異蝙搔。原生的中英文混排等寬字體其實(shí)非常少,比如說新宋體()考传。首推的還是Belleve大的更紗黑體吃型,還有一個(gè)經(jīng)典選擇自然是文泉驛等寬微米黑和文泉驛等寬正黑。
0x01 BASE64與編碼
作為一個(gè)加密器自然需要考慮各種各樣的編碼問題僚楞,雖然說也有很多場合把BASE64稱作加密勤晚,但其本質(zhì)只是把不可顯示的ASCII碼轉(zhuǎn)換到了可顯示部分。C#的Convert類中自帶了BASE64轉(zhuǎn)換泉褐,所以可以直接調(diào)用(本篇完赐写,下面沒有了)。
然而膜赃,要自己實(shí)現(xiàn)一遍~(我寫的比庫函數(shù)好得多.png)血淌。
C#所有文本都是Unicode(UTF-16LE),即對(duì)應(yīng)C++中的16位字符wchar_t
财剖,不能和C++一樣將工程設(shè)置為多字節(jié)(UTF-8/ANSI等)。這對(duì)于進(jìn)行加解密操作其實(shí)是不太方便的癌淮,BASE64是針對(duì)8位的byte(unsigned char)
進(jìn)行操作的躺坟,因此我們需要自己構(gòu)建一個(gè)C++的std::string
來方便操作。當(dāng)然乳蓄,加密算法中大量bit級(jí)的操作其實(shí)都不適合軟件編程咪橙,相比之下用HDL作專用硬件會(huì)方便很多。關(guān)于位操作的問題會(huì)在DES中更多涉及。
ByteString
一個(gè)好用的string
類需要哪些東西是很顯然的美侦,動(dòng)態(tài)分配/截取/查找/運(yùn)算符重載...當(dāng)然产舞,我的目標(biāo)是夠用就行,需要新的功能時(shí)再行添加菠剩。C#的List<>
和數(shù)組十分強(qiáng)大易猫,可以直接通過AddRange(), ToArray(), ToList()
等一系列方法進(jìn)行轉(zhuǎn)換和增加,因此其實(shí)就是對(duì)List<byte>
做一個(gè)二次封裝具壮。
用List<byte>
保存字符數(shù)據(jù)准颓,重載+
運(yùn)算符,構(gòu)造函數(shù)棺妓,定義索引器[]
攘已,外加Set/GetBytes()
和ToString()
方法。這樣一個(gè)簡單可用的ByteString
類就完成了怜跑。
在之后可能還會(huì)加入移位等的功能样勃,在遇到時(shí)再行討論。
BASE64
BASE64的加解密并不復(fù)雜性芬,簡單來說就是每三個(gè)bytes進(jìn)行一次替換峡眶,不足的地方用=
替換。那么批旺,這里就直接從一份C++代碼進(jìn)行改寫幌陕。將C++中的char
全部改為byte
類型,通過Encoding
獲取字符的ASCII碼汽煮,這里只要采用多字節(jié)代碼頁(ANSI/UTF-8/GBK/BIG5)都是沒有問題的搏熄,結(jié)果都是相同的ASCII碼。當(dāng)然Encoding
會(huì)損失一定的性能暇赤,通過硬編碼將對(duì)應(yīng)ASCII碼寫入程序能提高一定的性能心例,當(dāng)然既然選擇了C#對(duì)性能也不做過分的追求了。
一般而言會(huì)將查找表設(shè)為全局常量鞋囊,然而并沒有找到如何聲明一個(gè)const
數(shù)組止后,那么就只好使用static readonly
,效果似乎是相同的溜腐。
static readonly byte[] base64Table = Encoding.UTF8.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +/");
static readonly byte base64Pad = Encoding.UTF8.GetBytes("=")[0];
static readonly byte[] base64PadD = Encoding.UTF8.GetBytes("==");
static readonly int[] decodeTable =
{
-2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -2, -1, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2,
-2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2,
-2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2
};
加解密過程就不作詳細(xì)解釋了译株,再來說說編碼的問題⊥σ妫基本的加密方法的輸入是byte[]
輸出是string(UTF-16LE)
歉糜,但一般而言輸入會(huì)是一個(gè)字符串并且會(huì)有各種編碼的可能(當(dāng)然作為C#程序一般獲取到的都會(huì)是UTF-16LE)。高級(jí)語言的好處就在于各種功能都有現(xiàn)成的封裝望众,相比C++的MultiByteToWideChar()
函數(shù)和USES_CONVERSION
宏匪补,C#的Encoding
類要方便很多伞辛,支持的編碼可以在微軟的開發(fā)文檔中找到。核心的Encrypt
和Decrypt
方法使用byte[]
作為輸入/輸出夯缺,再進(jìn)行string
的重載并且添加指定編碼參數(shù)蚤氏。
public static String Encrypt(byte[] bPlain);
public static String Encrypt(String strPlain, String coding);
public static String Encrypt(String strPlain, int coding);
public static byte[] Decode(String strEnc);
public static String DecodeEncoding(String strEnc, String coding);
public static String DecodeEncoding(String strEnc, int coding);
0x02 解決方案與DLL
為了方便管理,將各個(gè)加密算法作為DLL項(xiàng)目添加至解決方案中踊兜。DLL的接口方法會(huì)逐漸完善竿滨。最終CryptoSharp將只需要調(diào)用DLL的接口,本身則是WinForm UI為主润文。
C#中同一解決方案項(xiàng)目姐呐、.NET庫、外部DLL都只需要在添加引用即可典蝌,包括C++ COM組件DLL也是可以直接使用的曙砂。
次回予告:DES AND SHIFTING
END_OF_PART_2