3DES crypt helper

来源:互联网 发布:淘宝购物卡有什么用 编辑:程序博客网 时间:2024/06/05 09:12

今天同事让写一个DLL给他,3DES+BASE64 加解密接口2个。
以前做的实验,做了半边(java加密,C解密),因为那次就半边的需求。
这次都要由C这边来做(C加密,C解密), 磨叽了2个小时。
其实正确的姿势是,以前就应该将实验做全的,这次应该拿过来就好用。
又杯具一次, 一个愉快的周末没开个好头.

对于基础代码,如果最开始没写好测试用例,以后有可能会写错。会怀疑到接口实现的问题上,在调试上容易浪费时间。

openssl代码维护真容易,都是自解释的函数名和参数名,而且参数摆放规律一致,如果有一个可用的加密函数,很容易维护出一个可用的解密函数。

实验

工程下载点

src_3DESCryptHelper_2017_0528_0026.zip

工程输出

2017/05/28  00:24    <DIR>          .2017/05/28  00:24    <DIR>          ..2017/05/28  00:24            12,800 3DESCryptHelper.dll2017/05/28  00:24             1,041 3DESCryptHelper.exp2017/05/28  00:24             2,280 3DESCryptHelper.lib2017/04/08  11:27         1,183,232 libeay32.dll2017/04/08  11:27           270,848 ssleay32.dll2017/05/28  00:24            10,240 test3DESCryptHelper.exe               6 个文件      1,480,441 字节

接口测试程序

// test3DESCryptHelper.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <windows.h>#include <atlconv.h>#include <string>#include "../dll/IF_3DESCryptHelper.h"#pragma comment(lib, "3DESCryptHelper.lib")#define _3DES_CRYPT_KEY "123456781234567812345678"int _tmain(int argc, _TCHAR* argv[]){    USES_CONVERSION;    std::string strEncBase64 = "";    std::string strPlainTxt = "";    strEncBase64 = IF_3DES_CryptHlerper_encrypt("hello", _3DES_CRYPT_KEY);    printf("strEncBase64 = %s\n", strEncBase64.c_str());    strPlainTxt = IF_3DES_CryptHlerper_decrypt(strEncBase64.c_str(), _3DES_CRYPT_KEY);    printf("strPlainTxt = %s\n", strPlainTxt.c_str());    system("pause");    return 0;}

运行效果

strEncBase64 = sRjgl3qfUBnbhZgumtlVgtCN+YQap6PMstrPlainTxt = hello请按任意键继续. . .

接口定义

