C语言实现DES加密以及与硬件运行对比

本文档详细介绍了使用C语言实现DES加密算法的过程,包括各个置换表、函数及其实现。作者提供了代码并进行了性能测试,分别在Windows 10和Linux环境下比较了加密速率。结果显示,硬件实现的DES加密速度远超软件,达到三个数量级的差距。此外,还分享了硬件实现的DES加密速率和面积报告。
摘要由CSDN通过智能技术生成

本项目由之前课设成果整理改编上传,供大家交流分享。
其中内容包括代码等大部分为我自己的原创,基于开源的互联网精神,也会分享给大家。

C语言实现DES加密:

 #include <stdio.h>
 #include<string.h>
 #include <time.h>
 #include <stdlib.h>
//IP初始置换表
int IPS_Table[64]={
    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
};

//IP-1逆初始置换表
int IPE_Table[64] = {
        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
};
//PC1密钥通路初始置换
int PC1_Table[56] = {
        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
};
//PC2密钥通路输出置换
int PC2_Table[48] = {
        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
};
//S盒
int S_Box[8][4][16] = {
        // 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
        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,
        //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,
        //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,
        //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,
        //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,
        //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,
        //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
};
//E盒扩展
int E_Table[48] = {
        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
};
//f函数最后的P置换
int P_Table[32] = {
        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
};
//将二进制字符转换为二进制值
void BinChar2Value(char *source,char *dest)
{
    int i=0;
    for(i=0;i<strlen(source);i++)
    {
        if(source[i]=='0')
             dest[i]=0;
        if(source[i]=='1')
             dest[i]=1;
    }
}
//将16进制字符转换为二进制值
void Hex2Bin(char source[],char dest[],int len)
{
    int i=0;
    char temp[64]={0};
    char Dict[17][5] =
    {
        "0000", "0001", "0010", "0011",
        "0100", "0101", "0110", "0111",
        "1000", "1001", "1010", "1011",
        "1100", "1101", "1110", "1111",
    };
    for(i=0;i<len;i++){
        int n = 16;
        if (source[i] >='a'&&source[i]<='f')
            n=source[i]-'a'+10;
        if (source[i]>='A'&& source[i]<='F')
            n=source[i]-'A'+10;
        if (source[i]>='0'&& source[i]<='9')
            n=source[i]-'0';
        memcpy(&temp[i*4],Dict[n],4);
        BinChar2Value(temp,dest);
    }
    return;
}
//将十进制值转换为二进制值
void Dec2Bin(int num,char *dest)
{
    char temp[4];
    char Dict[17][5] =
    {
        "0000", "0001", "0010", "0011",
        "0100", "0101", "0110", "0111",
        "1000", "1001", "1010", "1011",
        "1100", "1101", "1110", "1111",
    };
    memcpy(temp,Dict[num],4);
    BinChar2Value(temp,dest);
}
//将二进制值转换为16进制字符
void Bin2Hex(char Bin[64],char Hex[16])
{
    int i;
    for(i=0;i<16;i++)
    {
        Hex[i]=Bin[0+4*i]*8+Bin[1+4*i]*4+Bin[2+4*i]*2+Bin[3+4*i];
        if(Hex[i]<10)
            Hex[i]=Hex[i]+'0';
        else Hex[i]=Hex[i]-10+'a';
    }
}
//按位异或运算
void Xor(char InA[],char InB[],int len)
{
    int i=0;
    for(i=0;i<len;i++)
    {
        InA[i]=InA[i]^InB[i];                  
    }
}
//DES初始和结束时的IP置换运算,通过改变输入的IP表进行选择
void IP_trans(char input[64],char output[64],int table[64])
{
    int i=0;
    for(i=0;i<64;i++)
    {
        output[i]=input[table[i]-1];
    }
}

//PC-1置换运算
void PC_1(char input[64],char output[56],int table[56])
{
    int i=0;
    for(i=0;i<56;i++)
    {
        output[i]=input[table[i]-1];
    }
}

