CBC模式的DES加密算法(加密字符串、加密文件)

a) 所有协议数据采用标准的CBC模式的DES加密算法;

b) 密钥长度为8位,可以为空(为空时,默认是8个0)

c) 所有协议数据采用8位初始向量(VI)做互斥运算

d) 所有协议数据的明文需要在尾部加上原始数据长度(int大端字节数4字节),再加上“ABCD4个字母,然后按64位进行分组,不足64位的以“\0”补足,分组后的明文采用统一的加密方式生成密文,即采用 “明文+密钥+初始化向量(VI)”


1、加密文件:

*/*******************************************************************/


#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <unistd.h>


#include <openssl/des.h>




#define  READ_BLOCK_SIZE  65536
#define MIN(a,b)  ((a) > (b) ? (b) : (a))




static int crypt_block(FILE * fp, const uint8_t * buf, int buf_size,
                       DES_key_schedule * key_sch, DES_cblock * ivec, int enc)
{
    int i;
    uint8_t tmp[8];


    assert(buf_size % 8 == 0);


    for (i = 0; i < buf_size / 8; i++)
    {
        DES_ncbc_encrypt(buf + i * 8, tmp, 8, key_sch, ivec, enc);
        fwrite(tmp, 8, 1, fp);
    }
    return 0;
}


static int fread_while(uint8_t * buff, int buff_len, FILE * fp)
{
    int count = 0;
    int real_len = 0;


    while (!feof(fp))
    {
        real_len = fread(buff + count, 1, buff_len - count, fp);
        if (real_len < 0)
        {
            return -1;
        }


        count += real_len;


        if (count >= buff_len)
        {
            break;
        }
    }


    return count;
}




static bool is_zero(const uint8_t * buff, int buff_len)
{
    int i;


    for (i = 0; i < buff_len; i++)
    {
        if (buff[i] != 0)
        {
            return false;
        }
    }


    return true;
}




static int file_decrypt(FILE * src_fp, FILE * dst_fp, uint32_t src_file_len,
                        DES_key_schedule * key_sch, DES_cblock * ivec)
{
    int i = 0;
    uint8_t buff[READ_BLOCK_SIZE];
    int real_len = 0;
    int read_len = 0;
    int count = 0;
    int body_len = src_file_len - 16;   // 保留最后两个分组


    if (src_file_len % 8 != 0)
    {
        printf
            ("source file is not 3011 CBC DES  file;  [src_file_len mod 8 !=0] \n");
        return -1;
    }


    /* 1. 保留最后两个分组,其它所有的分组都在这里解密,并写到文件中 */
    for (i = 0; body_len > 0 && i * sizeof(buff) < body_len && !feof(src_fp);
         i++)
    {
        memset(buff, 0, sizeof(buff));


        if (body_len >= (i + 1) * sizeof(buff))
        {
            read_len = sizeof(buff);
        }
        else
        {
            read_len = body_len % sizeof(buff);
        }




        real_len = fread_while(buff, read_len, src_fp);
        if (real_len <= 0)
        {
            printf("read file 1[Fail]\n");
            return -1;
        }
        count += real_len;


        /* 读取一整块,可以直接进行加密了 */
        if (real_len == sizeof(buff))
        {
            crypt_block(dst_fp, buff, real_len, key_sch, ivec, DES_DECRYPT);
            continue;
        }


        /* 到达这里,表示文件一定是结束了 */
        if (read_len != read_len)
        {
            printf("read  file 2 [Fail]\n");
            return -1;
        }




        crypt_block(dst_fp, buff, real_len, key_sch, ivec, DES_DECRYPT);
        break;
    }


    /* 2. 因为在加密过程中,是如下处理 :
       将最后一个不足64位的分组,加上原始数据长度(int大端字节数4字节),再加上
       “ABCD”4个字母,然后按64位进行分组,不足64位的以“\0”补足;
       所以在这里必须进行相反的操作。即在解密后,去掉最后的0,并且去掉ABCD和
       文件大小; */
    uint8_t tmp[16];
    int tmp_len = 0;
    uint32_t file_len = 0;
    uint8_t post_fix[] = { 'A', 'B', 'C', 'D' };


    // 明文文件为空时,这里src_file_len 为 8;
    tmp_len = MIN(src_file_len, 16);




    // 读取最后分组,并解密
    real_len = fread_while(buff, tmp_len, src_fp);
    if (real_len != tmp_len)
    {
        printf("read  file 3 [Fail]\n");
        return -1;
    }
    DES_ncbc_encrypt(buff, tmp, 8, key_sch, ivec, DES_DECRYPT);
    if (tmp_len == 16)
    {
        DES_ncbc_encrypt(buff + 8, tmp + 8, 8, key_sch, ivec, DES_DECRYPT);
    }


    // find 'ABCD'
    uint8_t *pos_abcd = memmem(tmp, tmp_len, post_fix, sizeof(post_fix));
printf("tmp====%s\n",tmp);
    if (pos_abcd == NULL)
    {
        printf("source file is not 3011 CBC DES  file;  [pos_abcd == NULL] \n");
        return -1;
    }


    // 确认ABCD后面都是为0
    if (!is_zero
        (pos_abcd + sizeof(post_fix),
         tmp_len - (pos_abcd - tmp) - sizeof(post_fix)))
    {
        printf("source file is not 3011 CBC DES  file;  [!is_zero()] \n");
        return -1;
    }




    // 至少在ABCD前有4个字节,并且确认这里的文件大小与原来的文件大小一样
    if ((pos_abcd - tmp) < 4)
    {
        printf
            ("source file is not 3011 CBC DES  file;  [file size filed is not exist] \n");
        return -1;
    }


    // 最后一个分组去掉最后的0,并且去掉ABCD和       文件大小后,写入文件中
    memcpy(&file_len, pos_abcd - 4, 4);
    file_len = ntohl(file_len);
    count += pos_abcd - 4 - tmp;
    if (count != file_len)
    {
        printf
            ("source file is not 3011 CBC DES  file;  [src_file_len != file_len] \n");
        return -1;
    }


    fwrite(tmp, pos_abcd - 4 - tmp, 1, dst_fp);
    return 0;
}




