Windows中文网

 找回密码
 立即注册
搜索
查看: 5360|回复: 2

数据加密标准DES加密原理及编程实现

[复制链接]

19

主题

22

帖子

428

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
428
发表于 2022-9-10 09:14:13 | 显示全部楼层 |阅读模式
美国国家标准与技术研究院(National Institute of Standards and Technology,简称NIST,原美国国家标准局NBS)于1973年向社会公开征集一种用于政府机构和商业部门对非机密的敏感数据进行加密的加密算法。许多公司都提交了自己的加密算法,经过评测,最后选中了IBM公司提交的一种加密算法,又经过一段时间的试用和征求意见,美国政府于1977年1月5日将其作为数据加密标准(DataEncryption Standard,简称DES)。
DES是一种对称密码,也是一种分组密码。DES的明密文分组长度均为64位;密钥也是64位,但是只有其中的56位被实际用于算法,其余8位可以选择用于奇偶校验,因此,DES的有效密钥长度仅为56位。
DES所使用的56位密钥过短,随着计算机的快速发展,DES已经能够被暴力破解,1999年1月,distributed.net与电子前哨基金会合作,在22小时15分钟内即公开破解了一个DES密钥,再后来更是出现了秒速破解DES的技术,除了可以用于解密以前的密文,已经没有继续使用DES进行加密的理由。1999年以后,DES被3DES(即Triple DES,也称为Triple Data EncryptionAlgorithm,后者简称TDEA)所替代,3DES相当于是使用两个或三个不同的密钥将数据进行三次DES加密,可以说3DES是DES的一个更安全的变形。现在,3DES已经被更安全的高级加密标准AES所替代。
现在,详细介绍一下DES的加密解密原理。DES的基本结构是由霍斯特·费斯托(Horst Feistel)设计的,因此,DES也称为费斯托网络(Feistel Network)或费斯托密码(Feistel Cipher)。费斯托结构是用于构造分组密码的对称结构,该结构的优点在于加密和解密操作非常相似,在某些情况下甚至是相同的,只需要逆转密钥编排即可,因此,实现这种密码所需的代码或电路大小几乎可以减半。费斯托结构不仅被用于DES,很多其他密码系统也都采用这一结构。
在费斯托密码中,加密的各个步骤称为轮(Round),整个加密过程就是进行若干轮的迭代。DES是一种进行16轮迭代的费斯托密码。
DES的加密过程如下所示:
(1)   64位密钥经过子密钥产生算法生成16个子密钥:                              ,分别用于第1轮,第2轮,…,第16轮加密迭代时使用。
(2)  64位明文通过初始置换 (InitialPermutation)将数据打乱重新排列,并分成左右两半,左边32位称为 ,右边32位称为 。执行完初始置换 后,开始16轮加密迭代。
(3)    在子密钥 的参与下通过轮函数 进行加密,即 , 的输出结果还是32位数据; 的输出结果再与 执行异或操作,即 ,输出结果当然还是32位数据。然后,执行一个左右交换以供下一轮加密迭代使用,将 的输出结果作为第2轮加密迭代的 ,将 直接作为第2轮加密迭代的 。至此,第1轮加密迭代结束。总结一下就是: 。
(4)  为了直观起见,再列出第2轮加密过程。现在, 。执行完第2轮加密迭代的结果是: 直接作为 , 的输出结果作为 , 和 用于第3轮加密迭代。
(5)   第3~15轮加密迭代分别在子密钥 ~ 的参与下通过轮函数 进行加密,每一轮加密后都会进行左右交换,其过程与前2轮加密迭代是相同的道理。
(6) 很明显,第15轮加密迭代的操作是: 。现在,进行第16轮加密: 不变。因为没有第17轮加密迭代,所以这一轮不需要执行左右交换,不过,执行完第16轮加密操作后,左边32位我们还是称之为 ,右边32位则称之为 。
(7)   左边32位的 和右边32位的 ,这64位数据执行初始置换的逆 (也称为Final Permutation,简称FP),将数据打乱重新排列,得到64位的密文数据。至此,加密过程结束。
请结合下图以理解整个加密过程:
图片1.png
异或运算的一个特性是:某个操作数与同样的操作数执行两次异或运算后,其值保持不变。因为该特性,异或运算经常用于加密解密。例如字母‘A’的ASCII码值为0x41,字母‘K’的ASCII码值为0x4B,0x41⊕0x4B = 0x0A,0x0A⊕0x4B = 0x41,即0x41⊕0x4B⊕0x4B = 0x41。

