天天看点

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字节的整数倍,然后分组、加密,最后将各分组的密文数据进行整合,成为一个密文。

关键点:

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