static int file_encrypt(FILE * src_fp, FILE * dst_fp, uint32_t src_file_len,
                        DES_key_schedule * key_sch, DES_cblock * ivec)
{
    int i = 0;
    uint8_t buff[READ_BLOCK_SIZE];
    int real_len = 0;
    int remain_len = 0;
    int read_len = 0;


    /* 1.如果最后一个不足64位的分组,那么除了这个分组外,其它所有的分组都在这里加密 */
    for (i = 0; i * sizeof(buff) < src_file_len && !feof(src_fp); i++)
    {
        remain_len = 0;
        memset(buff, 0, sizeof(buff));


        if (src_file_len >= (i + 1) * sizeof(buff))
        {
            read_len = sizeof(buff);
        }
        else
        {
            read_len = src_file_len % sizeof(buff);
        }




        real_len = fread_while(buff, read_len, src_fp);
        if (real_len <= 0)
        {
            printf("read file 1[Fail]\n");
            return -1;
        }


        /* 读取一整块,可以直接进行加密了 */
        if (real_len == sizeof(buff))
        {
            crypt_block(dst_fp, buff, real_len, key_sch, ivec, DES_ENCRYPT);
            continue;
        }


        /* 到达这里,表示文件一定是结束了 */
        if (read_len != read_len)
        {
            printf("read  file 2 [Fail]\n");
            return -1;
        }


        /* 这里的分组有可能不被整除, 所以需要计算最后一个分组的大小remain_len */
        remain_len = real_len % 8;
        crypt_block(dst_fp, buff, real_len - remain_len, key_sch, ivec,
                    DES_ENCRYPT);
        break;
    }


    /* 2. 将最后一个不足64位的分组,加上原始数据长度(int大端字节数4字节),再加上
       “ABCD”4个字母,然后按64位进行分组,不足64位的以“\0”补足;


       如果文件的大小刚好被8整除, 那么tmp_len 的长度就为8,否则为16 */
    uint8_t tmp[16];
    int tmp_len = 0;
    uint32_t file_len = htonl(src_file_len);
    uint8_t post_fix[] = { 'A', 'B', 'C', 'D' };


    memset(tmp, 0, sizeof(tmp));
    memcpy(tmp, buff + real_len - remain_len, remain_len);
    tmp_len = remain_len;
    memcpy(tmp + tmp_len, &file_len, sizeof(file_len));
    tmp_len += sizeof(file_len);
    memcpy(tmp + tmp_len, &post_fix, sizeof(post_fix));
    tmp_len += sizeof(post_fix);


    tmp_len = tmp_len == 8 ? 8 : 16;


for(i=0;i<tmp_len;i++)
{
printf("tmp[%d]=%02x\n",i,tmp[i]);


}
    crypt_block(dst_fp, tmp, tmp_len, key_sch, ivec, DES_ENCRYPT);


    return 0;
}




