C++ Openssl AES GCM 128bits代码示例,可wins直接运行

使用vcpkg安装64bits的openssl,本人当前的openssl为openssl-1.1.1d版本,wins10系统,使用visual studio2017编辑器

注意事项:如果使用Openssl 1.0的版本,需要使用EVP_CIPHER_CTX ctx;来定义ctx对象。具体看下面链接:https://github.com/openssl/openssl/issues/962

执行结果:

下面代码有两个版本,第一个是基础的没经过速度优化的但比较适合阅读的。第二个是为了性能特意优化了。

代码:

//g++ main.cpp -lcrypto#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <string>
#include <sstream>
#include <vector>
#include <iostream>using std::string;
using std::vector;
using std::cout;
using std::endl;void aes_init()
{static int init = 0;if (init == 0){EVP_CIPHER_CTX * e_ctx = EVP_CIPHER_CTX_new();EVP_CIPHER_CTX *d_ctx = EVP_CIPHER_CTX_new();//initialize openssl ciphersOpenSSL_add_all_ciphers();//initialize random number generator (for IVs)int rv = RAND_load_file("/dev/urandom", 32);EVP_CIPHER_CTX_free(e_ctx);EVP_CIPHER_CTX_free(d_ctx);}
}std::vector<unsigned char> aes_128_gcm_encrypt(std::string plaintext, std::string key)
{aes_init();size_t enc_length = plaintext.length() * 3;std::vector<unsigned char> output;output.resize(enc_length, '\0');unsigned char tag[AES_BLOCK_SIZE];unsigned char iv[AES_BLOCK_SIZE];RAND_bytes(iv, sizeof(iv));std::copy(iv, iv + 16, output.begin() + 16);int actual_size = 0, final_size = 0;EVP_CIPHER_CTX* e_ctx = EVP_CIPHER_CTX_new();//EVP_CIPHER_CTX_ctrl(e_ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL);EVP_EncryptInit(e_ctx, EVP_aes_128_gcm(), (const unsigned char*)key.c_str(), iv);EVP_EncryptUpdate(e_ctx, &output[32], &actual_size, (const unsigned char*)plaintext.data(), plaintext.length());EVP_EncryptFinal(e_ctx, &output[32 + actual_size], &final_size);EVP_CIPHER_CTX_ctrl(e_ctx, EVP_CTRL_GCM_GET_TAG, 16, tag);std::copy(tag, tag + 16, output.begin());std::copy(iv, iv + 16, output.begin() + 16);output.resize(32 + actual_size + final_size);EVP_CIPHER_CTX_free(e_ctx);return output;
}std::string aes_128_gcm_decrypt(std::vector<unsigned char> ciphertext, std::string key)
{aes_init();unsigned char tag[AES_BLOCK_SIZE];unsigned char iv[AES_BLOCK_SIZE];std::copy(ciphertext.begin(), ciphertext.begin() + 16, tag);std::copy(ciphertext.begin() + 16, ciphertext.begin() + 32, iv);std::vector<unsigned char> plaintext; plaintext.resize(ciphertext.size(), '\0');int actual_size = 0, final_size = 0;EVP_CIPHER_CTX *d_ctx = EVP_CIPHER_CTX_new();EVP_DecryptInit(d_ctx, EVP_aes_128_gcm(), (const unsigned char*)key.c_str(), iv);EVP_DecryptUpdate(d_ctx, &plaintext[0], &actual_size, &ciphertext[32], ciphertext.size() - 32);EVP_CIPHER_CTX_ctrl(d_ctx, EVP_CTRL_GCM_SET_TAG, 16, tag);EVP_DecryptFinal(d_ctx, &plaintext[actual_size], &final_size);EVP_CIPHER_CTX_free(d_ctx);plaintext.resize(actual_size + final_size, '\0');return string(plaintext.begin(), plaintext.end());
}int main(int argc, char **argv)
{aes_init();//create a sample keyunsigned char key_bytes[16];RAND_bytes(key_bytes, sizeof(key_bytes));string key = string((char *)key_bytes, sizeof(key_bytes));//text to encryptstring plaintext = "elephants in space";cout << plaintext << endl;//encryptvector<unsigned char> ciphertext = aes_128_gcm_encrypt(plaintext, key);//outputstatic const char *chars = "0123456789ABCDEF";for (int i = 0; i < ciphertext.size(); i++){cout << chars[ciphertext[i] / 16];cout << chars[ciphertext[i] % 16];}cout << endl;//decryptstring out = aes_128_gcm_decrypt(ciphertext, key);cout << out << endl;system("pause");
}

第二个代码:

//http://www.zedwood.com/article/cpp-openssl-aes-gcm-code-sample//http://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption//g++ main.cpp -lcrypto#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <string>
#include <sstream>
#include <vector>
#include <iostream>#include <chrono>using std::string;
using std::vector;
using std::cout;
using std::endl;
using namespace std;
using namespace chrono;EVP_CIPHER_CTX * e_ctx = nullptr;
EVP_CIPHER_CTX *d_ctx = nullptr;void aes_init()
{static int init = 0;if (init == 0){e_ctx = EVP_CIPHER_CTX_new();d_ctx = EVP_CIPHER_CTX_new();//initialize openssl ciphersOpenSSL_add_all_ciphers();//initialize random number generator (for IVs)int rv = RAND_load_file("/dev/urandom", 32);init++;}}//需要在函数外面使用free()释放参数out的内容
void aes_128_gcm_encrypt0(const char* plaintext, size_t plaintext_len,const char * key,unsigned char ** out, size_t & out_len) {size_t output_length = AES_BLOCK_SIZE + AES_BLOCK_SIZE + plaintext_len;unsigned char * output = (unsigned char*)malloc(output_length);RAND_bytes(output+16, 16);int actual_size = 0, final_size = 0;EVP_EncryptInit(e_ctx, EVP_aes_128_gcm(), (const unsigned char*)key, output + 16);EVP_EncryptUpdate(e_ctx, &output[32], &actual_size, (const unsigned char*)plaintext, plaintext_len);EVP_EncryptFinal(e_ctx, &output[32 + actual_size], &final_size);EVP_CIPHER_CTX_ctrl(e_ctx, EVP_CTRL_GCM_GET_TAG, 16, output);*out = output;out_len = output_length;
}std::vector<unsigned char> aes_128_gcm_encrypt(std::string plaintext, std::string key){size_t enc_length = plaintext.length() * 3;std::vector<unsigned char> output;output.resize(enc_length, '\0');unsigned char tag[AES_BLOCK_SIZE];unsigned char iv[AES_BLOCK_SIZE];RAND_bytes(iv, sizeof(iv));std::copy(iv, iv + 16, output.begin() + 16);int actual_size = 0, final_size = 0;EVP_CIPHER_CTX* e_ctx = EVP_CIPHER_CTX_new();//EVP_CIPHER_CTX_ctrl(e_ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL);EVP_EncryptInit(e_ctx, EVP_aes_128_gcm(), (const unsigned char*)key.c_str(), iv);EVP_EncryptUpdate(e_ctx, &output[32], &actual_size, (const unsigned char*)plaintext.data(), plaintext.length());EVP_EncryptFinal(e_ctx, &output[32 + actual_size], &final_size);EVP_CIPHER_CTX_ctrl(e_ctx, EVP_CTRL_GCM_GET_TAG, 16, tag);std::copy(tag, tag + 16, output.begin());std::copy(iv, iv + 16, output.begin() + 16);output.resize(32 + actual_size + final_size);EVP_CIPHER_CTX_free(e_ctx);return output;
}//需要在函数外面使用free()释放参数out的内容
void aes_128_gcm_decrypt0(const char* ciphertext, size_t ciphertext_len,const char * key,unsigned char ** out, size_t & out_len) {unsigned char *plaintext = (unsigned char*)malloc(ciphertext_len - 32);int actual_size = 0, final_size = 0;EVP_DecryptInit(d_ctx, EVP_aes_128_gcm(), (const unsigned char*)key, (unsigned char*)ciphertext+16);EVP_DecryptUpdate(d_ctx, plaintext, &actual_size, (const unsigned char*)&ciphertext[32], ciphertext_len - 32);EVP_CIPHER_CTX_ctrl(d_ctx, EVP_CTRL_GCM_SET_TAG, 16, (char*)ciphertext);EVP_DecryptFinal(d_ctx, &plaintext[actual_size], &final_size);*out = plaintext;out_len = ciphertext_len - 32;
}std::string aes_128_gcm_decrypt(std::vector<unsigned char> ciphertext, std::string key)
{unsigned char tag[AES_BLOCK_SIZE];unsigned char iv[AES_BLOCK_SIZE];std::copy(ciphertext.begin(), ciphertext.begin() + 16, tag);std::copy(ciphertext.begin() + 16, ciphertext.begin() + 32, iv);std::vector<unsigned char> plaintext; plaintext.resize(ciphertext.size(), '\0');int actual_size = 0, final_size = 0;EVP_CIPHER_CTX *d_ctx = EVP_CIPHER_CTX_new();EVP_DecryptInit(d_ctx, EVP_aes_128_gcm(), (const unsigned char*)key.c_str(), iv);EVP_DecryptUpdate(d_ctx, &plaintext[0], &actual_size, &ciphertext[32], ciphertext.size() - 32);EVP_CIPHER_CTX_ctrl(d_ctx, EVP_CTRL_GCM_SET_TAG, 16, tag);EVP_DecryptFinal(d_ctx, &plaintext[actual_size], &final_size);EVP_CIPHER_CTX_free(d_ctx);plaintext.resize(actual_size + final_size, '\0');return string(plaintext.begin(), plaintext.end());
}void test() {aes_init();//create a sample keyunsigned char key_bytes[16];RAND_bytes(key_bytes, sizeof(key_bytes));string key = string((char *)key_bytes, sizeof(key_bytes));//text to encryptstring plaintext = "elephants in space dsfsdfgdgdliangyihuaifgf";cout << plaintext << endl;//encrypt//vector<unsigned char> ciphertext = aes_128_gcm_encrypt(plaintext, key);unsigned char * enc_msg = nullptr;size_t enc_msg_len = -1;aes_128_gcm_encrypt0(plaintext.c_str(), plaintext.length(), key.c_str(), &enc_msg, enc_msg_len);vector<unsigned char> ciphertext;ciphertext.resize(enc_msg_len, '\0');std::copy(enc_msg, enc_msg + enc_msg_len, ciphertext.begin());//outputstatic const char *chars = "0123456789ABCDEF";for (int i = 0; i < ciphertext.size(); i++){cout << chars[ciphertext[i] / 16];cout << chars[ciphertext[i] % 16];}cout << endl;//decrypt//string out = aes_128_gcm_decrypt(ciphertext, key);//cout << out << endl;unsigned char * dec_msg = nullptr;size_t len_dec_msg = -1;aes_128_gcm_decrypt0((char*)enc_msg, enc_msg_len, key.c_str(), &dec_msg, len_dec_msg);vector<unsigned char> ciphertext_final;ciphertext_final.resize(len_dec_msg, '\0');std::copy(dec_msg, dec_msg + len_dec_msg, ciphertext_final.begin());for (int i = 0; i < len_dec_msg; i++) {cout << dec_msg[i];}cout << endl;free(enc_msg);free(dec_msg);
}void performanceTest() {aes_init();//create a sample keyunsigned char key_bytes[16];RAND_bytes(key_bytes, sizeof(key_bytes));string key = string((char *)key_bytes, sizeof(key_bytes));//text to encryptstring plaintext = "elephants in space dsfsdfgdgdliangyihuaifgf";cout << plaintext << endl;const int round = 10000;auto begin = std::chrono::high_resolution_clock::now();for (int i = 0; i < round; i++) {//encryptunsigned char * enc_msg = nullptr;size_t enc_msg_len = -1;aes_128_gcm_encrypt0(plaintext.c_str(), plaintext.length(), key.c_str(), &enc_msg, enc_msg_len);/*vector<unsigned char> ciphertext;ciphertext.resize(enc_msg_len, '\0');std::copy(enc_msg, enc_msg + enc_msg_len, ciphertext.begin());*///output/*static const char *chars = "0123456789ABCDEF";for (int i = 0; i < ciphertext.size(); i++){cout << chars[ciphertext[i] / 16];cout << chars[ciphertext[i] % 16];}cout << endl;*///decryptunsigned char * dec_msg = nullptr;size_t len_dec_msg = -1;aes_128_gcm_decrypt0((char*)enc_msg, enc_msg_len, key.c_str(), &dec_msg, len_dec_msg);/*vector<unsigned char> ciphertext_final;ciphertext_final.resize(len_dec_msg, '\0');std::copy(dec_msg, dec_msg + len_dec_msg, ciphertext_final.begin());for (int i = 0; i < len_dec_msg; i++) {cout << dec_msg[i];}cout << endl;*/free(enc_msg);free(dec_msg);}auto end = std::chrono::high_resolution_clock::now();double elapsedTime = ((duration<double, std::milli>)(end - begin)).count();cout << "\ntotal elapsed time: " << elapsedTime << ", ave = " << (elapsedTime / round) << endl;}int main(int argc, char **argv)
{test();performanceTest();EVP_CIPHER_CTX_free(e_ctx);EVP_CIPHER_CTX_free(d_ctx);system("pause");
}

http://www.zedwood.com/article/cpp-openssl-aes-gcm-code-sample

http://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption

C++ Openssl AES GCM 128bits代码示例,可wins10的visual studio 2017 中直接运行相关推荐

  1. 如何用visual studio 2017建立一个python项目并且编写一段简单代码

    在visual studio 2017编写python首先需要在vs中安装python工具,具体操作在我的上一篇博客中有介绍如何在visual studio 2017 中安装python工具 本人电脑 ...

  2. Openssl Aes加解密使用示例

    Openssl Aes加解密使用示例 Aes简介 设置Aes密钥 Aes算法CBC加解密 Aes简介 Aes是分组加密算法,主要基于块加密,选取固定长度的密钥去加密明文中固定长度的块,生成的密文块与明 ...

  3. vs2017c语言程序添加图标,笔试编程必备技巧——Visual Studio 2017添加自定义代码片段...

    本文目录 代码模板 代码片段功能 step by step 添加自定义代码片段 传送门--常用IDE实现代码片段的方法 代码模板 如何有限的笔试时间中提高编程效率?除了提高自身代码能力之外,事先的准备 ...

  4. 您如何计算Visual Studio解决方案中的代码行?

    是否可以在整个解决方案中找到代码行数? 我听说过MZ-Tools ,但是有没有开源的? #1楼 你可以使用: SCLOCCount http://www.dwheeler.com/sloccount/ ...

  5. 解决OpenSSL加入到在Visual Studio 2019中编译返回LNK2019错误

    文章目录 小结 问题和解决 Error LNK2019 Error LNK1104 Warning C4996 参考 小结 碰到了OpenSSL加入到在Visual Studio 2019中编译返回L ...

  6. 一起谈.NET技术,Visual Studio 2010 中的代码约定设置

    软件约定称为代码约定,通过这一约定可以表示代码正常工作所需的正式条件. 如果方法未按预期收到数据或生成的数据不符合预期的后置条件,代码约定将导致代码引发异常. 有关前置条件和后置条件的概述,您可能需要 ...

  7. vscode 注释多行代码_如何在Visual Studio Code中注释多行?

    我找不到在Visual Studio Code中注释和取消注释多行代码的方法. 是否可以使用某些快捷方式在Visual Studio Code中注释和取消注释多行? 如果是,该怎么办? 当其中一行已被 ...

  8. 在 Visual Studio Code 中添加自定义的代码片段

    无论是那个编辑器,如果能够添加一些自定义代码片段,能够大大提升代码的输入效率. 本文介绍如何在 Visual Studio Code 中添加自定义代码片段. 本文内容 Visual Studio Co ...

  9. 分享好用的文本代码编辑器和源代码编辑器【notepad++,Visual Studio Code】

    文章目录 notepad++介绍 Visual Studio Code介绍 今天在这里给学习者和开发者分享好用的代码编辑器[notepad++]和[Visual Studio Code] notepa ...

最新文章

  1. 2022-2028年中国塑料安瓿瓶行业市场研究及前瞻分析报告
  2. 总结|深度学习实现缺陷检测
  3. 【java】人脸识别 虹软ArcFace 2.0-抽取人脸特征并做比对
  4. 通过ajax提交到url路由
  5. c++ 快速排序_常用排序算法之快速排序
  6. 百位云计算专家齐聚湖畔大学,阿里云MVP全球闭门会聚焦数字化转型
  7. ListView问题:Your content must have a ListView wh...
  8. 三维点云学习(4)3-Model Fitting Least Square
  9. RHEL6基础二十四之RHEL软件包管理③源码安装
  10. linux 安装pyaudio
  11. Vue 不睡觉教程3 - 来点实在的:自动计算剩余时间的任务列表
  12. vin码构成以及自动识别的用途。
  13. 【元器件】芯片封装汇总
  14. README.md的内容格式
  15. MySQL完全卸载干净(图解)
  16. 图库highcharts联合jquery ajax 后端取数据前端图表渲染
  17. The Unarchiver for Mac(mac解压缩神器)
  18. 双边滤波(bilateral filter)以及联合双边滤波(joint bilateral filter)
  19. [经验教程]支付宝好友被删除了怎么知道及支付宝好友删除是单向还是双向?
  20. jquary学习(一)jquary简介

热门文章

  1. java如何画周期sanjiao信号_如何声明一个可变长度的std_logic_vector信号
  2. 如何用excle制作黑人拉馆_家居DIY带你学习如何用塑料勺制作壁挂!
  3. HTTP 内容编码,也就这 2 点需要知道 | 实用 HTTP
  4. 记一次腾讯霸面---前端
  5. 因Facebook帖子涉嫌包含仇恨言论 德国警方突击搜查36名用户住所
  6. AOSuite V2.7 发布,JavaEE快速开发平台
  7. 王高利:Kvm虚拟化(1)__基础搭建
  8. 20151020sql2
  9. Linux中listen()系统调用的backlog参数分析
  10. js隐藏或显示某区域