赞
踩
OpenSSL库是由C语言实现,整个软件包大概可以分成三个主要的功能部分:密码算法库、SSL协议库以及应用程序。OpenSSL是目前主流的基于密码学的安全开发包,提供的功能相当强大和全面,包括了主要的密码算法、常用的密钥和证书封装管理功能以及SSL协议,并提供了丰富的应用程序供测试或其它目的使用。
OpenSSL库具有以下优点:1.功能全面,支持大部分主流密码算法、相关标准协议和SSL协议;2.开放源代码,可信任,能根据自己需要进行修改,对技术人员有借鉴和研究的价值;3.具备应用程序,既能直接使用,也可方便地进行二次开发;4.免费,也可用作非商业用途;5.应用广泛且持续更新
openssl库的下载和环境配置这里就不描述了。。。
Openssl EVP(high-level cryptographic functions) 提供了丰富的密码学中的各种函数,包括各种对称算法、摘要算法以及签名/验签算法。下面重点学习使用 DES 和 AES 两种对称加密算法。
在使用 EVP 库进行对称加密时,通常需要创建一个EVP_CIPHER_CTX 结构体对象,并通过一系列函数对其进行初始化、配置,最终进行加密操作。常用的 EVP_CIPHER_CTX 结构体初始化函数为 EVP_CIPHER_CTX_new() 和 EVP_CIPHER_CTX_init()。
EVP_CIPHER_CTX_new() 函数在堆上为 EVP_CIPHER_CTX 结构体分配内存空间,并将其所有成员变量初始化为 0;EVP_CIPHER_CTX_init() 函数则用于初始化 EVP_CIPHER_CTX结构体对象的成员变量。
在加密操作完成后,需要通过调用 EVP_CIPHER_CTX_cleanup 函数释放 EVP_CIPHER_CTX结构体对象的内存空间,以免内存泄漏。下面为EVP库的初始化代码:
- EVP_CIPHER_CTX∗ ctx = EVP_CIPHER_CTX_new() ; //结构体对象ctx分配内存空间
- EVP_CIPHER_CTX_init( ctx ) ; //初始化结构体对象ctx
- EVP_CIPHER_CTX_cleanup( ctx ) ; //释放结构体对象空间
在 DES 加密中,常见的 EVP_CIPHER 对象的类型有 EVP_des_ecb(),进行一次 des 的 ecb 模式加密;EVP_des_cbc()、EVP_des_ede3_cbc()。
在 AES 加密中,常见的 EVP_CIPHER 对象类型有:
EVP_aes_128_cbc、EVP_aes_192_cbc、EVP_aes_256_cbc:分别表示使用 AES 算法和 CBC 模式进行加密和解密,密钥长度分别为
128、192 和 256 位。
EVP_aes_128_ecb、EVP_aes_192_ecb、EVP_aes_256_ecb:分别表示使用 AES 算法和 ECB 模式进行加密和解密,密钥长度分别为 128、192 和 256 位。
EVP_aes_128_gcm、EVP_aes_256_gcm:分别表示使用 AES 算法和 GCM 模式进行加密和解密,密钥长度分别为 128 和 256 位。
下面列出两种加密方式
加密:将test.jpg加密另存为test.enc
#include <iostream> #include <fstream> #include <string> #include <openssl/err.h> #include <openssl/evp.h> #include <openssl/pem.h> using namespace std; #define READ_BUFF 1024 int main() { const unsigned char key[32] = "0123456789abcdef"; const unsigned char iv[16] = "edcba9876543210"; //创建一个 EVP_CIPHER_CTX 对象 EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); //选择加密算法 const EVP_CIPHER *cipher = EVP_aes_256_cbc(); //初始化加密上下文 EVP_CIPHER_CTX_init(ctx); //设置密钥和偏移量 EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv); std::ifstream in("test.jpg", ifstream::in | ios::binary); if (!in.is_open()) { std::cerr << "Failed to open file." << std::endl; return 1; } ofstream out("test.enc", ios::binary); if (!out) { perror("fopen"); return 1; } //加密文件内容并写入新文件 int out_len = 0; char inbuf[READ_BUFF]; char outbuf[READ_BUFF + 520]; while (!in.eof()) { in.read(inbuf, READ_BUFF); int read_len = in.gcount(); if (!EVP_EncryptUpdate(ctx, (unsigned char*)outbuf, &out_len, (unsigned char*)inbuf, read_len)) { cerr << "EVP_EncryptUpdate failed" << endl; return -1; } out.write(outbuf, out_len); } in.close(); if (!EVP_EncryptFinal_ex(ctx, (unsigned char*)outbuf, &out_len)) { cerr << "EVP_EncryptFinal_ex failed" << endl; return -1; } out.write(outbuf, out_len); out.close(); //销毁加密上下文 EVP_CIPHER_CTX_cleanup(ctx); return 0; }
解密:将test.enc解密另存为test2.jpg,解密用到的key和iv需同加密一致
#include <iostream> #include <fstream> #include <string> #include <openssl/err.h> #include <openssl/evp.h> #include <openssl/pem.h> using namespace std; #define READ_BUFF 1024 int main() { const unsigned char key[32] = "0123456789abcdef"; const unsigned char iv[16] = "edcba9876543210"; EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); const EVP_CIPHER *cipher = EVP_aes_256_cbc(); EVP_CIPHER_CTX_init(ctx); EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv); // 读取加密文件内容 std::ifstream in("test.enc", ifstream::in | ios::binary); if (!in.is_open()) { std::cerr << "failed to open encode file." << std::endl; return 1; } ofstream out("test2.jpg", ios::binary); if (!out) { cerr << "failed to create decode file!" << endl; return -1; } //解密文件内容并写入 int out_len = 0; char inbuf[READ_BUFF]; char outbuf[READ_BUFF + 520]; while (!in.eof()) { in.read(inbuf, READ_BUFF); int read_len = in.gcount(); if (!EVP_DecryptUpdate(ctx, (unsigned char*)outbuf, &out_len, (unsigned char*)inbuf, read_len)) { cerr << "EVP_DecryptUpdate failed" << endl; return 1; } out.write(outbuf, out_len); } in.close(); if (!EVP_DecryptFinal_ex(ctx, (unsigned char*)outbuf, &out_len)) { cerr << "EVP_DecryptFinal_ex failed" << endl; return 1; } out.write(outbuf, out_len); out.close(); //销毁解密上下文 EVP_CIPHER_CTX_cleanup(ctx); return 0; }
加密封装
/* *DES加密 ecb模式 *in_buffer:输入的明文 *in_length:明文长度 *key:密匙 */ std::string des_encrypt(const char* in_buffer, int in_length,const std::string &key) { std::string cipherText; // 密文 DES_cblock keyEncrypt; memset(keyEncrypt, 0, 8); // 构造补齐后的密钥 if (key.length() <= 8) memcpy(keyEncrypt, key.c_str(), key.length()); else memcpy(keyEncrypt, key.c_str(), 8); // 密钥置换 DES_key_schedule keySchedule; DES_set_key_unchecked(&keyEncrypt, &keySchedule); // 循环加密,每8字节一次 const_DES_cblock inputText; DES_cblock outputText; std::vector<unsigned char> vecCiphertext; unsigned char tmp[8]; for (int i = 0; i < in_length / 8; i++) { memcpy(inputText, in_buffer + i * 8, 8); DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT); memcpy(tmp, outputText, 8); vecCiphertext.insert(vecCiphertext.end(), tmp, tmp + 8); } if (in_length % 8 != 0) { int tmp1 = in_length / 8 * 8; int tmp2 = in_length - tmp1; memset(inputText, 0, 8); memcpy(inputText, in_buffer + tmp1, tmp2); DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT); memcpy(tmp, outputText, tmp2); vecCiphertext.insert(vecCiphertext.end(), tmp, tmp + tmp2); } cipherText.clear(); cipherText.assign(vecCiphertext.begin(), vecCiphertext.end()); return cipherText; }
解密封装
/* *DES解密 ecb模式 *in_buffer:输入的密文 *in_length:密文长度 *key:密匙 */ std::string des_decrypt(const char* in_buffer, int in_length, const std::string &key) { std::string clearText; // 明文 DES_cblock keyEncrypt; memset(keyEncrypt, 0, 8); if (key.length() <= 8) memcpy(keyEncrypt, key.c_str(), key.length()); else memcpy(keyEncrypt, key.c_str(), 8); DES_key_schedule keySchedule; DES_set_key_unchecked(&keyEncrypt, &keySchedule); const_DES_cblock inputText; DES_cblock outputText; std::vector<unsigned char> vecCleartext; unsigned char tmp[8]; for (int i = 0; i < in_length / 8; i++) { memcpy(inputText, in_buffer + i * 8, 8); DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT); memcpy(tmp, outputText, 8); vecCleartext.insert(vecCleartext.end(), tmp, tmp + 8); } if (in_length % 8 != 0) { int tmp1 = in_length / 8 * 8; int tmp2 = in_length - tmp1; memset(inputText, 0, 8); memcpy(inputText, in_buffer + tmp1, tmp2); DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT); memcpy(tmp, outputText, tmp2); vecCleartext.insert(vecCleartext.end(), tmp, tmp + tmp2); } clearText.clear(); clearText.assign(vecCleartext.begin(), vecCleartext.end()); return clearText; }
调用方式
int main(int argc, char **argv) { //加密 { std::ifstream file("test.jpg", ifstream::in | ios::binary); if (!file.is_open()) { std::cerr << "Failed to open file." << std::endl; return 1; } std::string srcText; while (!file.eof()) { char buffer[1024]; file.read(buffer, 1024); srcText.append(buffer, file.gcount()); } file.close(); std::string encryptText; std::string encryptHexText; std::string decryptText; std::string desKey = "12345"; encryptText = des_encrypt(srcText.data(), srcText.length(), desKey); ofstream out("test.enc", ios::binary); if (!out) { perror("fopen"); return 1; } out.write(encryptText.data(), encryptText.length()); out.close(); } //解密 { // 打开加密文件 std::ifstream file_out("test.enc", ios::binary); if (!file_out.is_open()) { std::cerr << "Failed to open file." << std::endl; return 1; } std::string content; while (!file_out.eof()) { char buffer[1024]; file_out.read(buffer, 1024); content.append(buffer, file_out.gcount()); } file_out.close(); decryptText = des_decrypt(content.data(), content.length(), desKey); ofstream out2("test2.jpg", ios::binary); if (!out) { perror("fopen2"); return 1; } out2.write(decryptText.data(), decryptText.length()); out2.close(); } system("pause"); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。