Openssl Crypto 加/解密功能封装之一:进制转换

本文详细介绍了使用OpenSSL实现加密/解密功能的封装过程,并提供了二进制转十六进制与十六进制转二进制的代码示例。通过源码分析,展示了如何在特定系统环境下配置环境变量并成功编译运行。

1、环境

OpenSSL 版本:openssl-0.9.8d

请确保系统存在环境变量 SSL_ROOT, $SSL_ROOT/lib 存在 crypto 库文件,$SSL_ROOT/lib 已加入 LD_LIBRARY_PATH 中。

测试过的系统版本:RHEL 4.8 32 bit,AIX 5.3 64bit

 

2、源码

 

/*
 * NumSysConvert.h
 *
 *  基于 Openssl crypto 库的加密/解密功能封装
 *
 *  Created on: Mar 11, 2012
 *      Author: yeyuzhen<mail.yeyuzhen@gmail.com>
 */

#ifndef NUMSYSCONVERT_H_
#define NUMSYSCONVERT_H_

#include <iostream>
#include <string>

#include <openssl/x509v3.h>

/**
* @brief 二进制转十六进制
* @author 
*/
inline std::string Bin2Hex(std::string _in)
{
	std::string result;
	const char hexdig[] = "0123456789ABCDEF";

	if(_in.empty())
	{
		return result;
	}

	result.clear();
	for(std::string::iterator i = _in.begin(); i != _in.end(); i++)
	{
		result.append(1, hexdig[(*i >> 4) & 0xf]);  //留下高四位
		result.append(1, hexdig[(*i & 0xf)]);  //留下低四位

	}

	return result;
}


/**
* @brief 十六进制转二进制
* @author 
*/
inline std::string Hex2Bin(std::string _in)
{
	long int binSize = 0;
	unsigned char *t = NULL;
	std::string result;

	t = string_to_hex((char *)_in.c_str(), &binSize);  // 位于 x509v3.h

	result.clear();
	result.append((char *)t, binSize);

	return result;
}

#endif /* NUMSYSCONVERT_H_ */


 

/*
 * main.cpp
 *   
 *   进制转换测试
 *
 */

#include <iostream>
#include <string>

#include "NumSysConvert.h"

