LegendSaber 发表于 2021-10-24 12:40

DES算法的C语言实现

本帖最后由 LegendSaber 于 2021-10-24 12:52 编辑

       曾经学习DES算法时候写过的一份C语言实现的DES加解密算法。现在提供给大家参考
       首先,由于DES是在比特层面对输入进行加密的。所以,首先需要做到将输入的字符与其二进制形式的互相转换,这部分代码在CChar中实现

#include "CChar.h"

void CharToBit(char input[], char output[])
{
      int i = 0, j = 0, k = 0;
      
      for (i = 0; i < 8; i++)
      {
                for (j = 0; j < 8; j++)
                {
                        k = 7 - j;
                        output = (input >> k) & 0x1;
                }
      }
}

void BitToChar(char input[], char output[])
{
      int i = 0, j = 0, k = 0;

      for (i = 0; i < 8; i++)
      {
                for (j = 0; j < 8; j++)
                {
                        k = 7 - j;
                        output |= (input << k);
                }
      }
}

         其次,为了完成DES加密需要用到的密钥以及置换表等等这部分内容在table.h中定义
#ifndef __MY_TABLE_
#define __MY_TABLE_

//存储程序所需要的表与密钥

//初始置换表IP
const char IP_Table = { 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,
                                                        56,48,40,32,24,16,8,0,
                                                        58,50,42,34,26,18,10,2,
                                                        60,52,44,36,28,20,12,4,
                                                        62,54,46,38,30,22,14,6};   
//逆初始置换表IP^-1
const char IP_1_Table = { 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,
                                                          32,0,40,8,48,16,56,24};
//扩展表E
const char E_Table = { 31, 0, 1, 2, 3, 4,
                                                   3, 4, 5, 6, 7, 8,
                                                   7, 8, 9, 10, 11, 12,
                                                   11, 12, 13, 14, 15, 16,
                                                   15, 16, 17, 18, 19, 20,
                                                   19, 20, 21, 22, 23, 24,
                                                   23, 24, 25, 26, 27, 28,
                                                   27, 28, 29, 30, 31, 0};
//置换表P
const char P_Table = { 15, 6, 19, 20, 11, 27, 16,
                                                   0, 14, 22, 25, 4, 17, 30, 9,
                                                   1, 7, 23, 13, 31, 26, 2, 8,
                                                   18, 12, 29, 5, 21, 10, 3, 24};
//S盒
const char S =
                                {
                                        //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}},
                      //S2
                                        {{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}},
                      //S3
                                        {{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}},
                      //S4
                                        {{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}},
                      //S5
                                        {{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}},
                      //S6
                                        {{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}},
                      //S7
                                        {{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}},
                      //S8
                                        {{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}}
                                };

//置换选择1                       
int PC_1 = { 56,48,40,32,24,16,8,
                   0,57,49,41,33,25,17,
                   9,1,58,50,42,34,26,
                   18,10,2,59,51,43,35,
                   62,54,46,38,30,22,14,
                   6,61,53,45,37,29,21,
                   13,5,60,52,44,36,28,
                   20,12,4,27,19,11,3};

//置换选择2
int PC_2 = { 13,16,10,23,0,4,2,27,
                   14,5,20,9,22,18,11,3,
                   25,7,15,6,26,19,12,1,
                   40,51,30,36,46,54,29,39,
                   50,44,32,46,43,48,38,55,
                   33,52,45,41,49,35,28,31};
                               
//循环左移的位数
const char RoundLeft = {1, 1, 2, 2,
                                                        2, 2, 2, 2,
                                                        1, 2, 2, 2,
                                                        2, 2, 1, 1};
//加密密钥                                               
const char cKey = {"12345678"};
char bKey = { 0 };
//IV向量
char cIV = {"IVVector"};
#endif


         最后就是在主函数中对输入进行16轮的DES加密
#include <cstdio>
#include <cstring>
#include "table.h"
#include "CChar.h"

