cpp对称加解密的综合例子.cpp:此文件包含main函数。程序执行将在此处开始并结束。需要这些依赖项:libssl.lib;Ws2_32.lib;libcrypto.lib;CR
cpp
// 对称加解密的综合例子.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// 需要这些依赖项:libssl.lib;Ws2_32.lib;libcrypto.lib;CRYPT32.lib
//
#include
#include
#include "openssl/evp.h"
#include
#include
/*加密*/
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:" <'\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:" <'\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:" <'\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:" <'\n';
return EXIT_SUCCESS;
}View Code