// @file IF_3DESCryptHelper.h// @brief 接口文件#ifndef __IF_3DES_CRYPT_HELPER_H__#define __IF_3DES_CRYPT_HELPER_H__#ifndef _3DES_CRYPT_HELPER_EXPORTS#define _3DES_CRYPT_HELPER_API __declspec(dllimport)#else#define _3DES_CRYPT_HELPER_API __declspec(dllexport)#endif// =============================================================================// 错误码定义// =============================================================================#define IF_OK 0#define IF_ERR_BASE IF_OK // 接口执行成功#define IF_ERR_PARAM1_INVALID (IF_ERR_BASE + 1) // 参数1无效#define IF_ERR_PARAM2_INVALID (IF_ERR_BASE + 2)  // 参数2无效#define IF_ERR_PARAM3_INVALID (IF_ERR_BASE + 3)  // 参数3无效#define IF_ERR_PARAM1_LEN_TOO_SMALL (IF_ERR_BASE + 4)  // 参数1缓冲区长度太短了#define IF_ERR_PARAM2_LEN_TOO_SMALL (IF_ERR_BASE + 5)  // 参数2缓冲区长度太短了#define IF_ERR_PARAM3_LEN_TOO_SMALL (IF_ERR_BASE + 6)  // 参数3缓冲区长度太短了#define IF_ERR_NOT_IMP (IF_ERR_BASE + 7)  // 接口未实现#define IF_ERR_UNKNOWN (IF_ERR_BASE + 0x1000)  // 未知错误// =============================================================================// 接口定义// =============================================================================#ifdef __cplusplusextern "C" {#endif// @fn _CryptHlerper_encrypt// @brief 文本加密接口//  给定明文和密钥, 输出密文(3DES加密+base64)// @param psz_plain_txt, 明文文本// @param psz_key, 密钥// @return const char*, 密文_3DES_CRYPT_HELPER_API const char* __stdcall IF_3DES_CryptHlerper_encrypt(/*IN*/ const char* psz_plain_txt, /*IN*/ const char* psz_key);// @fn 3DES_CryptHlerper_decrypt// @brief 文本解密接口//  给定加密接口输出的密文和密钥,输出明文(3DES解密+unbase64)// @param psz_cipher_txt, 密文(3DES_CryptHlerper_encrypt的输出)// @param psz_key, 密钥// @return const char*, 明文文本_3DES_CRYPT_HELPER_API const char* __stdcall IF_3DES_CryptHlerper_decrypt(/*IN*/ const char* psz_cipher_txt, /*IN*/ const char* psz_key);#ifdef __cplusplus}#endif#endif // #ifndef __IF_3DES_CRYPT_HELPER_H__
// LsBase64.h: interface for the LsBase64 class.////////////////////////////////////////////////////////////////////////#if !defined(AFX_LSBASE64_H__28E02995_79BF_48B8_9809_9A575CB7E700__INCLUDED_)#define AFX_LSBASE64_H__28E02995_79BF_48B8_9809_9A575CB7E700__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000namespace ns_ls{    unsigned int base64_encode(const unsigned char* bytes_to_encode, unsigned int in_len, unsigned char* encoded_buffer, unsigned int& out_len);    unsigned int base64_decode(const unsigned char* encoded_string, unsigned int in_len, unsigned char* decoded_buffer, unsigned int& out_len);}#endif // !defined(AFX_LSBASE64_H__28E02995_79BF_48B8_9809_9A575CB7E700__INCLUDED_)

接口实现