//PC-2置换运算
void PC_2(char input[56],char output[48],int table[48])
{
    int i=0;
    for(i=0;i<48;i++)
    {
        output[i]=input[table[i]-1];
    }
}
//循环左移函数,为生成轮密钥服务
void Left_shift(char *keyin)
{
    char temp;
    temp=keyin[0];
    memmove(keyin,keyin+1,27);
    keyin[27]=temp;
}
//轮密钥生成函数
void KS(char Keyin[64],char Keyround[16][48])
{
    int i=0;
    char temp[56];              //只定义一个存储密钥,左右通过指针区分
    char PC1out[56]={0};
    char *keyL=&temp[0],*keyR=&temp[28];
    PC_1(Keyin,PC1out,PC1_Table);
    memcpy(keyL,PC1out,28);
    memcpy(keyR,PC1out+28,28);
    for(i=0;i<16;i++)
    {
        if((i==0)||(i==1)||(i==8)||(i==15))     //不同轮次,左移次数不同
        {
            Left_shift(keyL);
            Left_shift(keyR);
        }
        else
        {
            Left_shift(keyL);
            Left_shift(keyL);
            Left_shift(keyR);
            Left_shift(keyR);
        }
            PC_2(temp,Keyround[i],PC2_Table);
    }
}
//E扩展
void E(char input[32],char output[48],int table[48])
{
    int i=0;
    for(i=0;i<48;i++)
    {
        output[i]=input[table[i]-1];
    }
}
//S盒函数
void S(char input[48],char output[32],int table[8][4][16])
{
    int i,X,Y;
    char temp[4]={0};
    for(i=0,Y=0,X=0;i<8;i++)
    {
        X=(input[1+6*i]<<3)+(input[2+6*i]<<2)+(input[3+6*i]<<1)+input[4+6*i];
        Y=(input[0+6*i]<<1)+input[5+6*i];
        Dec2Bin(table[i][Y][X],temp);       //根据每输入的6位的值,计算出S盒表的坐标,取出十进制值,再转换为二进制值
        memcpy(output+4*i,temp,4);
    }
}
//P置换
void P(char input[32],char output[32],int table[32])
{

    int i=0;
    for(i=0;i<32;i++)
    {
        output[i]=input[table[i]-1];
    }
}
//f函数
void F_fun(char input[32],char Roundkey[48],char F_out[32])
{
    char E_out[48]={0};
    char S_out[32]={0};
    E(input,E_out,E_Table);
    Xor(E_out,Roundkey,48);
    S(E_out,S_out,S_Box);
    P(S_out,F_out,P_Table);
}
//DES运算的函数
void Des_fun(char datain[64],char key[64],char dataout[64])
{
    int i;
    char IPS_out[64]={0};
    char RoundKey[16][48];
    char temp[64]={0};          //只定义一个数组存储,L,R通过指针改变其值
    char *L=&temp[0],*R=&temp[32];
    char F_out[32]={0};
    IP_trans(datain,IPS_out,IPS_Table);     //初始IP置换
    memcpy(L,IPS_out,32);               //分出左右
    memcpy(R,IPS_out+32,32);
    KS(key, RoundKey);                  //生成轮密钥,并存储
    for(i=0;i<16;i++)
    {
        F_fun(R,RoundKey[i],F_out);     //循环执行16轮
        Xor(F_out,L,32);
        memcpy(L,R,32);
        memcpy(R,F_out,32);
    }
    memcpy(R, L, 32);
    memcpy(L, F_out, 32);               //注意:最后结束循环后,左右不需交换了(再换一次换回来)
    IP_trans(temp,dataout,IPE_Table);
}

void main()
{
    int i;
    char plaintext[17];         //plaintext和key必须17位,因为strcpy复制会把最后的结束位复制过来,导致溢出
    char key[17];
    char ciphertext[17]={0};    //此初始赋0,方便最后puts输出结束
    char plaintext_bin[64];
    char key_bin[64];
    char ciphertext_bin[64];
    clock_t start, finish;       //计时变量
    double  total_time;

    start = clock();
    //去掉下方注释可改变为手动输入
    /*printf("输入明文(16位hex):\n");
    gets(plaintext);
    printf("输入密匙(16位hex):\n");
    gets(key);      */
    strcpy(plaintext,"123456abcd132536");
    strcpy(key,"aabb09182736ccdd");
    Hex2Bin(plaintext,plaintext_bin,16);    //将接收到的字符串转换为二进制值
    Hex2Bin(key,key_bin,16);
    start = clock();
    for (i = 0; i < 10000;i++)      //循环10000次,计算平均时间
        Des_fun(plaintext_bin, key_bin, ciphertext_bin);
    finish = clock();
    Bin2Hex(ciphertext_bin,ciphertext);     //将加密信息转换回16进制字符串以便显示
    total_time = (double)(finish - start)/ CLOCKS_PER_SEC;
    printf("Ciphertext:\n");
    puts(ciphertext);                       //显示密文
    printf( "%f seconds\n",total_time);     //显示所用时间
    system("pause");
}

此处代码参考了网上的代码设计,但是我找到的代码无法正常使用,我又重新编写测试解决了一系列问题。

DES程序导图此导图是我为C语言程序编写的导图,也能大概看出DES加密的原理。

硬件上提供了一版DES的Verilog代码可以通过FPGA平台运行。
链接:https://pan.baidu.com/s/1YY8qO1J_QPC0YpRh415cYw
提取码:siwu

软硬件速率对比
C语言软件运行情况:
环境:C语言编译 gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project
运行 WIN10教育版 版本号1803 处理器:Intel® Core™ i7-7700HQ CPU @ 2.80GHz
因为软件运行受到计算机当前状态的波动,故截取了三次结果,求平均值
以下都是每10000次64位DES加密所需时间。
在这里插入图片描述在这里插入图片描述在这里插入图片描述

经过计算平均每秒可计算46012次,即加密速率2944768‬ bit/s。

接下来我更换了环境,在老师提供的Linux虚拟机上运行
将代码通过本地分享到虚拟机中,拷贝到虚拟机内的目录里,用gcc编译,并同样运行三次,求得平均时间。
在这里插入图片描述
经计算每秒可计算27272次,即1745408‬ bit/s
此时软件运行速率比Win10下要慢,个人仍为可能是虚拟机设置上只调用了部分电脑的硬件,没有充分发挥硬件的性能。
硬件综合结果:

在这里插入图片描述
在这里插入图片描述
时钟周期为3.9ns,delay设置为0.3,此时可slack可以符合,且时钟周期最小
以DES硬件极限16周期加密一次计算,平均62.4ns一次,即每秒16025641次,加密速率1025641024‬ bit/s。
由此可见,硬件加密的速率是软件的3个数量级以上。
在这里插入图片描述

附:面积报告

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值