基於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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章