// 3DESCryptHelper.cpp : 定义 DLL 应用程序的导出函数。//#include "stdafx.h"#include <atlconv.h>#include <string>#include <WinSock2.h>#include <time.h>#pragma comment(lib, "ws2_32.lib")#include "IF_3DESCryptHelper.h"#include "LsBase64.h"#include "openssl\evp.h"#pragma comment(lib, "libeay32.lib")#pragma comment(lib, "ssleay32.lib")// iv is 20170528#define FILL_MY_IV iv[0] = 2; \    iv[1] = 0; \    iv[2] = 1; \    iv[3] = 7; \    iv[4] = 0; \    iv[5] = 5; \    iv[6] = 2; \    iv[7] = 8;std::string g_str_txt_was_encrypt = ""; // 加密后的密文std::string g_str_txt_was_decrypt = ""; // 解密后的明文static void fn_copy_by_end_char(WCHAR * pDst, WCHAR * pSrc, WCHAR cEndChar);int des3_DecryptBuffer(unsigned char* key, unsigned char* iv, unsigned char* in_dec, unsigned char* out_dec, int in_len, int* out_len);int des3_EncryptBuffer(unsigned char* key, unsigned char* iv, unsigned char* in_enc, unsigned char* out_enc, int in_len, int* out_len);BOOL php_time_2_systemtime(long lPhpTime, SYSTEMTIME* pst)  {      BOOL        bRc = FALSE;      time_t      tmt = -1;      struct tm*  pGmt = NULL;      do       {          if (NULL == pst)              break;          tmt = lPhpTime;          pGmt = gmtime(&tmt);          if (NULL == pGmt)              break;          pst->wYear = 1900 + pGmt->tm_year;          pst->wMonth = 1 + pGmt->tm_mon;          pst->wDay = pGmt->tm_mday;          pst->wHour = pGmt->tm_hour;          pst->wMinute = pGmt->tm_min;          pst->wSecond = pGmt->tm_sec;          pst->wDayOfWeek = pGmt->tm_wday;          bRc = TRUE;      } while (0);      return bRc;  }  static void fn_copy_by_end_char(WCHAR * pDst, WCHAR * pSrc, WCHAR cEndChar){    DWORD dwIndex = 0;    if((NULL != pDst) && (NULL != pSrc))    {        do        {            if((L'\0' == pSrc[dwIndex]) || (cEndChar == pSrc[dwIndex]))            {                break;            }            pDst[dwIndex] = pSrc[dwIndex];            dwIndex++;        }        while(1);    }}/** key:加密密钥,3DES密钥size = 24* iv:加密初始向量* in_dec:密文数组,输入数组* out_dec:解密后的数组,输出数组* in_len:密文长度* out_len:明文长度* *///解密函数int des3_DecryptBuffer(unsigned char* key, unsigned char* iv, unsigned char* in_dec, unsigned char* out_dec, int in_len, int* out_len){    int out1 = 0;  //第一次使用update解密的数据长度    int out2 = 0; //剩余的字段,经过final解密并去除填充后的长度    int rv = 0;    EVP_CIPHER_CTX ctx;    //初始化ctx    EVP_CIPHER_CTX_init(&ctx);    //设置解密的算法、key和iv    // java端加密模式采用, "DESede/CBC/PKCS5Padding", so 参数2为EVP_des_ede3_cbc()    rv = EVP_DecryptInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, key, iv);    if (rv != 1) {        EVP_CIPHER_CTX_cleanup(&ctx);        return -1;    }    //循环读取原文,解密后后保存到明文文件。    rv = EVP_DecryptUpdate(&ctx, out_dec, &out1, in_dec, in_len);//解密    if (rv != 1) {        EVP_CIPHER_CTX_cleanup(&ctx);        return -1;    }    //解密结束    rv = EVP_DecryptFinal_ex(&ctx, out_dec + out1, &out2);    if (rv != 1) {        EVP_CIPHER_CTX_cleanup(&ctx);        return -1;    }    *out_len = (out1 + out2);    EVP_CIPHER_CTX_cleanup(&ctx);//清除EVP加密上下文环境    return 0;}int des3_EncryptBuffer(unsigned char* key, unsigned char* iv, unsigned char* in_enc, unsigned char* out_enc, int in_len, int* out_len){    int out1 = 0;  //第一次使用update解密的数据长度    int out2 = 0; //剩余的字段,经过final解密并去除填充后的长度    int rv = 0;    EVP_CIPHER_CTX ctx;    //初始化ctx    EVP_CIPHER_CTX_init(&ctx);    //设置解密的算法、key和iv    // java端加密模式采用, "DESede/CBC/PKCS5Padding", so 参数2为EVP_des_ede3_cbc()    rv = EVP_EncryptInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, key, iv);    if (rv != 1) {        EVP_CIPHER_CTX_cleanup(&ctx);        return -1;    }    //循环读取原文,解密后后保存到明文文件。    rv = EVP_EncryptUpdate(&ctx, out_enc, &out1, in_enc, in_len);//解密    if (rv != 1) {        EVP_CIPHER_CTX_cleanup(&ctx);        return -1;    }    //解密结束    rv = EVP_EncryptFinal_ex(&ctx, out_enc + out1, &out2);    if (rv != 1) {        EVP_CIPHER_CTX_cleanup(&ctx);        return -1;    }    *out_len = (out1 + out2);    EVP_CIPHER_CTX_cleanup(&ctx);//清除EVP加密上下文环境    return 0;}_3DES_CRYPT_HELPER_API const char* __stdcall IF_3DES_CryptHlerper_encrypt(/*IN*/ const char* psz_plain_txt, /*IN*/ const char* psz_key){    USES_CONVERSION;    DWORD dwRc = IF_ERR_UNKNOWN;    unsigned char key[EVP_MAX_KEY_LENGTH]; //保存密钥的数组    unsigned char iv[EVP_MAX_IV_LENGTH]; //保存初始化向量的数组    char* psz_plain_txt_new = NULL;    int ilen_plain_txt_new = 0;    char* psz_cipher_txt = NULL;    int ilen_cipher_txt = 0;    char* psz_base64_txt = NULL;    int ilen_base64_txt = 0;    UINT ulRc = 0;    UINT ulLenOut = 0;    int iLenEncOut = 0;    memset(key, 0, sizeof(key));    memset(iv, 0, sizeof(iv));    g_str_txt_was_encrypt.clear();    // 设置IV    // static final byte m_iv8_byte_ary[] = {0,0,0,0,0,0,0,0};    // java加密时, iv就8个字节    memset(iv, 0, sizeof(iv));    FILL_MY_IV    do    {        if ((NULL == psz_plain_txt) || (strlen(psz_plain_txt) <= 0))        {            dwRc = IF_ERR_PARAM1_INVALID;            break;        }        if ((NULL == psz_key) || (strlen(psz_key) != 24))        {            dwRc = IF_ERR_PARAM2_INVALID;            break;        }        // 设置key, 3DES Key is 24bytes        // String str_key = new String("123456781234567812345678");        memcpy(key, psz_key, 24);        ilen_plain_txt_new = strlen(psz_plain_txt);        if (0 != (ilen_plain_txt_new % 16)) {            ilen_plain_txt_new = ilen_plain_txt_new - (ilen_plain_txt_new % 16) + 16; // base64还会再长一些        }        psz_plain_txt_new = new char[ilen_plain_txt_new + 1];        ZeroMemory(psz_plain_txt_new, ilen_plain_txt_new + 1);        strcpy(psz_plain_txt_new, psz_plain_txt);        ilen_cipher_txt = ilen_plain_txt_new * 2;        psz_cipher_txt = new char[ilen_cipher_txt + 1];        ZeroMemory(psz_cipher_txt, ilen_cipher_txt + 1);        ilen_base64_txt = ilen_cipher_txt * 2;        psz_base64_txt = new char[ilen_base64_txt + 1];        ZeroMemory(psz_base64_txt, ilen_base64_txt + 1);        iLenEncOut = ilen_cipher_txt;        if (0 != des3_EncryptBuffer(key, iv, (BYTE*)psz_plain_txt_new, (BYTE*)psz_cipher_txt, ilen_plain_txt_new, &iLenEncOut)) {            break;        }        // base64        ulLenOut = 0;        ulRc = ns_ls::base64_encode((const BYTE *)psz_cipher_txt, iLenEncOut, (BYTE *)psz_base64_txt, ulLenOut);        // test ok//         UINT i_tmp_len_out = 0;//         ZeroMemory(psz_cipher_txt, ilen_cipher_txt + 1);//         ulRc = ns_ls::base64_decode((const BYTE *)psz_base64_txt, ulLenOut, (BYTE*)psz_cipher_txt, i_tmp_len_out);        g_str_txt_was_encrypt = psz_base64_txt;    }    while(0);    if (NULL != psz_plain_txt_new) {        delete[] psz_plain_txt_new;        psz_plain_txt_new = NULL;    }    if (NULL != psz_cipher_txt) {        delete[] psz_cipher_txt;        psz_cipher_txt = NULL;    }    if (NULL != psz_base64_txt) {        delete[] psz_base64_txt;        psz_base64_txt = NULL;    }    return g_str_txt_was_encrypt.c_str();}_3DES_CRYPT_HELPER_API const char* __stdcall IF_3DES_CryptHlerper_decrypt(/*IN*/ const char* psz_cipher_txt, /*IN*/ const char* psz_key){    USES_CONVERSION;    DWORD dwRc = IF_ERR_UNKNOWN;    unsigned char key[EVP_MAX_KEY_LENGTH]; //保存密钥的数组    unsigned char iv[EVP_MAX_IV_LENGTH]; //保存初始化向量的数组    char* psz_un_base64_txt = NULL;    int ilen_un_base64_txt = 0;    char* psz_plain_txt = NULL;    int ilen_plain_txt = 0;    UINT ulRc = 0;    UINT ulLenOut = 0;    int iLenDecOut = 0;    memset(key, 0, sizeof(key));    memset(iv, 0, sizeof(iv));    g_str_txt_was_encrypt.clear();    // 设置IV    // static final byte m_iv8_byte_ary[] = {0,0,0,0,0,0,0,0};    // java加密时, iv就8个字节    memset(iv, 0, sizeof(iv));    FILL_MY_IV    do    {        if ((NULL == psz_cipher_txt) || (strlen(psz_cipher_txt) <= 0))        {            dwRc = IF_ERR_PARAM1_INVALID;            break;        }        if ((NULL == psz_key) || (strlen(psz_key) != 24))        {            dwRc = IF_ERR_PARAM2_INVALID;            break;        }        // 设置key, 3DES Key is 24bytes        // String str_key = new String("123456781234567812345678");        memcpy(key, psz_key, 24);        ilen_un_base64_txt = strlen(psz_cipher_txt);        psz_un_base64_txt = new char[ilen_un_base64_txt + 1];        ZeroMemory(psz_un_base64_txt, ilen_un_base64_txt + 1);        ilen_plain_txt = ilen_un_base64_txt;        psz_plain_txt = new char[ilen_plain_txt + 1];        ZeroMemory(psz_plain_txt, ilen_plain_txt + 1);        // unbase64        ulLenOut = 0;        ulRc = ns_ls::base64_decode((const BYTE *)psz_cipher_txt, strlen(psz_cipher_txt), (BYTE *)psz_un_base64_txt, ulLenOut);        iLenDecOut = ulLenOut;        if (0 != des3_DecryptBuffer(key, iv, (BYTE*)psz_un_base64_txt, (BYTE*)psz_plain_txt, ulLenOut, &iLenDecOut)) {            break;        }        psz_plain_txt[iLenDecOut] = '\0';        g_str_txt_was_decrypt = psz_plain_txt;    }    while(0);    if (NULL != psz_un_base64_txt) {        delete[] psz_un_base64_txt;        psz_un_base64_txt = NULL;    }    if (NULL != psz_plain_txt) {        delete[] psz_plain_txt;        psz_plain_txt = NULL;    }    return g_str_txt_was_decrypt.c_str();}
// LsBase64.cpp: implementation of the LsBase64 class.////////////////////////////////////////////////////////////////////////#include "stdafx.h"#include <stdlib.h>#include <stdio.h>#include <iostream>#include <string.h>#include "LsBase64.h"// https://www.codeproject.com/Tips/813146/Fast-base-functions-for-encode-decode//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////using namespace std;namespace ns_ls{    static const std::string base64_chars =        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"        "abcdefghijklmnopqrstuvwxyz"        "0123456789+/";    static inline bool is_base64(unsigned char c)    {        return (isalnum(c) || (c == '+') || (c == '/'));    }    unsigned int base64_encode(const unsigned char* bytes_to_encode, unsigned int in_len, unsigned char* encoded_buffer, unsigned int& out_len)    {        int i = 0;        int j = 0;        unsigned char char_array_3[3] = { 0, 0, 0 };        unsigned char char_array_4[4] = { 0, 0, 0, 0 };        out_len = 0;        while (in_len--) {            char_array_3[i++] = *(bytes_to_encode++);            if (i == 3) {                char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;                char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);                char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);                char_array_4[3] = char_array_3[2] & 0x3f;                for (i = 0; i < 4 ; i++) {                    encoded_buffer[out_len++] = base64_chars[char_array_4[i]];                }                i = 0;            }        }        if (i) {            for (j = i; j < 3; j++) {                char_array_3[j] = '\0';            }            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);            char_array_4[3] = char_array_3[2] & 0x3f;            for (j = 0; j < (i + 1); j++) {                encoded_buffer[out_len++] = base64_chars[char_array_4[j]];            }            while (i++ < 3) {                encoded_buffer[out_len++] = '=';            }        }        return out_len;    }    unsigned int base64_decode(const unsigned char* encoded_string, unsigned int in_len, unsigned char* decoded_buffer, unsigned int& out_len)    {        size_t i = 0;        size_t j = 0;        int in_ = 0;        unsigned char char_array_3[3] = { 0, 0, 0 };        unsigned char char_array_4[4] = { 0, 0, 0, 0 };        out_len = 0;        while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {            char_array_4[i++] = encoded_string[in_];            in_++;            if (i == 4) {                for (i = 0; i < 4; i++) {                    char_array_4[i] = static_cast<unsigned char>(base64_chars.find(char_array_4[i]));                }                char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);                char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);                char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];                for (i = 0; i < 3; i++) {                    decoded_buffer[out_len++] = char_array_3[i];                }                i = 0;            }        }        if (i) {            for (j = i; j < 4; j++) {                char_array_4[j] = 0;            }            for (j = 0; j < 4; j++) {                char_array_4[j] = static_cast<unsigned char>(base64_chars.find(char_array_4[j]));            }            char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);            char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);            char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];            for (j = 0; (j < i - 1); j++) {                decoded_buffer[out_len++] = char_array_3[j];            }        }        return out_len;    }}
原创粉丝点击