C++ openssl AES/CBC/PKCS7Padding 256位加密 解密示例 MD5示例

news/2025/2/26 21:37:02

C++ openssl AES/CBC/PKCS7Padding 256位加密 解密示例
在这里插入图片描述

加密

为了确保 AES 加密使用 AES/CBC/PKCS7Padding,我们需要确保在加密过程中正确处理填充。OpenSSL 的 AES_cbc_encrypt 函数并不自动处理填充,因此我们需要手动实现 PKCS7 填充。

以下是更新后的代码,确保在加密时使用 PKCS7 填充:

#include <openssl/aes.h>
#include <openssl/rand.h>
#include <iostream>
#include <iomanip>
#include <vector>
#include <stdexcept>

void printHex(const std::vector<unsigned char>& data) {
    for (unsigned char byte : data) {
        std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)byte;
    }
    std::cout << std::endl;
}

// PKCS7 填充
std::vector<unsigned char> pkcs7_pad(const std::vector<unsigned char>& data, size_t blockSize) {
    size_t paddingSize = blockSize - (data.size() % blockSize);
    std::vector<unsigned char> paddedData(data);
    paddedData.insert(paddedData.end(), paddingSize, static_cast<unsigned char>(paddingSize));
    return paddedData;
}

std::vector<unsigned char> aes_encrypt(const std::vector<unsigned char>& key, 
                                        const std::vector<unsigned char>& iv, 
                                        const std::vector<unsigned char>& plaintext) {
    AES_KEY encryptKey;
    std::vector<unsigned char> paddedPlaintext = pkcs7_pad(plaintext, AES_BLOCK_SIZE);
    std::vector<unsigned char> ciphertext(paddedPlaintext.size());

    // 设置加密密钥
    if (AES_set_encrypt_key(key.data(), 256, &encryptKey) < 0) {
        throw std::runtime_error("Failed to set encryption key");
    }

    // 加密
    AES_cbc_encrypt(paddedPlaintext.data(), ciphertext.data(), paddedPlaintext.size(), &encryptKey, const_cast<unsigned char*>(iv.data()), AES_ENCRYPT);

    return ciphertext;
}

int main() {
    // 密钥
    std::vector<unsigned char> key = {
        0xDF, 0xAB, 0x3A, 0xC1, 0xA8, 0xD6, 0xA4, 0xE4,
        0x30, 0x63, 0x64, 0xDC, 0x06, 0x93, 0xE2, 0x26,
        0x20, 0x80, 0x72, 0xF7, 0x68, 0x89, 0x5E, 0xD5,
        0xFB, 0x68, 0x49, 0x93, 0xE0, 0x9A, 0x42, 0xA6
    };

    // 明文
    std::vector<unsigned char> plaintext = {
        0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F,
        0x72, 0x6C, 0x64, 0x21, 0x20, 0x54, 0x68, 0x69,
        0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74,
        0x65, 0x73, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73,
        0x61, 0x67, 0x65
    };

    // 初始向量
    std::vector<unsigned char> iv = {
        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
        0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
    };

    try {
        std::vector<unsigned char> ciphertext = aes_encrypt(key, iv, plaintext);
        std::cout << "Encrypted ciphertext: ";
        printHex(ciphertext);
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }

    return 0;
}

说明:

  1. PKCS7 填充pkcs7_pad 函数实现了 PKCS7 填充。它计算需要添加的填充字节数,并在明文末尾添加相应数量的字节。
  2. 加密过程:在加密之前,首先对明文进行填充,然后使用 AES_cbc_encrypt 进行加密。
  3. 输出:加密后的密文以十六进制格式输出。

确保在项目中链接 OpenSSL 库,并根据您的项目设置进行相应的调整。这样可以确保加密后的密文符合 AES/CBC/PKCS7Padding 的要求。

解密

确保使用 AES/CBC/PKCS7Padding。我们将添加解密函数,并在 main 函数中演示如何使用它。

#include <openssl/aes.h>
#include <openssl/rand.h>
#include <iostream>
#include <iomanip>
#include <vector>
#include <stdexcept>

void printHex(const std::vector<unsigned char>& data) {
    for (unsigned char byte : data) {
        std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)byte;
    }
    std::cout << std::endl;
}

// PKCS7 填充
std::vector<unsigned char> pkcs7_pad(const std::vector<unsigned char>& data, size_t blockSize) {
    size_t paddingSize = blockSize - (data.size() % blockSize);
    std::vector<unsigned char> paddedData(data);
    paddedData.insert(paddedData.end(), paddingSize, static_cast<unsigned char>(paddingSize));
    return paddedData;
}