int main(int argc, char *argv[])
{
	char Bin[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
	std::string AllBin(Bin, 8);
	std::cout << "All Hex:" << Bin2Hex(AllBin) << std::endl;
	
	// 可查看内存值
	// gdb 单步执行到 line 19
	// (gdb) print AllBinResult
	// 记下 string 的底层字符串 _M_p 地址 0x??????
	// (gdb) x/8xb 0x??????
	std::string AllHex("0123456789ABCDEF");
	std::string AllBinResult = Hex2Bin(AllHex);
	std::cout << "All Bin" << AllBinResult << std::endl;
	
	// 非法十六进制转出的结果为空
	std::string InvalidHex("XYZ0123456789ABCDEF");
	std::cout << "Result Bin:" << Hex2Bin(InvalidHex) << std::endl;
	
	return 0;
}


Makefile:

NumSysConvert:NumSysConvert.h main.cpp
	g++ -g -o NumSysConvert -I$SSL_ROOT/include -L$SSL_ROOT/lib -lcrypto main.cpp


 

编辑记录:

V1.0 2012-4-24 12:52:04 初稿

// // Created by ZhanPeng on 2026/1/1. // #ifndef AUTOMATE_AES_UTILS_H #define AUTOMATE_AES_UTILS_H #include <openssl/aes.h> #include <openssl/evp.h> #include <openssl/err.h> #include <openssl/rand.h> #include <vector> #include <stdexcept> #include <memory> #include <iostream> #include <iomanip> #include <sstream> class AESUtils { public: // 构造函数,接受密钥和可选的初始化向量(IV) AESUtils(const std::vector<char>& key, const std::vector<char>& iv = std::vector<char>()) : key_(key), iv_(iv) { // 检查密钥长度是否符合 AES 标准 if (key_.size() != 16 && key_.size() != 24 && key_.size() != 32) { throw std::invalid_argument("密钥长度必须是 16(AES-128)、24(AES-192) 或 32(AES-256) 字节"); } // 如果未提供 IV,创建随机 IV if (iv_.empty()) { GenerateRandomIV(); } // 检查 IV 长度是否正确 else if (iv_.size() != BLOCK_SIZE) { throw std::invalid_argument("IV 长度必须是 " + std::to_string(BLOCK_SIZE) + " 字节"); } } // 密函数 std::vector<char> Encrypt(const std::vector<char>& plaintext) { // 创建密上下文 std::unique_ptr<EVP_CIPHER_CTX, decltype(&EVP_CIPHER_CTX_free)> ctx( EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free); if (!ctx) { throw std::runtime_error("无法创建密上下文: " + GetOpenSSLError()); } // 根据密钥长度选择密算法 const EVP_CIPHER* cipher = GetCipher(); if (!cipher) { throw std::runtime_error("不支持的密钥长度"); } // 初始化密操作 if (1 != EVP_EncryptInit_ex(ctx.get(), cipher, nullptr, reinterpret_cast<const unsigned char*>(key_.data()), reinterpret_cast<const unsigned char*>(iv_.data()))) { throw std::runtime_error("密初始化失败: " + GetOpenSSLError()); } // 计算输出缓冲区大小(明文长度 + 最大填充块大小) int out_len = plaintext.size() + BLOCK_SIZE; std::vector<char> ciphertext(out_len + BLOCK_SIZE); // 额外空间存储 IV // 添 IV 到密文开头 std::copy(iv_.begin(), iv_.end(), ciphertext.begin()); // 执行密 int actual_out_len = 0; if (1 != EVP_EncryptUpdate(ctx.get(), reinterpret_cast<unsigned char*>(ciphertext.data()) + BLOCK_SIZE, &out_len, reinterpret_cast<const unsigned char*>(plaintext.data()), plaintext.size())) { throw std::runtime_error("密失败: " + GetOpenSSLError()); } actual_out_len = out_len; // 完成密,处理可能的填充 int final_len = 0; if (1 != EVP_EncryptFinal_ex(ctx.get(), reinterpret_cast<unsigned char*>(ciphertext.data()) + BLOCK_SIZE + out_len, &final_len)) { throw std::runtime_error("密完成失败: " + GetOpenSSLError()); } actual_out_len += final_len; // 调整密文大小为实际大小(IV + 密数据) ciphertext.resize(BLOCK_SIZE + actual_out_len); return ciphertext; } // 解密函数 std::vector<char> Decrypt(const std::vector<char>& ciphertext) { // 检查最小密文长度(IV + 至少1个数据块) if (ciphertext.size() < BLOCK_SIZE + BLOCK_SIZE) { throw std::invalid_argument("密文太短"); } // 提取 IV(密文的前16字节) std::vector<char> iv(ciphertext.begin(), ciphertext.begin() + BLOCK_SIZE); // 创建解密上下文 std::unique_ptr<EVP_CIPHER_CTX, decltype(&EVP_CIPHER_CTX_free)> ctx( EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free); if (!ctx) { throw std::runtime_error("无法创建解密上下文: " + GetOpenSSLError()); } // 根据密钥长度选择解密算法 const EVP_CIPHER* cipher = GetCipher(); if (!cipher) { throw std::runtime_error("不支持的密钥长度"); } // 初始化解密操作 if (1 != EVP_DecryptInit_ex(ctx.get(), cipher, nullptr, reinterpret_cast<const unsigned char*>(key_.data()), reinterpret_cast<const unsigned char*>(iv.data()))) { throw std::runtime_error("解密初始化失败: " + GetOpenSSLError()); } // 准备输出缓冲区 int out_len = ciphertext.size() - BLOCK_SIZE; // 减去IV的长度 std::vector<char> plaintext(out_len + BLOCK_SIZE); // 额外空间 // 执行解密(跳过前16字节的IV) int actual_out_len = 0; if (1 != EVP_DecryptUpdate(ctx.get(), reinterpret_cast<unsigned char*>(plaintext.data()), &out_len, reinterpret_cast<const unsigned char*>(ciphertext.data()) + BLOCK_SIZE, ciphertext.size() - BLOCK_SIZE)) { throw std::runtime_error("解密失败: " + GetOpenSSLError()); } actual_out_len = out_len; // 完成解密,处理填充 int final_len = 0; if (1 != EVP_DecryptFinal_ex(ctx.get(), reinterpret_cast<unsigned char*>(plaintext.data()) + out_len, &final_len)) { throw std::runtime_error("解密完成失败: " + GetOpenSSLError()); } actual_out_len += final_len; // 调整明文大小为实际大小 plaintext.resize(actual_out_len); return plaintext; } // 获取十六进制表示的字符串(用于调试) static std::string ToHexString(const std::vector<char>& data) { std::stringstream ss; ss << std::hex << std::setfill('0'); for (char c : data) { ss << std::setw(2) << (static_cast<int>(c) & 0xFF) << " "; } return ss.str(); } private: // 根据密钥长度选择密码算法 const EVP_CIPHER* GetCipher() const { switch (key_.size()) { case 16: return EVP_aes_128_cbc(); // AES-128 case 24: return EVP_aes_192_cbc(); // AES-192 case 32: return EVP_aes_256_cbc(); // AES-256 default: return nullptr; } } // 生成随机初始化向量(IV) void GenerateRandomIV() { iv_.resize(BLOCK_SIZE); if (!RAND_bytes(reinterpret_cast<unsigned char*>(iv_.data()), BLOCK_SIZE)) { throw std::runtime_error("无法生成随机IV: " + GetOpenSSLError()); } } // 获取OpenSSL错误信息 static std::string GetOpenSSLError() { char err_buf[256]; ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf)); return std::string(err_buf); } static const int BLOCK_SIZE = 16; // AES块大小 std::vector<char> key_; // 密密钥 std::vector<char> iv_; // 初始化向量 }; // 示例用法 /* int main() { try { // 1. 准备密钥和明文数据 std::vector<char> key = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; // AES-128 std::string message = "使用OpenSSL进行AES解密的C++封装实现"; std::vector<char> plaintext(message.begin(), message.end()); std::cout << "原始数据: " << message << std::endl; std::cout << "密钥(HEX): " << AESUtils::ToHexString(key) << std::endl; // 2. 创建AesCrypto实例并密 AESUtils aes(key); std::vector<char> ciphertext = aes.Encrypt(plaintext); std::cout << "密文(HEX): " << AESUtils::ToHexString(ciphertext) << std::endl; // 3. 解密 std::vector<char> decrypted = aes.Decrypt(ciphertext); std::string decrypted_str(decrypted.begin(), decrypted.end()); std::cout << "解密结果: " << decrypted_str << std::endl; // 4. 验证 if (decrypted_str == message) { std::cout << "✓ 解密成功" << std::endl; } else { std::cout << "✗ 解密失败" << std::endl; } return 0; } catch (const std::exception& e) { std::cerr << "错误: " << e.what() << std::endl; return 1; } } */ #endif //AUTOMATE_AES_UTILS_H 解密后导致前部分原文不见得愿因
最新发布
01-02
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值