Crypto++ (CryptoPP) 是一个用于密码学和加密的 C++ 库。它是一个开源项目,提供了大量的密码学算法和功能,包括对称加密、非对称加密、哈希函数、消息认证码 (MAC)、数字签名等。Crypto++ 的目标是提供高性能和可靠的密码学工具,以满足软件开发中对安全性的需求。

高级加密标准(Advanced Encryption Standard,AES)是一种对称密钥加密标准,用于保护电脑上的敏感数据。AES是由美国国家标准与技术研究院(NIST)于2001年确定的,它取代了过时的数据加密标准(Data Encryption Standard,DES)。

以下是AES加密算法的主要特点和概述:

  1. 对称密钥算法: AES是一种对称密钥算法,意味着相同的密钥用于加密和解密数据。这就要求通信双方在通信前共享密钥,并确保其保密性。
  2. 分组密码: AES将明文数据分成固定大小的块(128比特),然后对每个块进行独立的加密。这个固定大小的块称为分组。AES支持多种分组长度,包括128比特、192比特和256比特。
  3. 轮数: AES加密算法的安全性与其轮数相关。轮数表示对数据块的处理循环次数,不同密钥长度的AES使用不同数量的轮数。通常,128比特密钥使用10轮,192比特密钥使用12轮,256比特密钥使用14轮。
  4. 密钥长度: AES支持多种密钥长度,包括128比特、192比特和256比特。密钥长度的选择直接影响加密算法的安全性。
  5. SubBytes、ShiftRows、MixColumns和AddRoundKey: 这些是AES加密算法中的四个主要操作,它们通过多轮迭代来加密数据。SubBytes和ShiftRows引入非线性性,MixColumns和AddRoundKey提供了扩散和混淆。
  6. 强安全性: AES被广泛认为是一种安全、可靠的加密算法。它经过广泛的密码分析和评估,并且在许多应用中得到了广泛的应用,包括加密通信、文件加密和硬件加密。

总体而言,AES是一种高效、安全且广泛应用的加密算法,适用于多种应用场景。其在加密强度和性能之间取得了良好的平衡,因此成为许多信息安全应用的首选算法。

使用AES算法

AES(Advanced Encryption Standard)广泛应用于保护敏感数据的加密和解密过程。以下是AES算法的概述:

1. 对称加密算法:

AES是一种对称加密算法,这意味着加密和解密都使用相同的密钥。密钥是保护数据安全的关键,因此对称加密算法需要确保密钥的安全分发和管理。

2. 密钥长度:

AES支持不同长度的密钥,包括128位、192位和256位。密钥长度越长,通常意味着更高的安全性,但也可能导致加密和解密的计算成本增加。

3. 块加密算法:

AES是块加密算法,它按照固定大小的数据块(128位)进行加密。加密和解密的过程都是对这些数据块的操作。

4. 加解密过程:

加密:

  • 数据分块:将明文分成固定大小的数据块(128位)。
  • 初始轮密钥加:将明文和初始密钥进行一次简单的混淆操作。
  • 轮加密:通过多轮的替代和置换操作(SubBytes、ShiftRows、MixColumns、AddRoundKey),对数据块进行混淆。
  • 最终轮:在最后一轮中,省略MixColumns操作。
  • 得到密文。

解密:

  • 初始轮密钥解:将密文和初始密钥进行一次简单的混淆操作。
  • 轮解密:通过多轮的逆操作(InvSubBytes、InvShiftRows、InvMixColumns、AddRoundKey),对数据块进行逆操作。
  • 最终轮:在最后一轮中,省略InvMixColumns操作。
  • 得到明文。

5. 使用场景:

AES广泛用于保护敏感数据,如文件、数据库、网络通信等。它是许多安全协议和标准的基础,包括TLS(安全套接层)、IPsec(Internet协议安全)等。

6. 安全性:

AES被广泛接受并认为是安全可靠的加密算法。密钥长度的选择对安全性至关重要,一般建议使用128位、192位或256位的密钥以满足特定安全需求。

总体而言,AES作为一种高效且安全的对称加密算法,在现代加密通信中扮演着重要的角色。AES的使用需要引入头文件#include <aes.h>其他部分与《C++ 通过CryptoPP计算Hash值》文章中的头文件引入保持一致。

