C语言实现des加解密_des加密c语言输入为十六位十六进制-程序员宅基地

技术标签: des加密  

简介:des算法是一种对称加密,通过同一组秘钥进行加密和解密。利用64位秘钥对64位数据进行加密生成一组新的64位数据,其中的转换都是利用统一的表格数组对秘钥和数据转换(这些表格都是全网统一的,有些博客中分享的表格数据含有少数错误数据且极难发现,加解密数据截然不同)

例   网上的错误表格数据:

 

以下为代码,这里的main函数传参加解密选项以及秘钥和数据,测试用只能传入64位秘钥和64位数据。选项1:加密,8字节秘钥可见字符,8字节数据可见字符 ; 选项2:加密,16位16进制秘钥,16位16进制数据(转换也是64位) ; 选项3:解密,16位16进制秘钥,16位16进制数据(转换也是64位)。。

流程:主要是表格对秘钥和数据的转换,以及分组后的秘钥对每轮数据的异或。
1、pc_1表对64位秘钥除去每字节的校验位后按表格位置打乱秘钥获得新的56位秘钥。
2、move表循环对56位秘钥按表格数据偏移16次,并将每次偏移后的数据记到16个内存中。(与位运算左移不同,此处左移会将左移的部分不到最后,而不是在尾部补0)
3、pc_2表在16组56位的秘钥中按表格数据顺序取内容会的16组48位秘钥,秘钥转换结束。
4、ip表打乱64位明文或密文。
5、将64位数据分成左右两部分L0和R0,进行16次循环(解密时key顺序倒过来输入到func即可):
       loop1:    L1=R0,R1=L0^func(R0 , key1);
       loop2:    L2=R1,R2=L1^func(R1 , key2);
       ......
       loop16:  L16=R15 ,R16=L15^func(R15 , key16);

       注:func流程    步骤1: ext表对32位上轮右半段数据拓展成48位步骤2: 48位数据域48位秘钥key异或步骤3: 48位数据拆成八组6位二进制数据,6位数据首尾组成一段2位的二进制,中间四个组成一段4位的二进制得到(x,y)值,其中x为0到3,y为0到15.。。。8组xy值分别对应8个s盒数据使用xy为下标取值,取出的十进制数可转成4位二进制,8段合起来组成一个32位数据步骤4: 左后p表将生成的32位数据打乱顺序。
6、再将左值和右值倒置R16L16,ipr表对这段64位数据打乱顺序得到最终结果。

 

头文件:tables.h

#ifndef _TABLES_H_
#define _TABLES_H_

//密钥第一次置换矩阵 
//64位秘钥跨过8 16 24 32 40 48 56 64位取得打乱的56位
int TBL_PC_1[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 
};

//半截秘钥偏移表
//将56位秘钥分为左右两段28位,分别左移16次并保存每次的值,再将左右两段合并成16组数据
const int TBL_MOVE[16] = {
    1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};

//密钥第二次置换矩阵 
//用上一步偏移后的16组数据,取56位秘钥的48位组成16段子秘钥
int TBL_PC_2[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 
};

//IP置换矩阵 
//64位明文打乱顺序
int TBL_IP[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 
};

//扩展矩阵
//分成两段32位左右值,分别拓展成48位,其中有重复位..48位再与48位子秘钥进行异或
int TBL_EXT[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 
};

