項目中需要用到就找了下,借鑑網上的一些代碼,在加上自己的改良,得到了現在的代碼,也解決了我的需求。
附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