/*
*函数功能:完成基于3011规范的CBC 加密;即 所有协议数据的明文需要在尾部加上原始数
据长度(int大端字节数4字节),再加上“ABCD”4个字母,然后按64位进行
分组,不足64位的以“\0”补足,分组后的明文采用统一的加密方式生成密文,
即采用 “明文+密钥+初始化向量(VI)”




*参数:
src_fi;e : 输入文件名
dst_file : 输出文件名
key : 密码
key_len : 密码的长度
iv: 初始向量
iv_len : 初始向量的长度
 
enc :是执行加密还是解密操作,加密:DES_ENCRYPT , 解密:DES_DECRYPT
 
*返 回 值:
 0 : 成功
 <0 : 失败
 
*其它说明:
*/
static int dec_cbc_crypt_file(const char *src_file, const char *dst_file,
                              const uint8_t * key, int key_len,
                              const uint8_t * iv, int iv_len, int enc)
{
    int ret = 0;
    FILE *src_fp;
    FILE *dst_fp;
    DES_cblock ivec;
    DES_key_schedule key_sch;
    struct stat stat_buf;


    if ((key == NULL) || key_len <= 0 || key_len % 8 != 0)
    {
        printf(" key is error \n");
        return -1;
    }


    if ((iv == NULL) || iv_len <= 0 || iv_len % 8 != 0)
    {
        printf(" initial verctor is error \n");
        return -1;
    }


    memcpy(ivec, iv, sizeof(ivec));
    DES_set_key_unchecked((const_DES_cblock *) key, &key_sch);




    src_fp = fopen(src_file, "r");
    if (src_fp == NULL)
    {
        printf(" %s file do not open\n", src_file);
        return -1;
    }


    dst_fp = fopen(dst_file, "w");
    if (src_fp == NULL)
    {
        fclose(src_fp);
        printf(" %s file do not write\n", dst_file);
        return -1;
    }


    if (stat(src_file, &stat_buf) != 0)
    {
        printf("check file(%s) fail\n", src_file);
        fclose(src_fp);
        fclose(dst_fp);
        return -1;
    }


    if (enc == DES_DECRYPT)
    {
        ret = file_decrypt(src_fp, dst_fp, stat_buf.st_size, &key_sch, &ivec);
    }
    else
    {
        ret = file_encrypt(src_fp, dst_fp, stat_buf.st_size, &key_sch, &ivec);
    }


    fclose(src_fp);
    fclose(dst_fp);
    return ret;
}




/*
*函数功能:完成基于3011规范的CBC 加密;即    所有协议数据的明文需要在尾部加上原始数
            据长度(int大端字节数4字节),再加上“ABCD”4个字母,然后按64位进行
            分组,不足64位的以“\0”补足,分组后的明文采用统一的加密方式生成密文,
            即采用 “明文+密钥+初始化向量(VI)”




*参数:
     src_fi;e : 输入文件名
     dst_file : 输出文件名
     str_key : 密码,一个以0结束的字符串
     enc :是执行加密还是解密操作,加密:DES_ENCRYPT , 解密:DES_DECRYPT
     
*返 回 值:
      0 : 成功
      <0 : 失败
      
*其它说明:这里的初始向量是固定的
*/
static int des_cbc_crypt(const char *src_file, const char *dst_file,
                         const char *str_key, int enc)
{
    uint8_t key[8];
    int min_len = MIN(sizeof(key), strlen(str_key));




    /* 设置秘钥,如果密码不足8个字节,补充0 */
    memset(key, 0, sizeof(key));
    memcpy(key, str_key, min_len);


    /* 固定初始向量 */
    uint8_t iv[] = { 'q', 'a', 'z', 'w', 's', 'x', 'e', 'd' };
    //memset(iv, 0x30, sizeof(iv));


    /* 加密 */
    return dec_cbc_crypt_file(src_file, dst_file, key, sizeof(key), iv,
                              sizeof(iv), enc);
}