如下AESEncrypt是一个使用AES算法进行加密的函数。下面是对函数的主要步骤的注释:

  1. AES加密对象初始化:

    • 创建AESEncryption对象用于AES加密。
    • 定义AES加密需要的数据块:inBlock(输入数据块)、outBlock(输出数据块)、xorBlock(异或数据块)。
  2. 计算加密数据块大小:
    • 计算需要的加密数据块数量,考虑到原始数据大小可能不是AES块大小的整数倍。
  3. 分配加密后的数据缓冲区:
    • 根据计算得到的加密数据块大小分配内存。
  4. 设置AES加密密钥:
    • 调用SetKey函数设置AES加密密钥。
  5. AES加密过程:
    • 循环处理原始数据块,每次处理一个AES块大小的数据。
    • 将原始数据块拷贝到输入数据块。
    • 使用AES算法进行加密。
    • 将加密后的数据块拷贝到输出缓冲区。
  6. 返回加密结果:
    • 返回加密后的数据缓冲区和大小。

请注意,在实际使用中,要确保释放了分配的内存,以防止内存泄漏。

BOOL AESEncrypt(BYTE *pOriginalData, DWORD dwOriginalDataSize, BYTE *pAESKey, DWORD dwAESKeySize, BYTE **ppEncryptData, DWORD *pdwEncryptData)
{
// 定义AES加密需要的数据块
AESEncryption aesEncryptor;
// 加密原文数据块
unsigned char inBlock[AES::BLOCKSIZE];
// 加密后密文数据块
unsigned char outBlock[AES::BLOCKSIZE];
// 必须设定全为0
unsigned char xorBlock[AES::BLOCKSIZE]; DWORD dwOffset = 0;
BYTE *pEncryptData = NULL;
DWORD dwEncryptDataSize = 0; // 计算需要的加密数据块大小, 并按 128位 即 16字节 对齐, 不够则 填充0 对齐
// 商
DWORD dwQuotient = dwOriginalDataSize / AES::BLOCKSIZE;
// 余数
DWORD dwRemaind = dwOriginalDataSize % AES::BLOCKSIZE;
if (0 != dwRemaind)
{
dwQuotient++;
} // 申请动态内存
dwEncryptDataSize = dwQuotient * AES::BLOCKSIZE; // 分配加密后的数据缓冲区
pEncryptData = new BYTE[dwEncryptDataSize];
if (NULL == pEncryptData)
{
return FALSE;
} // 设置AES加密密钥
aesEncryptor.SetKey(pAESKey, dwAESKeySize); do
{
// 初始化数据块
RtlZeroMemory(inBlock, AES::BLOCKSIZE);
RtlZeroMemory(xorBlock, AES::BLOCKSIZE);
RtlZeroMemory(outBlock, AES::BLOCKSIZE); // 获取加密块
if (dwOffset <= (dwOriginalDataSize - AES::BLOCKSIZE))
{
RtlCopyMemory(inBlock, (PVOID)(pOriginalData + dwOffset), AES::BLOCKSIZE);
}
else
{
RtlCopyMemory(inBlock, (PVOID)(pOriginalData + dwOffset), (dwOriginalDataSize - dwOffset));
} // 使用AES算法进行加密
aesEncryptor.ProcessAndXorBlock(inBlock, xorBlock, outBlock); // 将加密后的数据块拷贝到输出缓冲区
RtlCopyMemory((PVOID)(pEncryptData + dwOffset), outBlock, AES::BLOCKSIZE); // 更新数据
dwOffset = dwOffset + AES::BLOCKSIZE;
dwQuotient--;
} while (0 < dwQuotient); // 返回数据
*ppEncryptData = pEncryptData;
*pdwEncryptData = dwEncryptDataSize; return TRUE;
}

如下AESDecrypt是一个使用AES算法进行解密的函数。以下是对函数的主要步骤的注释:

  1. AES解密对象初始化:

    • 创建AESDecryption对象用于AES解密。
    • 定义AES解密需要的数据块:inBlock(输入数据块)、outBlock(输出数据块)、xorBlock(异或数据块)。
  2. 计算解密数据块大小:
    • 计算需要的解密数据块数量,考虑到加密数据大小可能不是AES块大小的整数倍。
  3. 分配解密后的数据缓冲区:
    • 根据计算得到的解密数据块大小分配内存。
  4. 设置AES解密密钥:
    • 调用SetKey函数设置AES解密密钥。
  5. AES解密过程:
    • 循环处理加密数据块,每次处理一个AES块大小的数据。
    • 将加密数据块拷贝到输入数据块。
    • 使用AES算法进行解密。
    • 将解密后的数据块拷贝到输出缓冲区。
  6. 返回解密结果:
    • 返回解密后的数据缓冲区和大小。

