天天看點

DES加解密原理及實作

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位元組的整數倍,然後分組、加密,最後将各分組的密文資料進行整合,成為一個密文。

關鍵點:

填充、分組、加密、合并。