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; }}
阅读全文
0 0
- 3DES crypt helper
- crypt
- DES & 3DES算法
- DES/3DES/AES
- DES/3DES/AES
- DES、3DES
- java 3des des
- DES、3DES
- DES、3DES、AES
- des与3des
- Helper
- DES(ECB) DES(CBC) 3DES
- 3DES
- 3des
- 3DES
- 3DES
- 3DES
- 3DES
- 洛谷oj P1196 银河英雄传说 ( 并查集
- express -V无效的解决方法
- (2)ffmpeg命令行工具的帮助中文
- 开启Maven解密之门
- resultType和resultMap区别
- 3DES crypt helper
- Redis 命令
- Effective Java读书笔记二四(Java Tips.Day.24)
- 死锁
- linux(一)文件处理命令
- keepalived+nginx的高可用
- Gradle总结
- SQL SERVER 2008 利用发布订阅方式实现数据库同步
- windbg远程调试方法