回复

使用道具 举报

19

主题

22

帖子

428

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
428
 楼主| 发表于 2022-9-11 09:26:06 | 显示全部楼层
DES.h头文件
[C] 纯文本查看 复制代码
#ifndef DES_H

#define DES_H

#define ENCRYPTION_MODE 1
#define DECRYPTION_MODE 0

#include <stdint.h>

// 子密钥结构
typedef struct _KeySet {
   uint8_t k[8];
   uint8_t c[4];
   uint8_t d[4];
} KeySet, * PKeySet;

void GenerateSubKeys(uint8_t* pcDesKey, PKeySet pKeySets);
void ProcessMessage(uint8_t* pcMessageBlock, uint8_t* pcMessageResult,
   PKeySet pKeySets, int nMode);

#endif

回复 支持 反对

使用道具 举报

19

主题

22

帖子

428

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
428
 楼主| 发表于 2022-9-11 09:28:22 | 显示全部楼层
DES.cpp源文件
[C] 纯文本查看 复制代码
#include <memory.h>
#include "DES.h"

int aPermutationChoice1Index[] = { 57, 49, 41, 33, 25, 17,  9,
                                    1, 58, 50, 42, 34, 26, 18,
                                   10,  2, 59, 51, 43, 35, 27,
                                   19, 11,  3, 60, 52, 44, 36,
                                   63, 55, 47, 39, 31, 23, 15,
                                    7, 62, 54, 46, 38, 30, 22,
                                   14,  6, 61, 53, 45, 37, 29,
                                   21, 13,  5, 28, 20, 12,  4 };

int aCyclicLeftShiftBits[] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };

int aPermutationChoice2Index[] = { 14, 17, 11, 24,  1,  5,
                                    3, 28, 15,  6, 21, 10,
                                   23, 19, 12,  4, 26,  8,
                                   16,  7, 27, 20, 13,  2,
                                   41, 52, 31, 37, 47, 55,
                                   30, 40, 51, 45, 33, 48,
                                   44, 49, 39, 56, 34, 53,
                                   46, 42, 50, 36, 29, 32 };

int aInitialPermutationIndex[] = { 58, 50, 42, 34, 26, 18, 10, 2,
                                   60, 52, 44, 36, 28, 20, 12, 4,
                                   62, 54, 46, 38, 30, 22, 14, 6,
                                   64, 56, 48, 40, 32, 24, 16, 8,
                                   57, 49, 41, 33, 25, 17,  9, 1,
                                   59, 51, 43, 35, 27, 19, 11, 3,
                                   61, 53, 45, 37, 29, 21, 13, 5,
                                   63, 55, 47, 39, 31, 23, 15, 7 };

int aDataExpansionTable[] = {      32,  1,  2,  3,  4,  5,
                                    4,  5,  6,  7,  8,  9,
                                    8,  9, 10, 11, 12, 13,
                                   12, 13, 14, 15, 16, 17,
                                   16, 17, 18, 19, 20, 21,
                                   20, 21, 22, 23, 24, 25,
                                   24, 25, 26, 27, 28, 29,
                                   28, 29, 30, 31, 32, 1 };

int S1[] = { 14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
              0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
              4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
             15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13 };

int S2[] = { 15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
              3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
              0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
             13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9 };

int S3[] = { 10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
             13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
             13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
              1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12 };

int S4[] = {  7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
             13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
             10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
              3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14 };

int S5[] = {  2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
             14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
              4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
             11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3 };

int S6[] = { 12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
             10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
              9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
              4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13 };

int S7[] = {  4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
             13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
              1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
              6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12 };

