详解DES算法原理与实现(2)

下一步,Rint 需要通过8个单独的S盒执行8次替换操作。每个S盒(j)从Rint的6j 到 6j+6 的位置取出6位,并为其在表6中查出1个4位的值,将该值写到缓冲区的4j位置处(如图3)。

图3:DES中的8个S盒

详解DES算法原理与实现

读表6,查找S盒(j)。通过前面取出的6位值,根据第1位和最后1位组成的2位值找到表6中的行号,而根据中间剩下的4位来确定表6中的列号。比如,在图3中,Rint中的第3个6位组是101011。因此,在表6中查找到的第3个S盒是9。因为行号等于112 = 3,列号等于01012 = 5(查表时从索引0开始计数)。S盒为数据增加了不确定性,除了给DES带来安全性外,没什么特别的。

表6:DES中数据块的S盒替换

详解DES算法原理与实现

详解DES算法原理与实现

一旦完成了S盒替换,得到的结果又变为一个32位的值。接下来再通过P盒来置换。如下表7所示。

表7:DES中数据块的P盒置换

到目前为止,我们把这一轮的操作想象为一个函数,一般记为f。如果 bj 代表Rint中的第j个6位组,Sj 代表第j个S盒,而P代表P盒置换,则该函数可以定义为

f = P(S1(b1),S2(b2),...,S8(b8))

每一轮的最后一个操作是计算 f 的32位结果值与传入本轮操作的原始数据的左分组Li-1之间的异或值。

一旦完成,将左右两个分组交换然后开始下一轮

在最后一轮中,不用交换左右分组。

把所有的步骤连起来,在每一轮中计算Li和Ri的步骤可以精确表示为:

Li = Ri-1

Ri = Li-1  f(Ri-1,Ki)

当全部的16轮操作都结束后,将最后的右分组R16和最后剩下的左分组L16连接起来,组成一个64位的分组R16L16。(回顾一下,在最后一轮中左右分组并没有交换。最后的右分组在左边而最后的左分组在右边。)

最后一步是将R16L16按照表8所示的置换进行置换。简而言之,就是撤消之前的初始置换。

加密数据时,最终结果就是一个64位的密文,而当解密数据时,最终结果就是64位的明文了。

表8:DES中数据块的最终置换

 DES的接口定义 

des_encipher

void des_encipher(const unsigned char *plaintext, unsigned char *ciphertext, unsigned char *key);

返回值:无

描述采用DES算法,将明文plaintext的一个64位的明文组加密。在key中指定64位的密钥(最后8位将被忽略掉,实际得到56位的密钥)。ciphertext是返回的64位的密文组。

由调用者负责管理ciphertext所需要的空间。要加密一段较大的数据,可以按照分组加密模式调用des_encipher。为了得到较高的效率,des_encipher可以重用之前的调用中计算出来的子密钥,这可以通过在之后的调用中将NULL传给key,以此来开启这种功能。

复杂度:O(1)

des_decipher

void des_decipher(const unsigned char *ciphertext, unsigned char *plaintext, unsigned char *key);

返回值:无

描述采用DES算法将密文ciphertext的一个64位分组解密。该函数假设ciphertext包含的是通过des_encipher加密过的密文。在key中指定64位的密钥(最后8位将被忽略掉,实际得到56位的密钥)。plaintext是返回的64位的明文组。由调用者负责管理plaintext所需要的空间。要解密一大段的数据,可以按照分组加密模式调用des_decipher。为了获得较高的效率,des_decipher可以重用之前调用中计算出来的子密钥。可以在随后的调用中将NULL传给key,以此来开启这种功能。

复杂度:O(1)

DES算法的实现

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/f623b421ca1b32ccaf22f3f01c926f02.html