DES加解密原理及實作
這幾天在寫加解密相關的API,用來給Lua進行調用,其中一個加解密的算法是DES,底層是C/C++實作的。
當然我不是真的寫一個DES加解密的實作,而是寫一個接口就好。
順便也了解了下DES加解密的相關事項,例如填充、加密模式等等。
DES是一種對稱分組加密算法。
關鍵點在于:分組、加密、合并密文。
用簡單的話來說明下DES分組和加密的概念吧。
現在我擁有開源的代碼,接口要求一個8位元組長度的資料作為DES密鑰,要求一個8位元組長度的資料作為待加密資料。
(你可能在想:密鑰是8位元組長度還可以接受,為啥待加密資料還要規定長度?别着急,繼續往下看:)
我們擁有的開源代碼接口大概是這個樣子的:
const char *desEncrypt(char *data, char *desKey);
data是一個指針,指向一個位元組大小的位元組數組(字元數組,包含待加密資料);
desKey是一個指針,也指向一個位元組大小的位元組數組(字元數組);
傳回值是一個指針,指向加密後的密文,是一個位元組大小的資料。
我們知道:
待加密資料是8位元組,DES密鑰也是8位元組,最後的密文也是8位元組。
現在我們想要的API接口是這個樣子的:
size_t desEnc(char *plain, size_t plainLen, char *desKey, char *cipher)
plain是一個位元組數組,長度不定(可能是位元組大小,可能是位元組大小,可能是位元組大小...);
plainLen指代plain的長度(因為plain是位元組資料,有可能包含);
desKey是位元組大小的DES密鑰;
cipher是存放加密結果的地方;
函數傳回值指代cipher的大小(因為cipher也有可能包含);
OK。
用一個例子來解釋:
假設你有下面的明文:
AAAAAAAABBBBBBBBCCCCCCCC
看到了吧?是8*3=24B長度的一個字元串。
注:
以上字元串實際對應的資料是:
0x410x410x410x410x410x410x410x41
0x420x420x420x420x420x420x420x42
0x430x430x430x430x430x430x430x43
應該說:這個待加密資料“恰好是可列印字元組成”,實際待加密的資料并不一定是可列印的喲!
我們的DES密鑰:
DDDDDDDD
這是一個8位元組長度的資料。
注:
以上密鑰對應的二進制資料是:
0x440x440x440x440x440x440x440x44
道理也是同上,這個DES密鑰也“恰好是可列印字元組成”,實際并不一定是可列印的。
假定我們預設使用的是PKCS#5填充模式。
詳見:
http://blog.csdn.net/test1280/article/details/
待加密資料剛好是24位元組,是8的整數倍,那麼進行PKCS#5填充,填充8個0x08位元組;
填充完畢後,待加密資料為:
0x410x410x410x410x410x410x410x41
0x420x420x420x420x420x420x420x42
0x430x430x430x430x430x430x430x43
0x080x080x080x080x080x080x080x08
分成四組(每8位元組一組):
待加密資料:
0x410x410x410x410x410x410x410x41
DES密鑰:
0x440x440x440x440x440x440x440x44
經過desEncrypt加密後,密文為:
0x580x580x580x580x580x580x580x58
待加密資料:
0x420x420x420x420x420x420x420x42
DES密鑰:
0x440x440x440x440x440x440x440x44
經過desEncrypt加密後,密文為:
0x590x590x590x590x590x590x590x59
待加密資料:
0x430x430x430x430x430x430x430x43
DES密鑰:
0x440x440x440x440x440x440x440x44
經過desEncrypt加密後,密文為:
0x600x600x600x600x600x600x600x60
待加密資料:
0x080x080x080x080x080x080x080x08
DES密鑰:
0x440x440x440x440x440x440x440x44
經過desEncrypt加密後,密文為:
0x570x570x570x570x570x570x570x57
最後将四組密文拼成一個密文:
0x580x580x580x580x580x580x580x58
0x590x590x590x590x590x590x590x59
0x600x600x600x600x600x600x600x60
0x570x570x570x570x570x570x570x57
大功告成!
用desEnc來說明:
size_t cipherLen = 0;
cipherLen = desEnc(plain, plainLen, desKey, cipher);
其中,plain内容為:
0x410x410x410x410x410x410x410x41
0x420x420x420x420x420x420x420x42
0x430x430x430x430x430x430x430x43
plainLen為:24;
desKey為:
0x440x440x440x440x440x440x440x44;
加密後,cipher為:
0x580x580x580x580x580x580x580x58
0x590x590x590x590x590x590x590x59
0x600x600x600x600x600x600x600x60
0x570x570x570x570x570x570x570x57
cipherLen為32;
記住,DES隻是做了加密,指的是8位元組資料和8位元組的密鑰進行加密變換。
至于填充方式,是在你的外部包裝的API(就是這裡的desEnc)裡面來做的,你可以用PKCS#5來進行填充,保證其總是8位元組的整數倍。
總的來說,真正的DES加密是對8位元組資料進行加密,但實際運用中我們的待加密資料很有可能不是8位元組大小,這個時候就要先進行填充,将其填充到8位元組的整數倍,然後分組、加密,最後将各分組的密文資料進行整合,成為一個密文。
關鍵點:
填充、分組、加密、合并。