//8个S盒
//48位数据按6位一段分成8组获得下标取s1-s8表中的值,获取32位数据。。
//6位数据首位2位一段,中间4位为一段   例:100011=(11,0001)=(3,1)  取第四行第二列的值
int TBL_S1[4][16] = {                        
    {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 TBL_S2[4][16] = {  
    {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 TBL_S3[4][16] = {
    {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 TBL_S4[4][16] = { 
    { 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 TBL_S5[4][16] = {  
    { 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 TBL_S6[4][16] = {  
    {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 TBL_S7[4][16] = {
    { 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 TBL_S8[4][16] = {  
    {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},
};

//P 盒
//8轮s盒查询结果获得的32位,再次进行顺序打乱
int TBL_P[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 
};

//逆IP置换矩阵
//16轮迭代后,再将左右两段交换,使用逆置换表打乱顺序得到最终加密结果 
int TBL_IPR[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
};


#endif

源文件:

#include "tables.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

#define _ENC_OPT_ 1
#define _DEC_OPT_ 2

unsigned char agSboxMapList[16][4] = {
    "0000",  /* 0*/
    "0001",  /* 1*/
    "0010",  /* 2*/
    "0011",  /* 3*/
    "0100",  /* 4*/
    "0101",  /* 5*/
    "0110",  /* 6*/
    "0111",  /* 7*/
    "1000",  /* 8*/
    "1001",  /* 9*/
    "1010",  /*10*/
    "1011",  /*11*/
    "1100",  /*12*/
    "1101",  /*13*/
    "1110",  /*14*/
    "1111",  /*15*/
};

int hex_str2bytes(unsigned char *in ,  unsigned char *out , int *outLen);
int proc_enc_dec(unsigned char *key , int key_len ,
            unsigned char *input , int in_put_len ,
            unsigned char *output , int *output_len , 
            int opt);
void bytes2bits_str(unsigned char *in , int inLen , unsigned char *out);
void bits_str2bytes(unsigned char *in , unsigned char *out , int *outLen);
void bits_str2deci(unsigned char *str , int *num);
void getBitsByPc1(unsigned char *in , unsigned char *out);
void getBitsListByMove(unsigned char *alKey56Bits , unsigned char alKeyLeft28BitsList[][28+1] , 
                        unsigned char alKeyRight28BitsList[][28+1]);
void getBitsListByPc2(unsigned char in[][56+1] , unsigned char out[][48+1]);
void getBitsByIp(unsigned char *in , unsigned char *out);
unsigned char *getBitsByFunc(unsigned char *data , unsigned char *key, unsigned char *result);
void xor_bits_str(unsigned char *str1 , unsigned char *str2 ,unsigned char *result);
void getBitsByIpr(unsigned char *in , unsigned char *out);


//16进制字符串转字节数组
int hex_str2bytes(unsigned char *in ,  unsigned char *out , int *outLen)
{
    int i = 0 , j = 0;
    int num = 0;
    int tmp = 0;
    for (i = 0 ; i < strlen((char *)in) ; i++)
    {
        if(in[i] < 58 && in[i] > 47) //0-9
            tmp = in[i]-48;
        else if(in[i] < 71 && in[i] > 64) //A-F
            tmp = 10+in[i]-65;
        else if(in[i] < 103 && in[i] > 96) //a-f
            tmp = 10+in[i]-97;
        else 
        {
            printf("Invalid arg!\n");
            return -1;
        }

        if(i%2 == 0)
            num = tmp*16;
        else
        {
            num += tmp;
            out[j++] = num;
        }
    }
    *outLen = j;
    return 0;
}

//字节数组转二进制字符数组
void bytes2bits_str(unsigned char *in , int inLen , unsigned char *out)
{
    //将二进制写为字符'0'和'1'而非0和1 , 方便打印观察
    int i = 0;
    for(i = 0 ; i<(inLen*8) ; i++)
    {
        if( in[i/8] & (0x01<<(7-i%8)) )
            out[i] = '1';
        else
            out[i] = '0';
    }
}

//二进制字符数组转字节数组
void bits_str2bytes(unsigned char *in , unsigned char *out , int *outLen)
{
    //将二进制字符数组'0'和'1'转换为字节数组    
    int i = 0 , j = 0;
    int num = 0;
    for(i = 0 ; i<strlen((char *)in) ; i++)
    {
        if(in[i] == '1')
        {
            num += pow(2,7-i%8);
        }
        if((i+1)%8 == 0)
        {
            out[j++] = num;
            num = 0;
        }
    }
    *outLen = j;
}

//二进制字符数组转十进制数
void bits_str2deci(unsigned char *str , int *num)
{
    int i = 0 , j = 0;
    *num = 0;
    //从最右最低位开始累加计算
    for(i = strlen((char *)str)-1 ; i >= 0 ; i--)
    {
        if(str[i] == '1')
        {
            *num += pow(2,j);
        }
        j++;
    }
}

//64位秘钥根据pc_1表获取56位秘钥
void getBitsByPc1(unsigned char *in , unsigned char *out)
{
    int i = 0;
    int index = 0;
    for(i = 0 ; i < 56 ; i++)
    {
        index = TBL_PC_1[i];
        out[i] = in[index-1];
    }
}
    
//对32段28位半段秘钥循环往左偏移,左边部分不丢弃填充到尾部
void getBitsListByMove(unsigned char *alKey56Bits , unsigned char alKeyLeft28BitsList[][28+1] , 
                        unsigned char alKeyRight28BitsList[][28+1])
{
    int i = 0;
    int ilOff = 0;

    memcpy(alKeyLeft28BitsList[0] , alKey56Bits , 28);
    memcpy(alKeyRight28BitsList[0] , alKey56Bits+28 , 28);

    for(i = 0 ; i < 16 ; i++)
    {
        ilOff = TBL_MOVE[i];
        memcpy(alKeyLeft28BitsList[i+1] , alKeyLeft28BitsList[i]+ilOff , 28-ilOff);
        memcpy(alKeyLeft28BitsList[i+1]+28-ilOff , alKeyLeft28BitsList[i] , ilOff);
        memcpy(alKeyRight28BitsList[i+1] , alKeyRight28BitsList[i]+ilOff , 28-ilOff);
        memcpy(alKeyRight28BitsList[i+1]+28-ilOff , alKeyRight28BitsList[i] , ilOff);
    }
}

//对16组56位左右两段秘钥数据根据pc_2选取48位并打乱顺序
void getBitsListByPc2(unsigned char in[][56+1] , unsigned char out[][48+1])
{
    int i = 0;
    int j = 0;
    int index = 0;

    for(i = 0 ; i < 16 ; i++)
    {
        for(j = 0 ; j < 48 ; j++)
        {
            index = TBL_PC_2[j];
            out[i][j] = in[i][index-1];
        }
        
    }
}

//64位加解密数据根据ip表打乱顺序
void getBitsByIp(unsigned char *in , unsigned char *out)
{
    int i = 0;
    int index = 0;
    for(i = 0; i<64 ; i++)
    {
        index = TBL_IP[i];
        out[i] = in[index-1];
    }
}

//16轮迭代处理函数  
//输入上一轮右半段32位数据和对应子秘钥
//拓展成48位,与子秘钥异或,每6位数据分成8组,收尾与中间段组成坐标x,y在s盒八组数据找到对应8个16进制数
//将8个16进制数转成二进制字符数组得到32位,最后根据评标打乱顺序得到函数结果
unsigned char *getBitsByFunc(unsigned char *data , unsigned char *key , unsigned char *result)
{
    int i = 0;
    int index = 0;
    char alEData[48+1] = {0};
    int x = 0;
    int y = 0;
    unsigned char alXBits[2+1] = {0};
    unsigned char alYBits[4+1] = {0};
    unsigned char alSboxRet[32+1] = {0};

    printf("proc data  [%s]\n" , data);
    //32位拓展成48位
    for(i = 0 ; i<48 ; i++)
    {
        index = TBL_EXT[i];
        alEData[i] = data[index-1];
    }
    printf("data by ext[%s]\n" , alEData);

    printf("XOR key    [%s]\n" , key);
    //与48位秘钥异或
    for(i = 0 ; i<48 ; i++)
    {
        if(alEData[i] == key[i])
            alEData[i] = '0';
        else
            alEData[i] = '1';
    }
    printf("XOR result [%s]\n" , alEData);
    
    //s盒取值
    //分8组6位取s盒坐标,对应s1-s8八组数据取值
    for(i = 0 ; i<8 ; i++)
    {
        memcpy(alXBits , alEData+i*6 , 1);
        memcpy(alXBits+1 , alEData+i*6+5 , 1);
        memcpy(alYBits , alEData+i*6+1 , 4);
        bits_str2deci(alXBits , &x);
        bits_str2deci(alYBits , &y);
        if(i+1 == 1)
        {
            //获得s表对应的16进制数,比转换为4位二进制字符依次赋值到结果,根据全局变量获取16进制映射值
            memcpy(alSboxRet+i*4 , agSboxMapList[TBL_S1[x][y]] , 4);
        }
        else if(i+1 == 2)
            memcpy(alSboxRet+i*4 , agSboxMapList[TBL_S2[x][y]] , 4);
        else if(i+1 == 3)
            memcpy(alSboxRet+i*4 , agSboxMapList[TBL_S3[x][y]] , 4);
        else if(i+1 == 4)
            memcpy(alSboxRet+i*4 , agSboxMapList[TBL_S4[x][y]] , 4);
        else if(i+1 == 5)
            memcpy(alSboxRet+i*4 , agSboxMapList[TBL_S5[x][y]] , 4);
        else if(i+1 == 6)
            memcpy(alSboxRet+i*4 , agSboxMapList[TBL_S6[x][y]] , 4);
        else if(i+1 == 7)
            memcpy(alSboxRet+i*4 , agSboxMapList[TBL_S7[x][y]] , 4);
        else if(i+1 == 8)
            memcpy(alSboxRet+i*4 , agSboxMapList[TBL_S8[x][y]] , 4);
    }

    printf("after SBOX [%s]\n" , alSboxRet);

    //p表打乱
    for(i = 0; i < 32 ; i++)
    {
        index = TBL_P[i];
        *(result+i) = alSboxRet[index-1];
    }
    printf("after TBL_P[%s]\n" , result);

    return result;

}

//异或上一轮左值和迭代处理函数结果得到32位值,为本轮右值
void xor_bits_str(unsigned char *str1 , unsigned char *str2 , unsigned char *result)
{
    int i = 0;
    for(i = 0 ; i<32 ;i++)
    {
        if(*(str1+i) == *(str2+i))
        {
            memcpy(result+i , "0" , 1);
        }
        else
            memcpy(result+i , "1" , 1);
    }
}

//将16轮后的R16和L16组成的数据根据逆置换表打乱顺序得到加解密的最终结果
void getBitsByIpr(unsigned char *in , unsigned char *out)
{
    int i = 0;
    int index = 0;
    for(i = 0; i < 64 ;i++)
    {
        index = TBL_IPR[i];
        out[i] = in[index-1];
    }
}

//加解密主函数,根据opt判断加密还是解密
int proc_enc_dec(unsigned char *key , int key_len ,
            unsigned char *input , int in_put_len ,
            unsigned char *output , int *output_len ,
            int opt)
{
    int i = 0;
    unsigned char alKeyHexStr[16+1] = {0};
    unsigned char alKeyVisibleBits[1024] = {0};
    unsigned char alKey56Bits[56+1] = {0};
    unsigned char alKeyLeft28BitsList[17][28+1] = {
   {0}};
    unsigned char alKeyRight28BitsList[17][28+1] = {
   {0}};
    unsigned char alKey56BitsList[16][56+1] = {
   {0}};
    unsigned char alKey48BitsList[16][48+1] = {
   {0}};

    unsigned char alInputHexStr[16+1] = {0};
    unsigned char alInputVisibleBits[1024] = {0};
    unsigned char alInputByIp[64+1] = {0};
    unsigned char alInputLeftDataList[1+16][32+1] = {
   {0}};
    unsigned char alInputRightDataList[1+16][32+1] = {
   {0}};
    unsigned char alInputAfterFunc[32+1] = {0};
    unsigned char alInputAfterXor[32+1] = {0};
    unsigned char alInputLast[64+1] = {0};

    unsigned char alEncBinRet[64+1] = {0};
    unsigned char alEncStrRet[8+1] = {0};
    int ilEncStrRetLen = 0;
    unsigned char alEncHexRet[16+1] = {0};

    for(i = 0 ; i<8 ; i++)
    {
        sprintf((char *)(alKeyHexStr+i*2) , "%02x" , key[i]);
        sprintf((char *)(alInputHexStr+i*2) , "%02x" , input[i]);
    }
   
    //将参数中的8字节数据转换成64位二进制可见字符
    bytes2bits_str(key , strlen((char *)key) , alKeyVisibleBits);
    bytes2bits_str(input , strlen((char *)input) , alInputVisibleBits);

    puts("*************************key****************************");
    printf("64bits:[%s]\n" , alKeyVisibleBits);
    //获取56位秘钥
    getBitsByPc1(alKeyVisibleBits , alKey56Bits);
    puts("-----------------------------------");
    printf("56bits:[%s]\n" , alKey56Bits);
    //获取32段左偏移秘钥段
    getBitsListByMove(alKey56Bits , alKeyLeft28BitsList , alKeyRight28BitsList); 
    for(i = 0; i<16 ; i++)
    {
        memcpy(alKey56BitsList[i] , alKeyLeft28BitsList[i+1] , 28);
        memcpy(alKey56BitsList[i]+28 , alKeyRight28BitsList[i+1] , 28);
    }
    puts("-----------------------------------");
    for(i = 0 ; i<17 ; i++)
    {
        printf("i=[%d] , key[%s,%s]\n" , i , alKeyLeft28BitsList[i] , alKeyRight28BitsList[i]);
    }
    //16组56位秘钥生成48位最终子秘钥
    getBitsListByPc2(alKey56BitsList , alKey48BitsList);
    puts("-----------------------------------");
    for(i = 0 ; i<16 ; i++)
    {
        printf("i=[%d] , child_key[%s]\n" , i ,alKey48BitsList[i]);
    }
    //打乱加解密数据
    getBitsByIp(alInputVisibleBits , alInputByIp);
    puts("************************data****************************");
    printf("64bits data:[%s]\n" , alInputVisibleBits);
    printf("after TblIp:[%s]\n" , alInputByIp);

    //迭代16次左右交替处理数据
    memcpy(alInputLeftDataList[0] , alInputByIp , 32);
    memcpy(alInputRightDataList[0] , alInputByIp+32 , 32);
    for(i = 1 ; i<=16 ; i++)
    {
    puts("-----------------------------------");
    printf("round [%d]   (‘>>’指向此轮结果)\n" , i);
        //左值等于上一次的右值
        memcpy(alInputLeftDataList[i] , alInputRightDataList[i-1] , 32);
        printf(">>left var [%s]\n" , alInputLeftDataList[i-1]);
        //右值等于上一次的左值与函数处理后的上一次右值异或
        if(opt == _ENC_OPT_)
        {
            xor_bits_str(alInputLeftDataList[i-1] , 
                        getBitsByFunc(alInputRightDataList[i-1] , alKey48BitsList[i-1] , alInputAfterFunc) ,
                        alInputAfterXor);
        }
        else if(opt == _DEC_OPT_)
        {
            xor_bits_str(alInputLeftDataList[i-1] , 
                        getBitsByFunc(alInputRightDataList[i-1] , alKey48BitsList[16-i] , alInputAfterFunc) ,
                        alInputAfterXor);
        }
        else
        {
            printf("[ERROR] Invalid option!\n");
            return -1;
        }

        memcpy(alInputRightDataList[i] , alInputAfterXor , 32);
        printf("XOR left   [%s]\n" , alInputLeftDataList[i-1]);
        printf("XOR result [%s]\n" , alInputAfterXor);
        printf(">>right var[%s]\n" , alInputRightDataList[i]);
        printf("left,right [%s]~[%s]\n" , alInputLeftDataList[i] , alInputRightDataList[i]);
    }

    //最终再将右值和左值倒放
    memcpy(alInputLast , alInputRightDataList[16] , 32);
    memcpy(alInputLast+32 , alInputLeftDataList[16] , 32);
    puts("-----------------------------------");
    printf("data=R,L   [%s]\n" , alInputLast);
    //逆置换64位数据获得最终加解密结果
    getBitsByIpr(alInputLast , alEncBinRet);
    printf("after IPR  [%s]\n" , alEncBinRet);
    if(opt == _ENC_OPT_) puts("【加密ENCRYPT】 结果:");
    else if(opt == _DEC_OPT_) puts("【解密DECRYPT】 结果:");
    printf("InputHexStr[%s] ~ keyHexStr[%s]\n" , alInputHexStr , alKeyHexStr);
    printf("bin format [%s]\n" , alEncBinRet);
    //64为可见字符转换成8字节数据发回主函数
    bits_str2bytes(alEncBinRet , alEncStrRet , &ilEncStrRetLen);
    for(i = 0 ; i<8 ; i++)
    {
        sprintf((char *)(alEncHexRet+i*2) , "%02x" , alEncStrRet[i]);
    }
    memcpy(output , alEncStrRet , ilEncStrRetLen);
    *output_len = ilEncStrRetLen;
    printf("hex format [%s]\n" , alEncHexRet);
    puts("**************************************END*******************************");
    return 0;
}


int main(int argc,char **argv)
{
    if(argc != 4)
    {
        printf("Usage: des_tool [1/2/3] [key] [input]\n(1: [encrypt] char8 key , char8 data)\n(2: [encrypt] hex16 key , hex16 data)\n(3: [decrypt] hex16 key , hex16 data)\n");
        return -1;
    }
    if(strcmp(argv[1] , "1") != 0 && strcmp(argv[1] , "2") != 0 && strcmp(argv[1] , "3") != 0)
    {
        printf("Usage: des_tool [1/2/3] [key] [input]\n(1: [encrypt] char8 key , char8 data)\n(2: [encrypt] hex16 key , hex16 data)\n(3: [decrypt] hex16 key , hex16 data)\n");
        return -1;
    }
    if(strcmp(argv[1] , "1") == 0 && 
        (strlen(argv[2]) != 8 || strlen(argv[3]) != 8))
    {
        printf("Usage: des_tool [1/2/3] [key] [input]\n(1: [encrypt] char8 key , char8 data)\n(2: [encrypt] hex16 key , hex16 data)\n(3: [decrypt] hex16 key , hex16 data)\n");
        return -1;
    }
    else if(strcmp(argv[1] , "1") != 0 &&
        (strlen(argv[2]) != 16 || strlen(argv[3]) != 16))
    {
        printf("Usage: des_tool [1/2/3] [key] [input]\n(1: [encrypt] char8 key , char8 data)\n(2: [encrypt] hex16 key , hex16 data)\n(3: [decrypt] hex16 key , hex16 data)\n");
        return -1;
    }

    
    int ilRet = 0;
    int ilType = 0;
    unsigned char alKey[8+1] = {0};
    unsigned char alInput[8+1] = {0};
    unsigned char alOutput[8+1] = {0};
    int ilKeyLen = 0;
    int ilInputLen = 0;
    int ilOutputLen = 0;

    ilType = atoi(argv[1]);

    if(ilType == 1)
    {
        //可见明文,可见密码,加密
        strcpy((char *)alKey , argv[2]);
        strcpy((char *)alInput , argv[3]);
        ilRet = proc_enc_dec(alKey , strlen((char *)alKey) , alInput , strlen((char *)alInput) , 
                        alOutput , &ilOutputLen , _ENC_OPT_);
    }
    else if(ilType == 2)
    {
        //参数16进制明文和密码,加密
        if(hex_str2bytes((unsigned char *)argv[2] , alKey , &ilKeyLen))
            return -1;
        if(hex_str2bytes((unsigned char *)argv[3] , alInput, &ilInputLen))
            return -1;
        ilRet = proc_enc_dec(alKey , ilKeyLen , alInput , ilInputLen , 
                        alOutput , &ilOutputLen , _ENC_OPT_);
    }
    else if(ilType == 3)
    {
        //参数16进制密文和密码,解密
        if(hex_str2bytes((unsigned char *)argv[2] , alKey , &ilKeyLen))
            return -1;
        if(hex_str2bytes((unsigned char *)argv[3] , alInput, &ilInputLen))
            return -1;
        ilRet = proc_enc_dec(alKey , ilKeyLen , alInput , ilInputLen , 
                        alOutput , &ilOutputLen , _DEC_OPT_);
    }
    else
    {
        printf("Invalid args!");
        return -2;
    }

    if(ilRet != 0)
        return -1;

    return 0;
}

Makefile:

TARGET = des_tool
DEPEND = des_tool.o
CC = gcc -g -Wall
RM = rm -f
LIB = -lm

.c.o :
	$(CC) -c $^ -o $@

$(TARGET) : $(DEPEND)
	$(CC) $^ -o $@ $(LIB)

.PHONY : clean
clean :
	$(RM) $(TARGET) *.o

./des_tool  2 133457799bbcdff1 0123456789abcdef
加密结果:85e813540f0ab405

./des_tool  3 133457799bbcdff1 85e813540f0ab405
解密结果:0123456789abcdef

输入明文秘钥和数据加密:

./des_tool  1 12345678 aaaaaaaa
加密结果:72dca13c37223cf0

./des_tool  3 3132333435363738 72dca13c37223cf0
解密结果:6161616161616161

下一篇3des算法:https://blog.csdn.net/jiujiederoushan/article/details/100014036

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jiujiederoushan/article/details/100008198

智能推荐

div阻止点击穿透+实现点击穿透_div 穿透-程序员宅基地

文章浏览阅读5.2w次,点赞16次,收藏40次。div阻止点击穿透+实现点击穿透_div 穿透

监听配置详解-程序员宅基地

文章浏览阅读980次。监听作用:一般来说本机不需要配置监听,只有远程客户端连接数据库时才需要服务器端配置监听,客户端配置TNS,一旦连接建立,监听就完成了使命。 一、配置监听 监听配置文件..._对同一个服务器的两个实例,客户端需要配置两个监听吗

MPI并行编程计算π值及PSRS排序-程序员宅基地

文章浏览阅读8.8k次,点赞5次,收藏35次。什么是MPIMPI(Message Passing Interface)是目前最重要的一个基于消息传递的并行编程工具,它具有移植性好、功能强大、效率高等许多优点,而且有多种不同的免费、高效、实用的实现版本,几乎所有的并行计算机厂商都提供对它的支持,成为了事实上的并行编程标准。MPI是一个库,而不是一门语言,因此对MPI的使用必须和特定的语言结合起来进行。MPI不是一个独立的自包含系统,而是建立在本地_psrs排序

python爬虫之selenium知识点记录-程序员宅基地

文章浏览阅读1.8k次,点赞16次,收藏24次。selenium本身是一个自动化测试工具。它可以让python代码调用浏览器。并获取到浏览器中加载的各种资源。我们可以利用selenium提供的各项功能。帮助我们完成数据的抓取。

Gitlab email server 报错「Traceback (most recent call last): 1: from (irb):1 EOFError (end of file)」_eoferror: end of file reached-程序员宅基地

文章浏览阅读2k次。自建的gitlab服务配置邮箱服务配置完成了之后,测试邮箱服务报错报错内容Traceback (most recent call last): 1: from (irb):1EOFError (end of file reached)解决过程Google了很久,有的是将ssl 改为false,有的是端口改为25,576但改成了25之后,也有另外的报错, connection timeout之类的,然后有人说是aliyun的EC2服务器默认关闭了25端口的访问最后_eoferror: end of file reached

使用Neo4j进行全栈Web开发_neo4jweb-程序员宅基地

文章浏览阅读7.1k次。在开发一个全栈web应用时,作为整个栈的底层,你可以在多种数据库之间进行选择。作为事实的数据源,你当然希望选择一种可靠的数据库,但同时也希望它能够允许你以良好的方式进行数据建模。在本文中,我将为你介绍Neo4j,当你的数据模型包含大量关联数据以及关系时,它可以成为你的web应用栈的基础的一个良好选择。Neo4j是什么?Neo4j是一个图形数据库,这也就意味着它的数据并非保存在表或集合中,而是保存为节_neo4jweb

随便推点

苹果状态栏HTML,iphoneX 适配客户端H5页面的方法教程-程序员宅基地

文章浏览阅读832次。前言目前,很多APP设计师小伙伴已经开始转向H5前端开发啦,但是解决所有iPhone和安卓机型的适配问题是我们的重中之重。无论是设计APP还是写前端H5.都是要考虑移动端的兼容性。由于iphoneX做了全面屏并且还保留一块小刘海,因此很多以前的移动端H5页面需要结合App客户端做出相应的适配,具体如下:1、顶部通栏之前的客户端一直采用状态栏20pt+导航栏44pt的做法。由于iphoneX多了一块..._ios html 通知栏

人工神经网络持续学习的脑激励重放_brain-inspired replay for continual learning with -程序员宅基地

文章浏览阅读1.8k次,点赞9次,收藏10次。目录Brain-inspired replay for continual learning with artificial neural networksResults比较连续学习方法Brain-inspired replay for continual learning with artificial neural networks作者:Gido M. van de Ven, Hava T. Siegelmann, Andreas S. Toliassolution1:不断学习以前的例子(效率低)_brain-inspired replay for continual learning with artificial neural networks

Linux 之旅 19:启动流程、模块管理与loader_default.target-程序员宅基地

文章浏览阅读1.2k次。Linux 之旅 19:启动流程、模块管理与loader图源:pexelsLinux启动流程分析启动流程一览通常操作系统的启动过程可以分为以下几个步骤:加载BIOS以获取硬件信息并进行自检,这样就可以获取到第一个可启动设备。读取并执行第一个可启动设备的MBR内的启动引导程序(grub2、spfdisk等)。根据启动引导程序的设置加载Kernel,Kernel进行硬件检测并加载需要的驱动和模块。Kernel启动Systemd进程,并且用default.target模式准备操作系统环境:_default.target

求助Fatal error: Class 'think\App' not found in C:\``thinkphp\start.php on line 19Fatal error: Class '_think/app notfound-程序员宅基地

文章浏览阅读3.9k次。公司网站程序无法进入,出现了这两行代码求助Fatal error: Class ‘think\App’ not found in C:``thinkphp\start.php on line 19Fatal error: Class ‘think\App’ not found in C:``\thinkphp\library\think\exception\Handle.php on line ..._think/app notfound

开始使用Mac OS X——写给Mac新人-程序员宅基地

文章浏览阅读118次。写这篇文档的原因有两个,一、身边使用Mac的朋友越来越多,经常会有人来咨询一些常见的使用问题,比如:“为什么把界面右上角的红色按钮叉掉,程序还没有关闭?”之类。而且我也不愿意看到很多人使用OSX时仅仅用到最基本的功能。让他们去Google吧,查完了回来还得问你,所以准备就我的个人经验写一个入门篇,这样再有人问的话,直接把博文地址甩给他就行啦。二、前几天写了一篇文章《从Mac OS X的L..._新手改用mac os

启动elasticsearch时报错log权限不够_./elasticsearch权限不够-程序员宅基地

文章浏览阅读7.5k次,点赞4次,收藏2次。启动es是非root用户启动,报错权限不够这是只要在root用户下为普通用户授权就可以了例如我的普通用户名是wsbchown wsb /usr/soft/elasticsearch-6.2.2 -R_./elasticsearch权限不够

推荐文章

热门文章

相关标签