static void print_usage(int argc, char *argv[])
{
    printf("Usage: %s -[d/e] <src_file>  <dst_file>  <key> \n", argv[0]);
    printf("-d : decrypt file\n");
    printf("-e : encrypt file\n\n");
    printf("Example: \n");
    printf("Decrypt file: %s  -d <src_file>  <dst_file>  <key> \n", argv[0]);
    printf("Encrypt file: %s  -e <src_file>  <dst_file>  <key> \n", argv[0]);


}




int main(int argc, char *argv[])
{
int i;
char read_buf[64]={0};
    if (argc < 4)
    {
        print_usage(argc, argv);
        return -1;
    }


    if (strcmp(argv[1], "-e") == 0)
    {
         des_cbc_crypt(argv[2], argv[3], argv[4], DES_ENCRYPT);
    }
    else if (strcmp(argv[1], "-d") == 0)
    {
        return des_cbc_crypt(argv[2], argv[3], argv[4], DES_DECRYPT);
    }
    else
    {
        print_usage(argc, argv);
        return -1;
    }


}


2、加密字符串




/*********************************************************************/


#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <unistd.h>


#include <openssl/des.h>
#include "des.h"




#define  READ_BLOCK_SIZE  65536
#define MIN(a,b)  ((a) > (b) ? (b) : (a))


int dst_str_len=0;
static int crypt_block(char * dst_str, const uint8_t * buf, int buf_size,
                       DES_key_schedule * key_sch, DES_cblock * ivec, int enc)
{
    int i;
    uint8_t tmp[8];


    assert(buf_size % 8 == 0);


    for (i = 0; i < buf_size / 8; i++)
    {
        DES_ncbc_encrypt(buf + i * 8, tmp, 8, key_sch, ivec, enc);
        // if(enc==DES_DECRYPT)
        // {
        //     printf("strlen(dst_str)=%d dst_str_len=%d\n",strlen(dst_str),dst_str_len );
        //     for (j = 0; j  < 8 ;j++)
        //     {
        //         printf("[[[[[[[[[src_str[%d]=%02x \n", j,tmp[j]);
        //     }


        // }
        memcpy(dst_str+dst_str_len,tmp,8);


        dst_str_len+=8;
        // for (j = 0; j  < dst_str_len ;j++)
        // {
        //     printf("[[[[[[[[[dst_str[%d]=%02x \n", j,dst_str[j]);
        // }
        // else
        // {
        //     memcpy(dst_str+strlen(dst_str),tmp,8);
        // }
        
        //printf("strlen(dst_str)=%d\n",strlen(dst_str));
    }
    return 0;
}
/*
static int fread_while(uint8_t * buff, int buff_len, FILE * fp)
{
    int count = 0;
    int real_len = 0;


    while (!feof(fp))
    {
        real_len = fread(buff + count, 1, buff_len - count, fp);
        if (real_len < 0)
        {
            return -1;
        }


        count += real_len;


        if (count >= buff_len)
        {
            break;
        }
    }


    return count;
}
*/


static bool is_zero(const uint8_t * buff, int buff_len)
{
    int i;


    for (i = 0; i < buff_len; i++)
    {
        if (buff[i] != 0)
        {
            return false;
        }
    }


    return true;
}