请注意,在实际使用中,要确保释放了分配的内存,以防止内存泄漏。

BOOL AESDecrypt(BYTE *pEncryptData, DWORD dwEncryptData, BYTE *pAESKey, DWORD dwAESKeySize, BYTE **ppDecryptData, DWORD *pdwDecryptData)
{
// 定义AES解密需要的数据块
AESDecryption aesDecryptor;
// 解密密文数据块
unsigned char inBlock[AES::BLOCKSIZE];
// 解密后后明文数据块
unsigned char outBlock[AES::BLOCKSIZE];
// 必须设定全为0
unsigned char xorBlock[AES::BLOCKSIZE];
DWORD dwOffset = 0;
BYTE *pDecryptData = NULL;
DWORD dwDecryptDataSize = 0; // 计算密文长度, 并按 128位 即 16字节 对齐, 不够则填充0对齐
// 商
DWORD dwQuotient = dwEncryptData / AES::BLOCKSIZE;
// 余数
DWORD dwRemaind = dwEncryptData % AES::BLOCKSIZE;
if (0 != dwRemaind)
{
dwQuotient++;
} // 分配解密后的数据缓冲区
dwDecryptDataSize = dwQuotient * AES::BLOCKSIZE;
pDecryptData = new BYTE[dwDecryptDataSize];
if (NULL == pDecryptData)
{
return FALSE;
} // 设置AES解密密钥
aesDecryptor.SetKey(pAESKey, dwAESKeySize); do
{
// 初始化数据块
RtlZeroMemory(inBlock, AES::BLOCKSIZE);
RtlZeroMemory(xorBlock, AES::BLOCKSIZE);
RtlZeroMemory(outBlock, AES::BLOCKSIZE); // 将加密数据块拷贝到输入数据块
if (dwOffset <= (dwDecryptDataSize - AES::BLOCKSIZE))
{
RtlCopyMemory(inBlock, (PVOID)(pEncryptData + dwOffset), AES::BLOCKSIZE);
}
else
{
RtlCopyMemory(inBlock, (PVOID)(pEncryptData + dwOffset), (dwEncryptData - dwOffset));
} // 使用AES算法进行解密
aesDecryptor.ProcessAndXorBlock(inBlock, xorBlock, outBlock); // 将解密后的数据块拷贝到输出缓冲区
RtlCopyMemory((PVOID)(pDecryptData + dwOffset), outBlock, AES::BLOCKSIZE); // 更新数据
dwOffset = dwOffset + AES::BLOCKSIZE;
dwQuotient--;
} while (0 < dwQuotient); // 返回数据
*ppDecryptData = pDecryptData;
*pdwDecryptData = dwDecryptDataSize; return TRUE;
}

AESEncrypt 函数用于对输入的原始数据进行AES加密,加密使用指定的AES密钥。函数通过参数返回加密后的数据和数据大小。

函数原型:

BOOL AESEncrypt(
BYTE *pOriginalData, // [in] 原始数据的指针
DWORD dwOriginalDataSize, // [in] 原始数据的大小
BYTE *pAESKey, // [in] AES加密密钥的指针
DWORD dwAESKeySize, // [in] AES加密密钥的大小
BYTE **ppEncryptData, // [out] 指向指针的指针,用于存储加密后的数据
DWORD *pdwEncryptData // [out] 指向DWORD的指针,用于存储加密后的数据大小
);
  • pOriginalData: 指向要加密的原始数据的指针。
  • dwOriginalDataSize: 原始数据的大小。
  • pAESKey: 指向用于AES加密的密钥的指针。
  • dwAESKeySize: AES加密密钥的大小。
  • ppEncryptData: 指向指针的指针,用于存储加密后的数据。该指针需要在函数外释放分配的内存。
  • pdwEncryptData: 指向DWORD的指针,用于存储加密后的数据大小。

