对称加解密的综合例子
cpp

// 对称加解密的综合例子.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // 需要这些依赖项:libssl.lib;Ws2_32.lib;libcrypto.lib;CRYPT32.lib // #include <iostream> #include <fstream> #include "openssl/evp.h" #include <vector> #include <initializer_list> /*加密*/ int do_encrypt_C(const EVP_CIPHER* type, const char* ctype); /*解密*/ int do_decypt_C(const EVP_CIPHER* type, const char* ctype); /*加密*/ int do_encrypt_CPP(const EVP_CIPHER* type, const char* ctype); /*解密*/ int do_decypt_CPP(const EVP_CIPHER* type, const char* ctype); int main() { do_encrypt_CPP(EVP_desx_cbc(), "dex-cbc"); do_decypt_CPP(EVP_desx_cbc(), "des-cbc"); } int do_encrypt_C(const EVP_CIPHER* type, const char* ctype) { unsigned char outbuf[1024]{ 0 }; int outlen{}, tmplen{}; unsigned char key[]{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, }; unsigned char iv[]{ 1,2,3,4,5,6,7,8 }; char in_text[] = "Hello world!"; /* * 原写法:EVP_CIPHER_CTX ctd; * 已经不再被使用的 */ EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); FILE* out{}; EVP_CIPHER_CTX_init(ctx); //初始化对称计算上下文。 //加密初始化函数,本函数调用具体算法的init回调函数,将外送密钥key转换为内部密钥形式,将初始化向量iv复制到CTX结构中。 /* * EVP_CIPHER_CTX *ctx, :输入参数,是已经被函数EVP_CIPHER_CTX_init初始化过的算法上下文结构体指针。 const EVP_CIPHER *cipher, :输入参数,表示具体的加密函数,它是一个指向EVP_CIPHER结构体的指针,指向一个EVP_CIPHER*类型的函数。在OpenSSL中,对称加密算法的格式都以函数形式提供,其实该函数返回一个该算法的结构体 ENGINE *impl, :输入参数,指向ENGINE结构体的指针,表示加密算法的引擎,可以理解为加密算法的提供者,比如是硬件加密卡提供者、软件算法提供者等,如果取值为NULL,就使用默认引擎。 const unsigned char *key, :输入参数,表示加密密钥,长度根据不同的加密算法而定。 const unsigned char *iv :输入参数,初始向量,当cipher所指的算法为CBC模式的算法才有效,因为CBC模式需要初始向量的输入,长度是对称算法分组长度。 返回值:如果函数执行成功就返回1,否则返回0。 值得注意的是,key和iv的长度都是根据不同算法而有默认值的,比如DES算法的key和iv都是8字节长度;3DES算法的key的长度是24字节,iv是8字节;128位的AES算法的key和iv都是16字节。使用时要先根据算法分配好key和iv的长度空间。 */ EVP_EncryptInit_ex(ctx, type, nullptr, key, iv); //加密函数,用于多次计算,它调用了具体算法的do_cipher回调函数。 /* * 该函数执行对数据的加密。 * EVP_CIPHER_CTX *ctx, :输入参数,指向EVP_CIPHER_CTX的指针,应该已经初始化过了。 unsigned char *out, :输出参数,指向存放输出密文的缓冲区指针。 int *outl, :输出参数,输出密文的长度。 const unsigned char *in, :输入参数,指向存放明文的缓冲区指针。 int inl :输入参数,要加密的明文长度。 返回值:如果函数执行成功就返回1,否则返回0。 */ if (!(EVP_EncryptUpdate(ctx, outbuf, &outlen, (unsigned char*)in_text, (int)strlen(in_text)))) { std::cout << "EVP_EncryptUpdate\n"; return EXIT_FAILURE; } //获取加密结果,函数可能涉及填充,它调用了具体算法的do_cipher回调函数。 /* * EVP_CIPHER_CTX *ctx, :输入参数,EVP_CIPHER_CTX结构体。 unsigned char *out, :输出参数,指向输出密文缓冲区的指针。 int *outl :输出参数,指向一个整型变量,该变量存储输出的密文数据长度。 返回值:如果函数执行成功就返回1,否则返回0。 */ if (!(EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen))) { std::cout << "EVP_EncryptFinal_ex\n"; return EXIT_FAILURE; } outlen += tmplen; //清除对称算法上下文数据,它调用用户提供的销毁函数清除内存中的内部密钥以及其他数据。 EVP_CIPHER_CTX_cleanup(ctx); out = fopen("./cipher", "wb+"); fwrite(outbuf, 1, outlen, out); fflush(out); fclose(out); return EXIT_SUCCESS; } int do_decypt_C(const EVP_CIPHER* type, const char* ctype) { unsigned char inbuf[1024]{}; unsigned char outbuf[1024]{}; int outlen{}, inlen{}, tmplen{}; unsigned char key[]{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, }; unsigned char iv[]{ 1,2,3,4,5,6,7,8 }; EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); FILE* in{}; EVP_CIPHER_CTX_init(ctx); ////解密初始化函数。 //和加密一样,解密时也要先初始化,用于设置密码算法、加密引擎、密钥、初始向量等参数。 /* * EVP_CIPHER_CTX *ctx, :输入参数;EVP_CIPHER_CTX结构体。 const EVP_CIPHER *cipher, :输入参数;指向EVP_CIPHER,表示要使用的解密算法。 ENGINE *impl, :输入参数;指向ENGINE,表示解密算法使用的加密引擎。应用程序可以使用自定义的加密引擎,如硬件加密算法等。如果取值为NULL,就使用默认引擎。 const unsigned char *key, :输入参数;解密密钥,其长度根据解密算法的不同而不同。 const unsigned char *iv :输入参数;初始向量,根据算法的模式而确定是否需要,比如CBC模式是需要iv的。长度同分组长度。 返回值:如果函数执行成功就返回1,否则返回0。 */ EVP_DecryptInit_ex(ctx, type, nullptr, key, iv); in = fopen("./cipher", "rb"); inlen = fread(inbuf, 1, sizeof(inbuf), in); fclose(in); std::cout << "readlen:" << inlen << '\n'; //解密函数,用于多次计算,它调用了具体算法的do_cipher回调函数。 /* EVP_CIPHER_CTX *ctx, :输入参数;EVP_CIPHER_CTX结构体。 unsigned char *out, :输出参数;指向解密后存放明文的缓冲区。 int *outl, :输出参数;指向存放明文长度的整型变量。 const unsigned char *in, :输入参数;指向存放密文的缓冲区的指针。 int inl :输入参数;指向存放密文的整型变量。 返回值:如果函数执行成功就返回1,否则返回0。 */ if (!(EVP_DecryptUpdate(ctx, outbuf, &outlen, inbuf, inlen))) { std::cout << "EVP_DecryptUpdate\n"; return EXIT_FAILURE; } //获取解密结果,函数可能涉及填充,它调用了具体算法的do_cipher回调函数。 /* EVP_CIPHER_CTX *ctx, :输入参数;EVP_CIPHER_CTX结构体。 unsigned char *outm, :输出参数;指向输出的明文缓冲区指针。 int *outl :输入参数;指向存储明文长度的整型变量。 */ if (!(EVP_DecryptFinal_ex(ctx, outbuf + outlen, &tmplen))) { std::cout << "EVP_DecryptFinal_ex\n"; return EXIT_FAILURE; } outlen += tmplen; //清除对称算法上下文数据,它调用用户提供的销毁函数清除内存中的内部密钥以及其他数据。 EVP_CIPHER_CTX_cleanup(ctx); std::cout << "result:" << outbuf << '\n'; return EXIT_SUCCESS; } int do_encrypt_CPP(const EVP_CIPHER* type, const char* ctype) { unsigned char outbuf[1024]{ 0 }; int outlen{}, tmplen{}; unsigned char key[]{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, }; unsigned char iv[]{ 1,2,3,4,5,6,7,8 }; char in_text[] = "Hello world!"; /* * 原写法:EVP_CIPHER_CTX ctd; * 已经不再被使用的 */ EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); //FILE* out{}; EVP_CIPHER_CTX_init(ctx); EVP_EncryptInit_ex(ctx, type, nullptr, key, iv); if (!(EVP_EncryptUpdate(ctx, outbuf, &outlen, (unsigned char*)in_text, (int)strlen(in_text)))) { std::cout << "EVP_EncryptUpdate\n"; return EXIT_FAILURE; } if (!(EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen))) { std::cout << "EVP_EncryptFinal_ex\n"; return EXIT_FAILURE; } outlen += tmplen; EVP_CIPHER_CTX_cleanup(ctx); auto out = std::ofstream("./cipher", std::ios::out | std::ios::binary); out.write((char*)outbuf, strlen((char*)outbuf)); out.close(); /*out = fopen("./cipher", "wb+"); fwrite(outbuf, 1, outlen, out); fflush(out); fclose(out);*/ return EXIT_SUCCESS; } int do_decypt_CPP(const EVP_CIPHER* type, const char* ctype) { unsigned char inbuf[1024]{}; unsigned char outbuf[1024]{}; int outlen{}, inlen{}, tmplen{}; unsigned char key[]{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, }; unsigned char iv[]{ 1,2,3,4,5,6,7,8 }; EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); //FILE* in{}; EVP_CIPHER_CTX_init(ctx); EVP_DecryptInit_ex(ctx, type, nullptr, key, iv); auto in = std::ifstream("./cipher"); in.read((char*)inbuf, sizeof(inbuf)); inlen = strlen((char*)inbuf); /*in = fopen("./cipher", "rb"); inlen = fread(inbuf, 1, sizeof(inbuf), in); fclose(in);*/ in.close(); std::cout << "readlen:" << inlen << '\n'; if (!(EVP_DecryptUpdate(ctx, outbuf, &outlen, inbuf, inlen))) { std::cout << "EVP_DecryptUpdate\n"; return EXIT_FAILURE; } if (!(EVP_DecryptFinal_ex(ctx, outbuf + outlen, &tmplen))) { std::cout << "EVP_DecryptFinal_ex\n"; return EXIT_FAILURE; } outlen += tmplen; EVP_CIPHER_CTX_cleanup(ctx); std::cout << "result:" << outbuf << '\n'; return EXIT_SUCCESS; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?