int S8[] = { 13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
              1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
              7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
              2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11 };

int aPermutationOperationIndex[] = { 16,  7, 20, 21,
                                     29, 12, 28, 17,
                                      1, 15, 23, 26,
                                      5, 18, 31, 10,
                                      2,  8, 24, 14,
                                     32, 27,  3,  9,
                                     19, 13, 30,  6,
                                     22, 11,  4, 25 };

int aFinalPermutationIndex[] = {     40,  8, 48, 16, 56, 24, 64, 32,
                                     39,  7, 47, 15, 55, 23, 63, 31,
                                     38,  6, 46, 14, 54, 22, 62, 30,
                                     37,  5, 45, 13, 53, 21, 61, 29,
                                     36,  4, 44, 12, 52, 20, 60, 28,
                                     35,  3, 43, 11, 51, 19, 59, 27,
                                     34,  2, 42, 10, 50, 18, 58, 26,
                                     33,  1, 41,  9, 49, 17, 57, 25 };

/*******************************************************************************
  * 函数功能:		产生16个48位的子密钥
  * 输入参数的说明:
    1. pcDesKey是用户输入的8字节(64位)密钥的指针
    2. pKeySets是指向17个KeySet结构数组的指针
  * 注意:调用该函数之前,必须将pKeySets参数指向的结构数组初始化为0
*******************************************************************************/
void GenerateSubKeys(uint8_t* pcDesKey, PKeySet pKeySets)
{
   int i, j;
   int nShiftIndex;
   uint8_t cShiftByte;
   uint8_t cFirstShiftBit, cSecondShiftBit, cThirdShiftBit, cFourthShiftBit;

   // 64位密钥首先执行置换选择PC-1,从中选出56位作为初始密钥,
   // 存放于pKeySets[0].k的前7个字节中
   for (i = 0; i < 56; i++)
   {
      nShiftIndex  = aPermutationChoice1Index[i];     // 在原64位密钥中的索引
      cShiftByte   = 0x80 >> ((nShiftIndex - 1) % 8); // 这个索引在字节中的标志位
      cShiftByte  &= pcDesKey[(nShiftIndex - 1) / 8]; // 从8字节密钥中取对应的位
      cShiftByte <<= ((nShiftIndex - 1) % 8);         // 对应的位成为最高位

      pKeySets[0].k[i / 8] |= (cShiftByte >> (i % 8));// 构成56位初始密钥,7个字节
   }

   // 把56位初始密钥分成两个28位的半密钥C0和D0,各使用3.5字节
   for (i = 0; i < 3; i++)
   {
      pKeySets[0].c[i] = pKeySets[0].k[i];
   }
   pKeySets[0].c[3] = pKeySets[0].k[3] & 0xF0;

   for (i = 0; i < 3; i++)
   {
      pKeySets[0].d[i]  = (pKeySets[0].k[i + 3] & 0x0F) << 4;
      pKeySets[0].d[i] |= (pKeySets[0].k[i + 4] & 0xF0) >> 4;
   }
   pKeySets[0].d[3] = (pKeySets[0].k[6] & 0x0F) << 4;

   // 产生16个48位的子密钥
   for (i = 1; i < 17; i++)
   {
      // C1 = C0, D1 = D0; C2 = C1, D2 = D1; …; C16 = C15, D16 = D15;
      for (j = 0; j < 4; j++)
      {
         pKeySets[i].c[j] = pKeySets[i - 1].c[j];
         pKeySets[i].d[j] = pKeySets[i - 1].d[j];
      }

      // 循环左移1或2位
      nShiftIndex = aCyclicLeftShiftBits[i - 1];
      if (nShiftIndex == 1)
         cShiftByte = 0x80;
      else
         cShiftByte = 0xC0;

      // 循环左移左半密钥C1,C2,…,C16
      cFirstShiftBit  = cShiftByte & pKeySets[i].c[0];
      cSecondShiftBit = cShiftByte & pKeySets[i].c[1];
      cThirdShiftBit  = cShiftByte & pKeySets[i].c[2];
      cFourthShiftBit = cShiftByte & pKeySets[i].c[3];

      pKeySets[i].c[0] <<= nShiftIndex;
      pKeySets[i].c[0]  |= (cSecondShiftBit >> (8 - nShiftIndex));

      pKeySets[i].c[1] <<= nShiftIndex;
      pKeySets[i].c[1]  |= (cThirdShiftBit  >> (8 - nShiftIndex));

      pKeySets[i].c[2] <<= nShiftIndex;
      pKeySets[i].c[2]  |= (cFourthShiftBit >> (8 - nShiftIndex));

      pKeySets[i].c[3] <<= nShiftIndex;
      pKeySets[i].c[3]  |= (cFirstShiftBit  >> (4 - nShiftIndex));

      // 循环左移右半密钥D1,D2,…,D16
      cFirstShiftBit  = cShiftByte & pKeySets[i].d[0];
      cSecondShiftBit = cShiftByte & pKeySets[i].d[1];
      cThirdShiftBit  = cShiftByte & pKeySets[i].d[2];
      cFourthShiftBit = cShiftByte & pKeySets[i].d[3];

      pKeySets[i].d[0] <<= nShiftIndex;
      pKeySets[i].d[0]  |= (cSecondShiftBit >> (8 - nShiftIndex));

      pKeySets[i].d[1] <<= nShiftIndex;
      pKeySets[i].d[1]  |= (cThirdShiftBit  >> (8 - nShiftIndex));

      pKeySets[i].d[2] <<= nShiftIndex;
      pKeySets[i].d[2]  |= (cFourthShiftBit >> (8 - nShiftIndex));

      pKeySets[i].d[3] <<= nShiftIndex;
      pKeySets[i].d[3]  |= (cFirstShiftBit  >> (4 - nShiftIndex));

      // 执行置换选择PC-2,从已经经过循环左移的56位密钥中选择出48位作为子密钥,
      // 存放于pKeySets[i].k的前6个字节中
      for (j = 0; j < 48; j++)
      {
         nShiftIndex = aPermutationChoice2Index[j];             // 在56位密钥中的索引
         if (nShiftIndex <= 28)
         {
            cShiftByte   = 0x80 >> ((nShiftIndex - 1) % 8);     // 在字节中的标志位
            cShiftByte  &= pKeySets[i].c[(nShiftIndex - 1) / 8];// 取对应的位
            cShiftByte <<= ((nShiftIndex - 1) % 8);             // 对应的位成为最高位
         }
         else
         {
            cShiftByte   = 0x80 >> ((nShiftIndex - 29) % 8);
            cShiftByte  &= pKeySets[i].d[(nShiftIndex - 29) / 8];
            cShiftByte <<= ((nShiftIndex - 29) % 8);
         }

         pKeySets[i].k[j / 8] |= (cShiftByte >> (j % 8));      // 构成48位子密钥
      }
   }
}