函数返回一个BOOL值,表示操作是否成功。如果函数返回TRUE,则表示加密成功,否则表示加密失败。

AESDecrypt 函数用于对输入的加密后的数据进行AES解密,解密使用指定的AES密钥。函数通过参数返回解密后的数据和数据大小。

函数原型:

BOOL AESDecrypt(
BYTE *pEncryptData, // [in] 加密后的数据的指针
DWORD dwEncryptDataSize, // [in] 加密后的数据的大小
BYTE *pAESKey, // [in] AES解密密钥的指针
DWORD dwAESKeySize, // [in] AES解密密钥的大小
BYTE **ppDecryptData, // [out] 指向指针的指针,用于存储解密后的数据
DWORD *pdwDecryptData // [out] 指向DWORD的指针,用于存储解密后的数据大小
);
  • pEncryptData: 指向要解密的加密后数据的指针。
  • dwEncryptDataSize: 加密后数据的大小。
  • pAESKey: 指向用于AES解密的密钥的指针。
  • dwAESKeySize: AES解密密钥的大小。
  • ppDecryptData: 指向指针的指针,用于存储解密后的数据。该指针需要在函数外释放分配的内存。
  • pdwDecryptData: 指向DWORD的指针,用于存储解密后的数据大小。

函数返回一个BOOL值,表示操作是否成功。如果函数返回TRUE,则表示解密成功,否则表示解密失败。

调用时通过AESEncrypt加密数据,AESDecrypt则用于解密数据;

void ShowData(BYTE *pData, DWORD dwSize)
{
for (int i = 0; i < dwSize; i++)
{
if ((0 != i) &&
(0 == i % 16))
{
printf("\n");
}
else if ((0 != i) &&
(0 == i % 8))
{
printf(" ");
} printf("%02X ", pData[i]);
}
printf("\n");
} int main(int argc, char* argv[])
{
BYTE *pEncryptData = NULL;
DWORD dwEncryptDataSize = 0;
BYTE *pDecryptData = NULL;
DWORD dwDecryptDataSize = 0;
char szOriginalData[] = "It’s better to be alone than to be with someone you’re not happy to be with."; char szAESKey[] = "ABCDEFGHIJKIMNOP";
BOOL bRet = FALSE; // 加密
bRet = AESEncrypt((BYTE *)szOriginalData, (1 + ::lstrlen(szOriginalData)), (BYTE *)szAESKey, ::lstrlen(szAESKey), &pEncryptData, &dwEncryptDataSize);
if (FALSE == bRet)
{
return 1;
} // 解密
bRet = AESDecrypt(pEncryptData, dwEncryptDataSize, (BYTE *)szAESKey, ::lstrlen(szAESKey), &pDecryptData, &dwDecryptDataSize);
if (FALSE == bRet)
{
return 2;
} // 显示
printf("原文数据:\n");
ShowData((BYTE *)szOriginalData, (1 + ::lstrlen(szOriginalData)));
printf("密文数据:\n");
ShowData(pEncryptData, dwEncryptDataSize);
printf("解密后数据:\n");
ShowData(pDecryptData, dwDecryptDataSize); // 释放内存
delete[]pEncryptData;
pEncryptData = NULL;
delete[]pDecryptData;
pDecryptData = NULL; system("pause");
return 0;
}

运行后对szOriginalData中的数据进行加密,密钥是szAESKey中的长度,如下图所示;

