热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

对称加解密的综合例子

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

 



推荐阅读
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有