// PKCS7 去填充
std::vector<unsigned char> pkcs7_unpad(const std::vector<unsigned char>& data) {
    size_t paddingSize = data.back();
    return std::vector<unsigned char>(data.begin(), data.end() - paddingSize);
}

std::vector<unsigned char> aes_encrypt(const std::vector<unsigned char>& key, 
                                        const std::vector<unsigned char>& iv, 
                                        const std::vector<unsigned char>& plaintext) {
    AES_KEY encryptKey;
    std::vector<unsigned char> paddedPlaintext = pkcs7_pad(plaintext, AES_BLOCK_SIZE);
    std::vector<unsigned char> ciphertext(paddedPlaintext.size());

    // 设置加密密钥
    if (AES_set_encrypt_key(key.data(), 256, &encryptKey) < 0) {
        throw std::runtime_error("Failed to set encryption key");
    }

    // 加密
    AES_cbc_encrypt(paddedPlaintext.data(), ciphertext.data(), paddedPlaintext.size(), &encryptKey, const_cast<unsigned char*>(iv.data()), AES_ENCRYPT);

    return ciphertext;
}

std::vector<unsigned char> aes_decrypt(const std::vector<unsigned char>& key, 
                                        const std::vector<unsigned char>& iv, 
                                        const std::vector<unsigned char>& ciphertext) {
    AES_KEY decryptKey;
    std::vector<unsigned char> decryptedData(ciphertext.size());

    // 设置解密密钥
    if (AES_set_decrypt_key(key.data(), 256, &decryptKey) < 0) {
        throw std::runtime_error("Failed to set decryption key");
    }

    // 解密
    AES_cbc_encrypt(ciphertext.data(), decryptedData.data(), ciphertext.size(), &decryptKey, const_cast<unsigned char*>(iv.data()), AES_DECRYPT);

    // 去填充
    return pkcs7_unpad(decryptedData);
}

int main() {
    // 密钥
    std::vector<unsigned char> key = {
        0xDF, 0xAB, 0x3A, 0xC1, 0xA8, 0xD6, 0xA4, 0xE4,
        0x30, 0x63, 0x64, 0xDC, 0x06, 0x93, 0xE2, 0x26,
        0x20, 0x80, 0x72, 0xF7, 0x68, 0x89, 0x5E, 0xD5,
        0xFB, 0x68, 0x49, 0x93, 0xE0, 0x9A, 0x42, 0xA6
    };

    // 明文
    std::vector<unsigned char> plaintext = {
        0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F,
        0x72, 0x6C, 0x64, 0x21, 0x20, 0x54, 0x68, 0x69,
        0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74,
        0x65, 0x73, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73,
        0x61, 0x67, 0x65
    };

    // 初始向量
    std::vector<unsigned char> iv = {
        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
        0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
    };

    try {
        // 加密
        std::vector<unsigned char> ciphertext = aes_encrypt(key, iv, plaintext);
        std::cout << "Encrypted ciphertext: ";
        printHex(ciphertext);

        // 解密
        std::vector<unsigned char> decryptedText = aes_decrypt(key, iv, ciphertext);
        std::cout << "Decrypted plaintext: ";
        printHex(decryptedText);
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }

    return 0;
}

说明:

  1. PKCS7 填充和去填充

    • pkcs7_pad 函数用于在加密前对明文进行填充。
    • pkcs7_unpad 函数用于在解密后去除填充。
  2. AES 加密和解密

    • aes_encrypt 函数实现 AES 加密,使用 CBC 模式和 PKCS7 填充。
    • aes_decrypt 函数实现 AES 解密,使用 CBC 模式,并在解密后去除填充。
  3. 主函数

    • main 函数中,首先加密明文,然后解密密文,并输出加密后的密文和解密后的明文。

确保在项目中链接 OpenSSL 库,并根据您的项目设置进行相应的调整。这样可以确保加密和解密过程符合 AES/CBC/PKCS7Padding 的要求。

C++ 用openssl计算字符串的md5

要在 C++ 中使用 OpenSSL 计算字符串的 MD5 哈希,可以按照以下步骤进行。首先,确保你已经安装了 OpenSSL 库。然后,你可以使用以下代码示例来计算字符串的 MD5 值:

#include <iostream>
#include <openssl/md5.h>