C++ CryptoPP使用AES加解密的更多相关文章

  1. DES,AeS加解密,MD5,SHA加密

    1.DES一共就有4个参数参与运作:明文.密文.密钥.向量.其中这4者的关系可以理解为: 密文=明文+密钥+向量: 明文=密文-密钥-向量: 为什么要向量这个参数呢?因为如果有一篇文章,有几个词重复, ...

  2. c# Aes加解密和对象序列化

    aes加解密 public class AesCryptto { private string key = "hjyf57468jhmuist"; private string i ...

  3. Java、C#双语版配套AES加解密示例

      这年头找个正经能用的东西那是真难,网上一搜索一大堆,正经能用的没几个,得,最后还是得靠自己,正巧遇上需要AES加解密的地方了,而且还是Java和C#间的相互加解密操作,这里做个备忘 这里采用的加解 ...

  4. AES加解密算法Qt实现

    [声明] (1) 本文源码 在一位未署名网友源码基础上,利用Qt编程,实现了AES加解密算法,并添加了文件加解密功能.在此表示感谢!该源码仅供学习交流,请勿用于商业目的. (2) 图片及描述 除图1外 ...

  5. aes加解密 Illegal key size

    做aes加密时,发生一个奇怪的错误,在本地环境是好的,发布到测试环境就出问题, java.security.InvalidKeyException: Illegal key size 想到本地环境之前 ...

  6. C# RSA加解密与验签,AES加解密,以及与JAVA平台的密文加解密

    前言: RSA算法是利用公钥与密钥对数据进行加密验证的一种算法.一般是拿私钥对数据进行签名,公钥发给友商,将数据及签名一同发给友商,友商利用公钥对签名进行验证.也可以使用公钥对数据加密,然后用私钥对数 ...

  7. Aes加解密,php

    Aes类库 <?php namespace Aes; class Aes { /** * var string $method 加解密方法,可通过openssl_get_cipher_metho ...

  8. cryptoJS AES 加解密简单使用

    简单记录一下,前端利用 cryptoJS 如何加解密的.主要是关于 AES 加解密. 需求描述:需要对 url 中的参数进行 AES 解密,然后再把该参数进行 MD5 加密通过接口传递. AES AE ...

  9. AES加解密程序的实现

    AES加解密程序的实现正常情况,用户不能访问sys.dbms_crypto,需要DBA授权:grant execute on dbms_crypto to crm;建立加解密的PKG_AES包:CRE ...

  10. 收银台数据库存储AES加解密

    高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法加密和解密用到的密钥是相同的,这种加密方式加密速度非常快,适合经常发送数据的场合.缺点是密钥的传输 ...

随机推荐

  1. 使用 FHE 实现加密大语言模型

    近来,大语言模型 (LLM) 已被证明是提高编程.内容生成.文本分析.网络搜索及远程学习等诸多领域生产力的可靠工具. 大语言模型对用户隐私的影响 尽管 LLM 很有吸引力,但如何保护好 输入给这些模型 ...

  2. CentOS7系统上安装升级Vim8

    基本步骤 1.卸载旧版vim yum remove vim* -y 2. 到Vim官方Github仓库下载目前最新的Vim Release版本 git clone https://github.com ...

  3. KB21N、KB24N作业分配与冲销

    一.KB21N 调用BAPI:BAPI_ACC_ACTIVITY_ALLOC_POST 经测试,分配订单时行项目一次性最多传332条数据 "------------------------- ...

  4. CS01 BOM客制化屏幕增强

    一.BOM行项目新增定制字段 效果如下 二.前台增强实现步骤 1.行项目表新增字段 2.CMOD,增强项目PCSD0002:在行项目中增强(PCSD0003:在抬头增强) 3.双击创建定制化屏幕 4. ...

  5. CO02生产订单新增组件

    "-----------------------------------------@斌将军-------------------------------------------- LOOP ...

  6. POJ 1742 Coins(多重背包的可行性问题)

    Description People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar. ...

  7. mysql 使用 trim去不掉空格 解决

    使用mysql8.0时 发现 有几个空字符串怎么也过滤不掉,使用 is not null.trim()<>''.length()>=1都不行,最后查了一些资料说 trim只能去除半角 ...

  8. freeswitch如何判断挂机方

    概述 freeswitch作为VOIP的软交换平台,需要对呼叫的信息做判断和归类. 常见的呼叫信息中,挂机方向的信息对于话单统计有很大的用处. 但是fs的原始话单和日志中并没有挂机方向的信息. 环境 ...

  9. 线性代数 · 矩阵 · Matlab | 满秩分解代码实现

    背景 - 矩阵的满秩分解: 若 A 为 m×n 矩阵,rank(A) = r,则存在 F m×r.G r×n,使得 A = FG. 其中,F 列满秩,G 行满秩. 求满秩分解的方法: 得到 A 的行最 ...

  10. Feign 实现微服务调用及进行服务熔断与降级

    本文为博主原创,未经允许不得转载: 1. Feign 日志级别配置 2. Feign client 封装调用 3. Feign 定义熔断降级方法 4. 通过 FallbackFactory 工厂 实现 ...