void DESAlgorithm(char cOrigData[]);      //DES算法主体
//对左边32比特进行加密
void XOREncryptLeft(char cLeftChar[], char cRightChar[], int iIndex);
void InitBitKey();      //将密钥初始化为比特形式且进行置换      
void EncryptByCBC(char cOrigData[], char cOrigData2[]);      //采用CBC模式加密
void EncryptByCFB(char cOrigData[], char cOrigData2[]); //采用CFB模式加密

int main()
{
      char cOrigData = {"1900Code"};
      char cOrigData2 = {"I 1900"};
      
      printf("加密前的数据: %s %s\n", cOrigData, cOrigData2);
      
      EncryptByCBC(cOrigData, cOrigData2);
      EncryptByCFB(cOrigData, cOrigData2);
      
      getchar();
      return 0;
}

void EncryptByCFB(char cOrigData[], char cOrigData2[])
{
      InitBitKey();
      DESAlgorithm(cIV);
      
      for (int i = 0; i < 9; i++) cOrigData ^= cIV;
      printf("CFB模式加密后的数据:%s ", cOrigData);
      
      InitBitKey();
      DESAlgorithm(cOrigData);
      
      for (int i = 0; i < 9; i++) cOrigData2 ^= cOrigData;
      printf("%s\n", cOrigData2);
      
      
      for (int i = 0; i < 9; i++) cOrigData2 ^= cOrigData;
      InitBitKey();
      DESAlgorithm(cOrigData);
      for (int i = 0; i < 9; i++) cOrigData ^= cIV;
      printf("CFB模式解密的数据:%s %s\n", cOrigData, cOrigData2);
      InitBitKey();
      DESAlgorithm(cIV);
}

void EncryptByCBC(char cOrigData[], char cOrigData2[])
{
      InitBitKey();
      for (int i = 0; i < 9; i++) cOrigData ^= cIV;
      DESAlgorithm(cOrigData);

      InitBitKey();
      for (int i = 0; i < 9; i++) cOrigData2 ^= cOrigData;
      DESAlgorithm(cOrigData2);
      printf("CBC模式加密后结果: %s %s\n", cOrigData, cOrigData2);
      
      InitBitKey();
      DESAlgorithm(cOrigData2);
      for (int i = 0; i < 9; i++) cOrigData2 ^= cOrigData;
      
      InitBitKey();
      DESAlgorithm(cOrigData);
      for (int i = 0; i < 9; i++) cOrigData ^= cIV;
      printf("CBC模式解密后的数据: %s %s\n", cOrigData, cOrigData2);
}

void DESAlgorithm(char cOrigData[])
{
      char cLeft = { 0 }, cRight = { 0 }, cOrigChar = { 0 };
      char cTmp = 0, cOrigCpyChar = { 0 };

      CharToBit(cOrigData, cOrigChar);
      
      memset(cOrigCpyChar, 0, sizeof(cOrigCpyChar));
      memcpy(cOrigCpyChar, cOrigChar, 64);      //进行初始置换
      for (int i = 0; i < 64; i++)
      {
                cOrigChar = cOrigCpyChar];
      }
      
      for (int i = 0; i < 32; i++)
      {
                cLeft = cOrigChar;
                cRight = cOrigChar;
      }
      
      for (int i = 0; i < 16; i++)      //进行16轮的加密
      {
                XOREncryptLeft(cLeft, cRight, i);
               
                //除最后一轮,交换左右两边的比特
                if (i < 15)
                {
                        for (int j = 0; j < 32; j++)
                        {
                              cTmp = cLeft;
                              cLeft = cRight;
                              cRight = cTmp;
                        }
                }
      }
      
      for (int i = 0; i < 32; i++)
      {
                cOrigChar = cLeft;
                cOrigChar = cRight;
      }

      memset(cOrigCpyChar, 0, sizeof(cOrigCpyChar));
      memcpy(cOrigCpyChar, cOrigChar, 64);      //进行逆初始置换
      for (int i = 0; i < 64; i++)
      {
                cOrigChar = cOrigCpyChar];
      }
      
      memset(cOrigData, 0, sizeof(cOrigData));
      BitToChar(cOrigChar, cOrigData);
}