static int file_decrypt(char * src_str, char * dst_str,uint32_t src_file_len , DES_key_schedule * key_sch, DES_cblock * ivec)
{
    int i = 0;
    uint8_t buff[READ_BLOCK_SIZE];
    int real_len = 0;
    int read_len = 0;
    int count = 0;
    int body_len = src_file_len - 16;   // 保留最后两个分组


    


    /* 1. 保留最后两个分组,其它所有的分组都在这里解密,并写到文件中 */
    for (i = 0; body_len > 0 && i * sizeof(buff) < body_len;i++)
    {
        memset(buff, 0, sizeof(buff));


        if (body_len >= (i + 1) * sizeof(buff))
        {
            read_len = sizeof(buff);
        }
        else
        {
            read_len = body_len % sizeof(buff);
        }




        real_len =read_len; 
        memcpy(buff,src_str+i*read_len,read_len);
        if (real_len <= 0)
        {
            printf("read file 1[Fail]\n");
            return -1;
        }
        count += real_len;


        /* 读取一整块,可以直接进行加密了 */
        if (real_len == sizeof(buff))
        {
            crypt_block(dst_str, buff, real_len, key_sch, ivec, DES_DECRYPT);
            continue;
        }


        /* 到达这里,表示文件一定是结束了 */
        if (read_len != read_len)
        {
            printf("read  file 2 [Fail]\n");
            return -1;
        }




        crypt_block(dst_str, buff, real_len, key_sch, ivec, DES_DECRYPT);
       
        break;
    }


    /* 2. 因为在加密过程中,是如下处理 :
       将最后一个不足64位的分组,加上原始数据长度(int大端字节数4字节),再加上
       “ABCD”4个字母,然后按64位进行分组,不足64位的以“\0”补足;
       所以在这里必须进行相反的操作。即在解密后,去掉最后的0,并且去掉ABCD和
       文件大小; */
    uint8_t tmp[16];
    int tmp_len = 0;
    uint32_t file_len = 0;
    uint8_t post_fix[] = { 'A', 'B', 'C', 'D' };


    // 明文文件为空时,这里src_file_len 为 8;
    tmp_len = MIN(src_file_len, 16);




    // 读取最后分组,并解密
    //real_len = fread_while(buff, tmp_len, src_fp);
    //real_len=src_file_len-i*read_len;
    memcpy(buff,src_str+count,tmp_len);
    // if (real_len != tmp_len)
    // {
    //     printf("read  file 3 [Fail]\n");
    //     return -1;
    // }
    DES_ncbc_encrypt(buff, tmp, 8, key_sch, ivec, DES_DECRYPT);
    if (tmp_len == 16)
    {
        DES_ncbc_encrypt(buff + 8, tmp + 8, 8, key_sch, ivec, DES_DECRYPT);
    }


    // find 'ABCD'
    uint8_t *pos_abcd = memmem(tmp, tmp_len, post_fix, sizeof(post_fix));


    if (pos_abcd == NULL)
    {
        printf("tmp=%s post_fix=%c\n",tmp,post_fix[0] );
        printf("source file is not 3011 CBC DES  file;  [pos_abcd == NULL] \n");
        return -1;
    }


    // 确认ABCD后面都是为0
    if (!is_zero
        (pos_abcd + sizeof(post_fix),
         tmp_len - (pos_abcd - tmp) - sizeof(post_fix)))
    {
        printf("source file is not 3011 CBC DES  file;  [!is_zero()] \n");
        return -1;
    }




    // 至少在ABCD前有4个字节,并且确认这里的文件大小与原来的文件大小一样
    if ((pos_abcd - tmp) < 4)
    {
        printf
            ("source file is not 3011 CBC DES  file;  [file size filed is not exist] \n");
        return -1;
    }


    // 最后一个分组去掉最后的0,并且去掉ABCD和       文件大小后,写入文件中
    memcpy(&file_len, pos_abcd - 4, 4);
    
    file_len = ntohl(file_len);
    printf("count=%d file_len=%d \n",count,file_len );


    count += pos_abcd - 4 - tmp;
    if (count != file_len)
    {
        printf("count=%d file_len=%d \n",count,file_len );
        printf
            ("source file is not 3011 CBC DES  file;  [src_file_len != file_len] \n");
        return -1;
    }
     memcpy(dst_str+dst_str_len,tmp,pos_abcd - 4 - tmp);
    //fwrite(tmp, pos_abcd - 4 - tmp, 1, dst_fp);
    return 0;
}




