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

智能推荐

php中提示注意怎么解决,PHP中操作MySQL时一定要注意-程序员宅基地

文章浏览阅读53次。恍惚恍惚又来到了文章的学习,想必大家又有很多问题吧!对于 MySQL ,第一件你必须牢记的是它的每一行命令都是用分号 (;) 作为结束的,但……没有完全绝对的事,在这儿也是一样,当一行 MySQL **入在 PHP 代码中时,最好把后面的分号省略掉.例如mysql_query ("INSERT INTO tablename (first_name, last_name) VALUES ('$fir..._php 不提示注意

Redis从入门到精通(二十)Redis最佳实践(一)优雅的Key结构、拒绝BigKey

分析RDB快照文件,全面分析内存使用情况。,在raw模式下内存空间不是连续的,而是采用一个指针指向了另外一段内存空间,访问的时候性能也就会受到影响,还有可能产生内存碎片。假设有一个hash类型的Key,其有10万对field和value,field是自增id,那这个Key存在什么问题?:对BigKey执行读请求时,少量的QPS就可能导致带宽使用率被占满,导致Redis实例,乃至所在物理机变慢;BigKey内存占用较多,删除这样的Key也需要耗费很长时间,从而导致Redis主线程阻塞,引发一系列问题。

UltraEdit-文本编辑器Mac绿色版-程序员宅基地

文章浏览阅读454次。前言更多内容,请访问我的 个人博客。简介:Ultraedit是一款在Windows系统中非常出名的文本编辑器,可以编辑文本、十六进制、ASCII 码,完全可以取代其他文本工具,同时还支持许多开发语言,如 C, Objective C, Javascript, XML, PHP, Perl, Python等,并可同时编辑多个文件,而且即使开启很大的文件速度也不会慢。功能特点:可..._ultraedit编辑mac地址

vue @click 绑定的函数,传入事件对象和自定义参数_vue @click 自定义参数-程序员宅基地

文章浏览阅读2k次。1.仅传入自定义参数html:<div id="app"> <button @click="tm(123)">ddddd</button></div>js:new Vue({ el:'#app', methods:{ tm:function(e){ console.log(e); //会输出 123 } }})2.仅传入事件对象html:<div id="app_vue @click 自定义参数

SSM宠物领养管理系统-计算机毕设 附源码73769_宠物寄养系统er图-程序员宅基地

文章浏览阅读1.3k次,点赞4次,收藏15次。关于宠物领养管理系统的基本要求(1)功能要求:可以管理首页,站点管理(轮播图,通知栏),人员管理(管理员,注册用户,发布用户),内容管理(宠物资讯,新闻分类列表),商城管理(宠物商城,分类列表,订单列表),更多管理(宠物信息,领养宠物,养宠知识)等功能模块。(2)性能:在不同操作系统上均能无差错实现在不同类型的用户登入相应界面后能不出差错、方便地进行预期操作。(3)安全与保密要求:用户都必须通过管理员审核才能进入系统。(4)环境要求:支持Windows系列、Vista系统等多种操作系统使用。2、开_宠物寄养系统er图

程序员自我养成第三天-程序员宅基地

文章浏览阅读83次。Pandas包内函数练习一话不多说,直接上图。

随便推点

H5定位问题-程序员宅基地

文章浏览阅读681次。写在最前面HTML5 Geolocation API 用于获得用户的地理位置。鉴于该特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的。如:目前常见的坐标系有三种:地球坐标(WGS84,国际公认坐标),火星坐标(GCJ02,国家标准,适用于高德百度地图大陆+港澳部分、Google地图大陆部分),百度坐标(BD09,适用于百度地图大陆+港澳台部分)。我们通过浏览器所在硬件设备..._微信内置浏览器h5定位使用的是什么坐标系

c语言与linux变量,从汇编来看C语言之变量-程序员宅基地

文章浏览阅读89次。1、基础研究对如图程序进行编译连接,再用debug加载。我们在偏移地址1fa处查看main函数的内容:执行到1fd处,发现n的偏移地址为01a6,段地址存储在ds寄存器里,为07c4.再查看函数f2:参数a、b的值是用栈来传递的,它们的段地址都存放在ss寄存器中:局部变量c的值在这里是用si寄存器存储的,因为c正好是int型,那么子函数里定义的局部变量是用寄存器存储吗?我们在这里加一条赋值语句看看..._c语言的f3函数

python中字符串转xml对象_Python实现对象转换为xml的方法示例-程序员宅基地

文章浏览阅读1.7k次。本文实例讲述了Python实现对象转换为xml的方法。分享给大家供大家参考,具体如下:# -*- coding:UTF-8 -*-'''''Created on 2010-4-20@author: 忧里修斯'''import xml.etree.ElementTree as ETimport xml.dom.minidom as minidomfrom addrbook.dom..._python 字符串转xml

DBA搞钱之路

如今也是而且大部分都是,提供的岗位真多!就是搞数据库开发,比如周边的工具,或者包装下PG,MYSQL. 比如说PIGSTY工具包, 自然对你需要懂很多,尤其是商业眼光,懂C/C++语言的开发,系统内部原理. 首先你得先开发出来,然后有客户有市场,才能创业开公司.不要聚集在国内,放眼全球市场.那个啥,河北有个程序员翻墙给外网做了啥,结果获得300万都被没收了. 翻墙是不对的,是违法的,前提需要备案,然后中国电信提供翻墙业务,不能去淘宝买翻墙软件. 这对你要求很高,要有商业眼光,要有开发能力,要会英语交流!

ROS(ERROR):Rosdep cannot find all required resources to answer your query_error: rosdep cannot find all required resources t-程序员宅基地

文章浏览阅读1w次,点赞8次,收藏12次。今天LZ在运行下面给代码时出现rosdep install rgbdslam然后报如下错误:ERROR: Rosdep cannot find all required resources to answer your queryMissing resource rgbdslamROS path [0]=/opt/ros/indigo/share/rosROS path ..._error: rosdep cannot find all required resources to answer your query missin

PS1~4,终端提示符设置_echo $ps1返回\s-\v\$-程序员宅基地

文章浏览阅读3.8k次,点赞3次,收藏7次。终端可以说是在Linux的使用中最常用到的工具了,通过设置PS1,PS2,PS3,PS4这四个环境变量,我们就可以个性化定制终端的提示符。一、PS1—默认的交互提示符默认情况下PS1为”\s-\v\$”,显示为-bash-3.2$通过改变PS1,就可以在提示符显示一些对我们有用的信息,如用户名、工作目录、系统时间等-bash-3.2$export PS1_echo $ps1返回\s-\v\$

推荐文章

热门文章

相关标签