/*******************************************************************************
  * 函数功能:   对64位明文数据块进行DES加密;或对64位密文数据块进行DES解密
  * 输入参数的说明:
    1. pcMessageBlock是指向64位明文或密文数据块的指针
    2. pcMessageResult指向的64位缓冲区用于返回明文或密文数据块的加密或解密结果
    3. pKeySets是指向17个KeySet结构数组的指针
    4. nMode参数用于指定执行模式,指定为自定义常量ENCRYPTION_MODE(1)表示加密,
       指定为DECRYPTION_MODE(0)表示解密
  * 注意:调用该函数之前,必须将pcMessageResult参数指向的缓冲区初始化为0
*******************************************************************************/
void ProcessMessage(uint8_t* pcMessageBlock, uint8_t* pcMessageResult, 
   PKeySet pKeySets, int nMode)
{
   int i;
   int nShiftIndex;
   uint8_t cShiftByte;
   uint8_t aInitialPermutation[8] = { 0 };   // 临时数组
   uint8_t aL[4] = { 0 }, aR[4] = { 0 };     // L0和R0

   // 初始置换IP,将64位明文数据打乱重新排列,存放于aInitialPermutation数组
   for (i = 0; i < 64; i++)
   {
      nShiftIndex  = aInitialPermutationIndex[i];
      cShiftByte   = 0x80 >> ((nShiftIndex - 1) % 8);
      cShiftByte  &= pcMessageBlock[(nShiftIndex - 1) / 8];
      cShiftByte <<= ((nShiftIndex - 1) % 8);

      aInitialPermutation[i / 8] |= (cShiftByte >> (i % 8));
   }

   // L0和R0
   for (i = 0; i < 4; i++)
   {
      aL[i] = aInitialPermutation[i];
      aR[i] = aInitialPermutation[i + 4];
   }

   // 左32位的Li,右32位的Ri,48位的中间结果,32位的S盒输出
   uint8_t aLi[4] = { 0 }, aRi[4] = { 0 }, aMid[6] = { 0 }, aSOut[4] = { 0 };
   int j, nKeyIndex;

   // 开始16轮加密迭代,上边用于表示L0和R0的变量aL和aR,现在用于表示Li-1和Ri-1
   for (i = 1; i <= 16; i++)
   {
      memcpy_s(aLi, 4, aR, 4);      // Li = Ri-1

      memset(aRi,   0, 4);          // 右32位的Ri初始化为0
      memset(aMid,  0, 6);          // 48位的中间结果初始化为0
      memset(aSOut, 0, 4);          // 32位的S盒输出初始化为0

      // 执行选择运算E,将右32位的Ri-1扩展为48位的中间结果,存放于aMid
      for (j = 0; j < 48; j++)
      {
         nShiftIndex  = aDataExpansionTable[j];
         cShiftByte   = 0x80 >> ((nShiftIndex - 1) % 8);
         cShiftByte  &= aR[(nShiftIndex - 1) / 8];
         cShiftByte <<= ((nShiftIndex - 1) % 8);

         aMid[j / 8] |= (cShiftByte >> (j % 8));
      }

      // 加密的话,依次使用子密钥索引1,2,…,16;解密则反之,使用16,15,…,1
      if (nMode == ENCRYPTION_MODE)
         nKeyIndex = i;
      else
         nKeyIndex = 17 - i;

      // 通过选择运算E产生的48位数据再与子密钥Ki执行异或运算
      for (j = 0; j < 6; j++)
         aMid[j] ^= pKeySets[nKeyIndex].k[j];

      // 执行8个代替函数(S盒)
      uint8_t cRow, cColumn;  // S盒代替矩阵的行索引、列索引

      // 请结合下面的48位数据以辅助理解8个代替函数(S盒)的工作流程,r表示行,c表示列
      // 0000 0000 0000 0000 0000 0000  0000 0000 0000 0000 0000 0000
      // rccc crrc cccr rccc crrc cccr  rccc crrc cccr rccc crrc cccr

      // Byte 1(S1的输出 + S2的输出)
      cRow  = 0;
      cRow |= ((aMid[0] & 0x80) >> 6);    // 取第1位
      cRow |= ((aMid[0] & 0x04) >> 2);    // 取第6位

      cColumn  = 0;
      cColumn |= ((aMid[0] & 0x78) >> 3); // 取中间4位

      aSOut[0] |= ((uint8_t)S1[cRow * 16 + cColumn] << 4);

      cRow  = 0;
      cRow |= (aMid[0] & 0x02);           // 取第1位
      cRow |= ((aMid[1] & 0x10) >> 4);    // 取第6位

      cColumn  = 0;
      cColumn |= ((aMid[0] & 0x01) << 3);
      cColumn |= ((aMid[1] & 0xE0) >> 5); // 取中间4位

      aSOut[0] |= (uint8_t)S2[cRow * 16 + cColumn];

      // Byte 2(S3的输出 + S4的输出)
      cRow  = 0;
      cRow |= ((aMid[1] & 0x08) >> 2);
      cRow |= ((aMid[2] & 0x40) >> 6);

      cColumn  = 0;
      cColumn |= ((aMid[1] & 0x07) << 1);
      cColumn |= ((aMid[2] & 0x80) >> 7);

      aSOut[1] |= ((uint8_t)S3[cRow * 16 + cColumn] << 4);

      cRow  = 0;
      cRow |= ((aMid[2] & 0x20) >> 4);
      cRow |= (aMid[2] & 0x01);

      cColumn  = 0;
      cColumn |= ((aMid[2] & 0x1E) >> 1);

      aSOut[1] |= (uint8_t)S4[cRow * 16 + cColumn];

      // Byte 3(S5的输出 + S6的输出)
      cRow  = 0;
      cRow |= ((aMid[3] & 0x80) >> 6);
      cRow |= ((aMid[3] & 0x04) >> 2);

      cColumn  = 0;
      cColumn |= ((aMid[3] & 0x78) >> 3);

      aSOut[2] |= ((uint8_t)S5[cRow * 16 + cColumn] << 4);

      cRow  = 0;
      cRow |= (aMid[3] & 0x02);
      cRow |= ((aMid[4] & 0x10) >> 4);

      cColumn  = 0;
      cColumn |= ((aMid[3] & 0x01) << 3);
      cColumn |= ((aMid[4] & 0xE0) >> 5);

      aSOut[2] |= (uint8_t)S6[cRow * 16 + cColumn];

      // Byte 4(S7的输出 + S8的输出)
      cRow  = 0;
      cRow |= ((aMid[4] & 0x08) >> 2);
      cRow |= ((aMid[5] & 0x40) >> 6);

      cColumn  = 0;
      cColumn |= ((aMid[4] & 0x07) << 1);
      cColumn |= ((aMid[5] & 0x80) >> 7);

      aSOut[3] |= ((uint8_t)S7[cRow * 16 + cColumn] << 4);

      cRow  = 0;
      cRow |= ((aMid[5] & 0x20) >> 4);
      cRow |= (aMid[5] & 0x01);

      cColumn  = 0;
      cColumn |= ((aMid[5] & 0x1E) >> 1);

      aSOut[3] |= (uint8_t)S8[cRow * 16 + cColumn];

      // 8个S盒输出的32位数据再执行置换运算P,放入Ri
      for (j = 0; j < 32; j++)
      {
         nShiftIndex  = aPermutationOperationIndex[j];
         cShiftByte   = 0x80 >> ((nShiftIndex - 1) % 8);
         cShiftByte  &= aSOut[(nShiftIndex - 1) / 8];
         cShiftByte <<= ((nShiftIndex - 1) % 8);

         aRi[j / 8] |= (cShiftByte >> (j % 8));
      }

      // F(Ri-1, Ki)⊕Li-1
      for (j = 0; j < 4; j++)
         aRi[j] ^= aL[j];

      // Li和Ri作为下一轮加密迭代的Li-1和Ri-1
      for (j = 0; j < 4; j++)
      {
         aL[j] = aLi[j];
         aR[j] = aRi[j];
      }
   }

   // 16轮加密迭代已经结束,但是每一轮都有执行左右交换,现在,需要再左右交换回来
   uint8_t aFinalPermutation[8];

   for (j = 0; j < 4; j++)
   {
      aFinalPermutation[j] = aR[j];
      aFinalPermutation[4 + j] = aL[j];
   }

   // 执行初始置换的逆FP
   for (j = 0; j < 64; j++)
   {
      nShiftIndex  = aFinalPermutationIndex[j];
      cShiftByte   = 0x80 >> ((nShiftIndex - 1) % 8);
      cShiftByte  &= aFinalPermutation[(nShiftIndex - 1) / 8];
      cShiftByte <<= ((nShiftIndex - 1) % 8);

      pcMessageResult[j / 8] |= (cShiftByte >> (j % 8));
   }
}

回复 支持 反对

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies |上传

本版积分规则

QQ|Archiver|手机版|小黑屋|Windows中文网 ( 鲁ICP备2021014210号 )

GMT+8, 2025-6-9 20:44 , Processed in 0.111721 second(s), 29 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表