static int file_encrypt(char * src_str, char * dst_str,uint32_t src_file_len, DES_key_schedule * key_sch, DES_cblock * ivec)
{
    int i = 0;
    uint8_t buff[READ_BLOCK_SIZE];
    int real_len = 0;
    int remain_len = 0;
    int read_len = 0;
   


    /* 1.如果最后一个不足64位的分组,那么除了这个分组外,其它所有的分组都在这里加密 */
    for (i = 0; i * sizeof(buff) < src_file_len ;i++)
    {
        remain_len = 0;
        memset(buff, 0, sizeof(buff));


        if (src_file_len >= (i + 1) * sizeof(buff))
        {
            read_len = sizeof(buff);
        }
        else
        {
            read_len = src_file_len % sizeof(buff);
        }


        real_len =read_len; 
        memcpy(buff,src_str+i*read_len,read_len);
    
        if (real_len <= 0)
        {
            printf("read file 1[Fail]\n");
            return -1;
        }


        /* 读取一整块,可以直接进行加密了 */
        if (real_len == sizeof(buff))
        {
            crypt_block(dst_str, buff, real_len, key_sch, ivec, DES_ENCRYPT);
            continue;
        }


        /* 到达这里,表示文件一定是结束了 */
        if (read_len != read_len)
        {
            printf("read  file 2 [Fail]\n");
            return -1;
        }


        /* 这里的分组有可能不被整除, 所以需要计算最后一个分组的大小remain_len */
        remain_len = real_len % 8;
        crypt_block(dst_str, buff, real_len - remain_len, key_sch, ivec,
                    DES_ENCRYPT);
        break;
    }


    
    /* 2. 将最后一个不足64位的分组,加上原始数据长度(int大端字节数4字节),再加上
       “ABCD”4个字母,然后按64位进行分组,不足64位的以“\0”补足;


       如果文件的大小刚好被8整除, 那么tmp_len 的长度就为8,否则为16 */
    uint8_t tmp[16];
    int tmp_len = 0;
    uint32_t file_len = htonl(src_file_len);
    uint8_t post_fix[] = { 'A', 'B', 'C', 'D' };


    memset(tmp, 0, sizeof(tmp));
    memcpy(tmp, buff + real_len - remain_len, remain_len);
    tmp_len = remain_len;
    memcpy(tmp + tmp_len, &file_len, sizeof(file_len));
    tmp_len += sizeof(file_len);
    memcpy(tmp + tmp_len, &post_fix, sizeof(post_fix));
    tmp_len += sizeof(post_fix);


    tmp_len = tmp_len == 8 ? 8 : 16;
    for(i=0;i<tmp_len;i++)
    {
        //printf("3333333333[%d]=%02x\n", i,tmp[i]);
    }
    crypt_block(dst_str, tmp, tmp_len, key_sch, ivec, DES_ENCRYPT);
     
    return 0;
}




/*
*函数功能:完成基于3011规范的CBC 加密;即 所有协议数据的明文需要在尾部加上原始数
据长度(int大端字节数4字节),再加上“ABCD”4个字母,然后按64位进行
分组,不足64位的以“\0”补足,分组后的明文采用统一的加密方式生成密文,
即采用 “明文+密钥+初始化向量(VI)”




*参数:
src_fi;e : 输入文件名
dst_file : 输出文件名
key : 密码
key_len : 密码的长度
iv: 初始向量
iv_len : 初始向量的长度
 
enc :是执行加密还是解密操作,加密:DES_ENCRYPT , 解密:DES_DECRYPT
 
*返 回 值:
 0 : 成功
 <0 : 失败
 
*其它说明:
*/
static int dec_cbc_crypt_file(char *src_str, char *dst_str,uint32_t src_file_len ,const uint8_t * key, int key_len,
                              const uint8_t * iv, int iv_len, int enc)
{
    int ret = 0;
    //FILE *src_fp;
    //FILE *dst_fp;
    DES_cblock ivec;
    DES_key_schedule key_sch;
    //struct stat stat_buf;
    //printf("key_len========%d iv_len=%d\n", key_len,iv_len);
    if ((key == NULL) || key_len <= 0 || key_len % 8 != 0)
    {
        printf(" key is error \n");
        return -1;
    }


    if ((iv == NULL) || iv_len <= 0 || iv_len % 8 != 0)
    {
        printf(" initial verctor is error \n");
        return -1;
    }


    memcpy(ivec, iv, sizeof(ivec));
    DES_set_key_unchecked((const_DES_cblock *) key, &key_sch);






    if (enc == DES_DECRYPT)
    {
        ret = file_decrypt(src_str, dst_str,src_file_len, &key_sch, &ivec);
    }
    else
    {
        ret = file_encrypt(src_str, dst_str,src_file_len,&key_sch, &ivec);
    }


    //fclose(src_fp);
    //fclose(dst_fp);
    return ret;
}