std::string calculateMD5(const std::string &input) {
    unsigned char digest[MD5_DIGEST_LENGTH];
    MD5((unsigned char*)input.c_str(), input.size(), digest);

    // 将结果转换为十六进制字符串
    char md5String[33];
    for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) {
        sprintf(&md5String[i * 2], "%02x", (unsigned int)digest[i]);
    }
    return std::string(md5String);
}

int main() {
    std::string input = "hello world";
    std::string md5Hash = calculateMD5(input);
    std::cout << "MD5 of \"" << input << "\" is: " << md5Hash << std::endl;
    return 0;
}

代码说明:

  1. 包含头文件:引入 openssl/md5.h 以使用 MD5 函数。
  2. 计算 MD5calculateMD5 函数接受一个字符串输入,计算其 MD5 值,并返回十六进制格式的字符串。
  3. 主函数:在 main 函数中,定义一个输入字符串并调用 calculateMD5 函数,然后输出结果。

编译和运行:

确保在编译时链接 OpenSSL 库,例如:

g++ -o md5_example md5_example.cpp -lssl -lcrypto

然后运行生成的可执行文件:

./md5_example

这将输出字符串 “hello world” 的 MD5 哈希值。


http://www.niftyadmin.cn/n/5869183.html

相关文章

一文掌握Splash的详细使用

文章目录 1. 安装与启动 Splash1.1 使用 Docker 安装1.2 直接安装 2. 基本用法2.1 访问 Splash 界面2.2 使用 Splash 渲染页面2.3 使用 Lua 脚本 3. 高级用法3.1 处理 JavaScript3.2 截图与 PDF3.3 处理 AJAX 请求3.4 设置请求头3.5 处理 Cookies 4. 与 Scrapy 集成4.1 安装 Sc…

日语学习-日语知识点小记-构建基础-JLPT-N4N5阶段(11): 助动词使用 なります&なりました:復習(ふくしゅう)

日语学习-日语知识点小记-构建基础-JLPT-N4&N5阶段(11): 助动词使用 & なります&なりました:復習(ふくしゅう)  1、前言(1)情况说明(2)工程师的信仰2、知识点(1)基本助词复习(2)なります&なりました:復習(ふくしゅう)3、单词(1)日语单词(2)…

git常用命令(时常更新)

Git基础 添加&#xff06;提交 分支管理 远程仓库 版本回退 处理冲突 暂存改动 git stash 其他常用Git命令 日常git流程&#xff1a; 日常使用 git init # 初始化仓库 git remote add origin <远程地址> # 绑定远程仓库 git checkout -b dev # 创建并切换分支 git a…

优选算法大集合(待更新)

1.双指针 1.1.移动零 leetcode链接&#xff1a;283. 移动零 - 力扣&#xff08;LeetCode&#xff09;​​​​​​ 移动零的问题我们可以将它归类为数组划分的问题&#xff0c;我们将数组划分为非零部分和零部分。我们会使用到双指针的算法&#xff0c;在这里&#xff0c;我…

【PyQt】图像处理系统

@[toc]pyqt实现图像处理系统 图像处理系统 1.创建阴影去除ui文件 2.阴影去除代码 1.创建阴影去除ui文件 UI文件效果图: 1.1QT Desiger设置组件 1.两个Pushbutton按钮 2.两个label来显示图像 3.Text Browser来显示输出信息 1.2布局的设置 1.先不使用任何Layout,把所…

从电子管到量子计算:计算机技术的未来趋势

计算机发展的历史 自古以来人类就在不断地发明和改进计算工具,从结绳计数到算盘,计算尺,手摇计算机,直到1946年第一台电子计算机诞生,虽然电子计算机至今虽然只有短短的半个多世纪,但取得了惊人的发展吗,已经经历了五代的变革。计算机的发展和电子技术的发展密切相关,…

日本IT|SQL工程师的工作内容以及所需的技能·资格

SQLエンジニアとは&#xff1f; 1.データベースの設計・開発、管理、運用を担うエンジニア データ抽出と整形 SQLエンジニアにおいて、データの抽出と整形は重要な仕事です。 リレーショナルデータベースではテーブルという形式でデータを管理しており、複数のテーブルから…

Android Realm数据库使用与集成指南

本地存储storage集成创建Realm数据模型插入和更新数据模型数据查询统计数据分页查询处理表数据删除操作总结Realm 是一款专为移动端和嵌入式场景设计的高性能、跨平台的 对象数据库(NoSQL),由 MongoDB 团队维护。它的核心思想是将数据模型直接映射到对象(如 Java/Kotlin、S…