基于openssl的3DES(ECB)加密算法

项目中需要用到就找了下,借鉴网上的一些代码,在加上自己的改良,得到了现在的代码,也解决了我的需求。

附openssl安装教程 https://blog.csdn.net/qq_39805297/article/details/100532833

先说下,3DES加密算法有几种填充方式,比如zeropadding、pkcs5padding、pkcs7padding等等,我使用的pkcs7padding的填充方式,比较普遍的算法,而且也是可以与java端契合的填充方式。

#pragma once
#include <iostream>
#include <string.h>
#include <openssl/des.h>

class C3DES 
{
public:
    /******************* 加密:strin是需要加密的明文,strkey是密钥 *********************/
    static std::string encrypt(std::string strin, std::string strkey)
    {
        std::string ret;
        int docontinue = 1;
        const char *data = strin.c_str(); /* 明文 */
        int data_len;
        int data_rest;
        unsigned char ch;
        unsigned char *src = NULL; /* 补齐后的明文 */
        unsigned char *dst = NULL; /* 加密后的明文 */
        int len;
        unsigned char tmp[8];
        unsigned char in[8];
        const char *k = strkey.c_str(); /* 原始密钥 */
        int key_len;
#define LEN_OF_KEY 24
        unsigned char key[LEN_OF_KEY]; /* 补齐后的密钥 */
        unsigned char block_key[9];
        DES_key_schedule ks, ks2, ks3;
        /* 构造补齐后的密钥 密钥需要24位 不足24位的用0x00补齐*/
        key_len = strlen(k);
        memcpy(key, k, key_len);
        memset(key + key_len, 0x00, LEN_OF_KEY - key_len);
        /* 分析补齐明文所需空间及补齐填充数据 pkcs7填充方式要将明文补齐八位,缺几位填充几个几
        比如少一位填充一个0x01 少两位填充两个0x02 整八位的需要填充8个0x08*/
        data_len = strlen(data);
        data_rest = data_len % 8;
        len = data_len + (8 - data_rest);
        ch = 8 - data_rest;
        src = (unsigned char *)malloc(len);
        dst = (unsigned char *)malloc(len);
        if (NULL == src || NULL == dst)
        {
            docontinue = 0;
        }
        if (docontinue)
        {
            int count;
            int i;
            /* 构造补齐后的加密内容 */
            memset(src, 0, len);
            memcpy(src, data, data_len);
            memset(src + data_len, ch, 8 - data_rest);
            /* 密钥置换 */
            memset(block_key, 0, sizeof(block_key));
            memcpy(block_key, key + 0, 8);
            DES_set_key_unchecked((const_DES_cblock*)block_key, &ks);
            memcpy(block_key, key + 8, 8);
            DES_set_key_unchecked((const_DES_cblock*)block_key, &ks2);
            memcpy(block_key, key + 16, 8);
            DES_set_key_unchecked((const_DES_cblock*)block_key, &ks3);
            printf("before encrypt:\n");
            for (i = 0; i < len; i++)
            {
                printf("%c ", *(src + i));
            }
            printf("\n");
            /* 循环加密/解密,每8字节一次 */
            count = len / 8;
            for (i = 0; i < count; i++)
            {
                memset(tmp, 0, 8);
                memset(in, 0, 8);
                memcpy(tmp, src + 8 * i, 8);
                /* 加密 */
                DES_ecb3_encrypt((const_DES_cblock*)tmp, (DES_cblock*)in, &ks, &ks2, &ks3, DES_ENCRYPT);
                /* 将解密的内容拷贝到解密后的明文 */
                memcpy(dst + 8 * i, in, 8);
            }
            printf("after decrypt :\n");
            for (i = 0; i < len; i++)
            {
                printf("%c ", *(dst + i));
                ret.push_back(*(dst + i));
            }
            printf("\n");
            printf("%s\n", ret.c_str());
        }
        if (NULL != src)
        {
            free(src);
            src = NULL;
        }
        if (NULL != dst)
        {
            free(dst);
            dst = NULL;
        }
        return ret;
    }
    //解密
    static std::string decode(std::string strin, std::string strkey)
    {
        std::string ret;
        int docontinue = 1;
        char *data = new char[strin.length()];
        //此种方式避免密文中存在\0的情况
        for (int i = 0; i < strin.length(); ++i)
        {
            data[i] = strin.at(i);
        }
        int data_len;
        unsigned char *src = NULL; /* 补齐后的密文 */
        char *dst = NULL; /* 解密后的密文 */
        unsigned char tmp[8];
        unsigned char out[8];
        const char *k = strkey.c_str(); /* 原始密钥 */
        int key_len;
#define LEN_OF_KEY 24
        unsigned char key[LEN_OF_KEY]; /* 补齐后的密钥 */
        unsigned char block_key[9];
        DES_key_schedule ks, ks2, ks3;
        /* 构造补齐后的密钥 */
        key_len = strlen(k);
        memcpy(key, k, key_len);
        memset(key + key_len, 0x00, LEN_OF_KEY - key_len);
        /* 分析补齐明文所需空间及补齐填充数据 */
        data_len = strin.length();
        src = (unsigned char *)malloc(data_len);
        dst = (char *)malloc(data_len);
        if (NULL == src || NULL == dst)
        {
            docontinue = 0;
        }
        if (docontinue)
        {
            int count;
            int i;
            /* 构造补齐后的加密内容 */
            memset(src, 0, data_len);
            memcpy(src, data, data_len);
            /* 密钥置换 */
            memset(block_key, 0, sizeof(block_key));
            memcpy(block_key, key + 0, 8);
            DES_set_key_unchecked((const_DES_cblock*)block_key, &ks);
            memcpy(block_key, key + 8, 8);
            DES_set_key_unchecked((const_DES_cblock*)block_key, &ks2);
            memcpy(block_key, key + 16, 8);
            DES_set_key_unchecked((const_DES_cblock*)block_key, &ks3);
            printf("before encrypt:\n");
            for (i = 0; i < data_len; i++)
            {
                printf("%c", *(src + i));
            }
            printf("\n");
            /* 循环加密/解密,每8字节一次 */
            count = data_len / 8;
            for (i = 0; i < count; i++)
            {
                memset(tmp, 0, 8);
                memset(out, 0, 8);
                memcpy(tmp, src + 8 * i, 8);
                /* 解密 */
                DES_ecb3_encrypt((const_DES_cblock*)tmp, (DES_cblock*)out, &ks, &ks2, &ks3, DES_DECRYPT);
                /* 将解密的内容拷贝到解密后的明文 */
                memcpy(dst + 8 * i, out, 8);
            }
            printf("after decrypt :\n");
            printf("%s\n", dst);
            //去除补齐长度
            data_len -= *(dst + data_len - 1);
            for (i = 0; i < data_len; i++)
            {
                ret.push_back(*(dst + i));
                printf("%c", *(dst + i));
            }
            printf("\n");
            printf("%c\n", *(dst + data_len - 1));
        }
        if (NULL != src)
        {
            free(src);
            src = NULL;
        }
        if (NULL != dst)
        {
            free(dst);
            dst = NULL;
        }
        return ret;
    }
};

附源码下载地址:https://download.csdn.net/download/qq_39805297/11950533

发布了14 篇原创文章 · 获赞 0 · 访问量 5066
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章