/*
*函数功能:完成基于3011规范的CBC 加密;即    所有协议数据的明文需要在尾部加上原始数
            据长度(int大端字节数4字节),再加上“ABCD”4个字母,然后按64位进行
            分组,不足64位的以“\0”补足,分组后的明文采用统一的加密方式生成密文,
            即采用 “明文+密钥+初始化向量(VI)”




*参数:
     src_fi;e : 输入文件名
     dst_file : 输出文件名
     str_key : 密码,一个以0结束的字符串
     enc :是执行加密还是解密操作,加密:DES_ENCRYPT , 解密:DES_DECRYPT
     
*返 回 值:
      0 : 成功
      <0 : 失败
      
*其它说明:这里的初始向量是固定的
*/
static int des_cbc_crypt(char *src_str, char *dst_str,uint32_t src_file_len, const char *str_key, char *init_vector,int enc)
{
    uint8_t key[8];
    int min_len = MIN(sizeof(key), strlen(str_key));




    /* 设置秘钥,如果密码不足8个字节,补充0 */
    memset(key, 0, sizeof(key));
    memcpy(key, str_key, min_len);


    /* 固定初始向量 */
    uint8_t iv[8] = {0};
    memcpy(iv,init_vector,sizeof(iv));
    //memset(iv, 0x30, sizeof(iv));


    /* 加密 */
    return dec_cbc_crypt_file(src_str, dst_str,src_file_len,key, sizeof(key), iv,
                              sizeof(iv), enc);
}


/*

static void print_usage(int argc, char *argv[])
{
    printf("Usage: %s -[d/e] <src_file>  <dst_file>  <key> \n", argv[0]);
    printf("-d : decrypt file\n");
    printf("-e : encrypt file\n\n");
    printf("Example: \n");
    printf("Decrypt file: %s  -d <src_file>  <dst_file>  <key> \n", argv[0]);
    printf("Encrypt file: %s  -e <src_file>  <dst_file>  <key> \n", argv[0]);


}
*/




void des_encryption(char *src_str,char *dst_str,uint32_t src_file_len,char *key,char *init_vector)
{
    dst_str_len=0;
     des_cbc_crypt(src_str, dst_str,src_file_len, key,init_vector, DES_ENCRYPT);
}


void des_decryption(char *src_str,char *dst_str,uint32_t src_file_len,char *key,char *init_vector)
{
    dst_str_len=0;
     des_cbc_crypt(src_str, dst_str, src_file_len,key,init_vector, DES_DECRYPT);
}
    
#if 0
int main(int argc, char *argv[])
{
    char src_str[]="1234567891234554321";
    char dst_str[1024]={0};
    char src_str2[1024]={0};
    char *key="";
    int i;


    des_encryption(src_str,dst_str,strlen(src_str),key);
    
    for(i=0;i<strlen(dst_str);i++)
    {
        printf("dst_str[%d]=%02x\n", i,dst_str[i]);
    }
    printf("strlen(dst_str)=========%d\n",strlen(dst_str) );
    des_decryption(dst_str,src_str2,strlen(dst_str),key);
    //printf("src_str====%s dst_str======%s\n", src_str,dst_str);
    for(i=0;i<strlen(src_str2);i++)
    {
        printf("src_str[%d]=%02x\n", i,src_str2[i]);
    }
}
#endif



3、编译使用

gcc des.c -lcrypto

加密文件:des -e src.txt dst.txt 12345678

解密文件:des -d dst.txt src2.txt 12345678

src.txt 应和src2.txt 相同



加密字符串就不多说了,调用加解密函数就行

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值