void XOREncryptLeft(char cLeftChar[], char cRightChar[], int iIndex)
{
      char cExtendChar = { 0 };
      int i = 0, moveNum = 0, col = 0, row = 0, j = 0, k = 0, l = 0;
      char cLeftKey = { 0 }, cRightKey = { 0 };
      char bEncryptKey = { 0 };
      char bSData = { 0 };
      char cSData = 0;
      
      //进行扩展E置换
      for (i = 0; i < 48; i++)
      {
                cExtendChar = cRightChar];
      }
      
      for (i = 0; i < 28; i++)
      {
                cLeftKey = bKey;
                cRightKey = bKey;
      }
      
      moveNum = RoundLeft;
      for (i = 0; i < 28 - moveNum; i++)
      {
                cLeftKey = cLeftKey;
                cRightKey = cRightKey;
      }
      
      for (i = 28 - moveNum; i < 28; i++)
      {
                cLeftKey = 0;
                cRightKey = 0;
      }
      
      for (i = 0; i < 28; i++)
      {
                bKey = cLeftKey;
                bKey = cRightKey;
      }
      
      for (i = 0; i < 48; i++) bEncryptKey = bKey];
      
      for (i = 0; i < 48; i++) cExtendChar |= bEncryptKey;
      
      for (i = 0; i < 8; i++)
      {
                row = (cExtendChar - '0') * 2 + (cExtendChar - '0');
                col = (cExtendChar - '0') * 8 + (cExtendChar - '0') * 4
                        + (cExtendChar - '0') * 2 + (cExtendChar - '0');
                        
                cSData = S;
                if (cSData >= 8)
                {
                        bSData = 1;
                        cSData -= 8;
                }
               
                if (cSData >= 4)
                {
                        bSData = 1;
                        cSData -= 4;
                }
               
                if (cSData >= 2)
                {
                        bSData = 1;
                        cSData -= 2;
                }
               
                if (cSData == 1) bSData = 1;
      }
      
      for (i = 0; i < 32; i++) cLeftChar |= bSData;
}

void InitBitKey()
{
      int i = 0, j = 0, k = 0;
      char bCpyKey = { 0 };
      
      for (i = 0; i < 7; i++)
      {
                for (j = 0; j < 8; j++)
                {
                        k = 7 - j;
                        bKey = (cKey >> k) & 0x1;
                }
      }
      
      memset(bCpyKey, 0, sizeof(bCpyKey));
      memcpy(bCpyKey, bKey, 56);
      for (i = 0; i < 56; i++)
      {
                bKey = bCpyKey];
      }
}

          可以看到最终的输出,程序成功对输入的字符进行DES的加密解密

LegendSaber 发表于 2021-10-24 12:53

Eaglecad 发表于 2021-10-24 12:51
感谢分享,要是再讲解下原理啥的更好

哦。。那是因为这种经典的密码算法原理网上真的特别特别多。。再写的话挺多余的。。。。

LegendSaber 发表于 2021-10-24 13:18

nanaqilin 发表于 2021-10-24 13:07
我早就不是学生了,我是社会人事,现在做项目都是用openssl

实际项目肯定是调包啊。。。谁能写的比那些人好啊。。。

Eaglecad 发表于 2021-10-24 12:51

感谢分享,要是再讲解下原理啥的更好

nanaqilin 发表于 2021-10-24 12:58

你这个挺厉害的,我都是用openssl来实现加解密

LegendSaber 发表于 2021-10-24 13:00

nanaqilin 发表于 2021-10-24 12:58
你这个挺厉害的,我都是用openssl来实现加解密

谁还不是被挂科的恐惧逼了一把。。。

nanaqilin 发表于 2021-10-24 13:07

LegendSaber 发表于 2021-10-24 13:00
谁还不是被挂科的恐惧逼了一把。。。

我早就不是学生了,我是社会人事,现在做项目都是用openssl

大脑组织残缺 发表于 2021-10-24 13:34

DES,RSA 网络安全课上做过

yacc 发表于 2021-10-24 15:34

LegendSaber 发表于 2021-10-24 13:00
谁还不是被挂科的恐惧逼了一把。。。

当年被密码学考试支配的恐惧{:1_909:}

谁的坏叔叔 发表于 2021-10-24 19:39

有易语言的吗
页: [1] 2
查看完整版本: DES算法的C语言实现