OpenSSL中AES加密的用法

这篇具有很好参考价值的文章主要介绍了OpenSSL中AES加密的用法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 AES算法简介

原文链接:
https://blog.csdn.net/mao834099514/article/details/54945776

1.1 AES算法介绍

密码学中的高级加密标准(Advanced Encryption Standard,AES),又称 Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。

如下图所示,AES算法的数据分组长度为128比特、密钥长度为128/192/256比特。
OpenSSL中AES加密的用法

1.2 AES工作模式介绍

1)ECB模式简介
OpenSSL中AES加密的用法

2)CBC模式简介

下图中,IV一般为16字节全0,数据块长度为16字节的整数倍,则在此数据块后附加一个8字节长的数据块,

附加的数据块为:16进制的“80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00”
OpenSSL中AES加密的用法

2 AES算法ECB模式

2.1 使用函数AES_set_encrypt_key设置加密密钥

函数原型:

**int AES_set_encrypt_key(const unsigned char userKey, const int bits,AES_KEY key);

函数作用:

设定加密用的Key;

参数说明:

userKey: 密钥数值;

bits:密钥长度,以bit为单位,如果密钥数字是16个字节,则此参数值应为128;

key: AES_KEY对象指针;

返回值: 0 成功, -1 userkey,key为空, -2: 密钥长度不是128,192,256;

2.2 使用函数AES_set_decrypt_key设置解密密钥。

函数原型:

**int AES_set_decrypt_key(const unsigned char userKey, const int bits, AES_KEY key);

函数作用:

设定解密用的Key;

参数说明:

userKey: 密钥数值;

bits:密钥长度,以bit为单位,如果密钥数字是16个字节,则此参数值应为128;

key: AES_KEY对象指针;

返回值: 0 成功, -1 userkey,key为空, -2: 密钥长度不是128,192,256;

2.3 使用函数AES_ecb_encrypt对数据进行加解密

函数原型:

**void AES_ecb_encrypt(const unsigned char *in, unsigned char out, const AES_KEY key, const int enc);

函数说明:

AES加密/解密单个数据块(16个字节),ECB模式

参数说明:

in: 需要加密/解密的数据;

out: 计算后输出的数据;
key:密钥

enc: AES_ENCRYPT 代表加密, AES_DECRYPT代表解密;

3 AES算法CBC模式

3.1 使用函数AES_set_encrypt_key设置加密密钥。

函数原型:

**int AES_set_encrypt_key(const unsigned char userKey, const int bits,AES_KEY key);

函数作用:

设定加密用的Key;

参数说明:

userKey: 密钥数值;

bits:密钥长度,以bit为单位,如果密钥数字是16个字节,则此参数值应为128;

key: AES_KEY对象指针;

返回值: 0 成功, -1 userkey,key为空, -2: 密钥长度不是128,192,256;

3.2 使用函数AES_set_decrypt_key设置解密密钥。

函数原型:

**int AES_set_decrypt_key(const unsigned char userKey, const int bits, AES_KEY key);

函数作用:

设定解密用的Key;

参数说明:

userKey: 密钥数值;

bits:密钥长度,以bit为单位,如果密钥数字是16个字节,则此参数值应为128;

key: AES_KEY对象指针;

返回值: 0 成功, -1 userkey,key为空, -2: 密钥长度不是128,192,256;

3.3 使用函数AES_cbc_encrypt对数据进行加解密

函数原型:

**void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t length, const AES_KEY key, unsigned char ivec, const int enc);

函数作用:

AES加密/解密单个数据块(16个字节),CBC模式

参数说明:

in: 需要加密/解密的数据;

out: 计算后输出的数据;

length: 数据长度(这里不包含初始向量数据长度)
key:密钥

ivec: 初始向量(一般为16字节全0)
enc: AES_ENCRYPT 代表加密, AES_DECRYPT代表解密;

4 AES算法ECB、CBC两种模式下的加解密实现代码:

4.1 加密实现

void CPage3::OnButtonEncrypt()
{
 // TODO: Add your control notification handler code here
 unsigned char key_hex[256] = {0};
 unsigned char data_hex[256] = {0};
 unsigned char initval_hex[256] = {0};
 unsigned char temp[256] = {0};
 int i = 0;
 int keylen = 0;
 int datalen = 0;
 int InitialLen = 0;
 AES_KEY key;
 
    UpdateData(TRUE);
 
 m_key.Remove(' ');
 m_data.Remove(' ');
 m_initval.Remove(' ');
 
 keylen = m_key.GetLength()/2;
    datalen = m_data.GetLength()/2;
 InitialLen = m_initval.GetLength()/2;
 
 if (datalen%16!=0)
 {
  AfxMessageBox("输入数据长度不是16的整数倍,请重新输入!");
  return;
 }
 
 StrToHex(m_key,key_hex,keylen);
 StrToHex(m_data,data_hex,datalen);
 StrToHex(m_initval,initval_hex,InitialLen);
 
 if (keylen == 16)
 {
  //设置加密密钥
  AES_set_encrypt_key(key_hex,128,&key);
 }
 else if (keylen == 24)
 {
        //设置加密密钥
  AES_set_encrypt_key(key_hex,192,&key);
 }
 else if (keylen == 32)
 {
  //设置加密密钥
  AES_set_encrypt_key(key_hex,256,&key);
 }
 else
 {
        AfxMessageBox("输入密钥长度不是16/24/32字节,请重新输入!");
  return;
 }
 
 //ECB模式
 if (((CButton*)GetDlgItem(IDC_RADIO1))->GetCheck())
 {
  for(i = 0;i < datalen/16;i++)
  {
   AES_ecb_encrypt(data_hex+i*16, temp+i*16,&key,AES_ENCRYPT);
  }
 }
 //CBC模式
 else if (((CButton*)GetDlgItem(IDC_RADIO2))->GetCheck())
 {
  memcpy(data_hex+datalen,"\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",16);
 
  datalen = datalen+16;
  
  for(i = 0;i < datalen/16;i++)
  {
   AES_cbc_encrypt(data_hex+i*16, temp+i*16,16,&key,initval_hex, AES_ENCRYPT);
  }
  
 }
 
 HexToStr(temp,datalen,m_result);
 
    UpdateData(FALSE);
}

4.2 解密实现

void CPage3::OnButtonDecrypt()
{
 // TODO: Add your control notification handler code here
 unsigned char key_hex[256] = {0};
 unsigned char data_hex[256] = {0};
 unsigned char initval_hex[256] = {0};
 unsigned char temp[256] = {0};
 int i = 0;
 int keylen = 0;
 int datalen = 0;
 int InitialLen = 0;
 AES_KEY key;
 
    UpdateData(TRUE);
 
 m_key.Remove(' ');
 m_data.Remove(' ');
 m_initval.Remove(' ');
 
 keylen = m_key.GetLength()/2;
    datalen = m_data.GetLength()/2;
 InitialLen = m_initval.GetLength()/2;
 
 if (datalen%16!=0)
 {
  AfxMessageBox("输入数据长度不是16的整数倍,请重新输入!");
  return;
 }
 
 StrToHex(m_key,key_hex,keylen);
 StrToHex(m_data,data_hex,datalen);
 StrToHex(m_initval,initval_hex,InitialLen);
 
 if (keylen == 16)
 {
  //设置解密密钥
  AES_set_decrypt_key(key_hex,128,&key);
 }
 else if (keylen == 24)
 {
        //设置解密密钥
  AES_set_decrypt_key(key_hex,192,&key);
 }
 else if (keylen == 32)
 {
  //设置解密密钥
  AES_set_decrypt_key(key_hex,256,&key);
 }
 else
 {
        AfxMessageBox("输入密钥长度不是16/24/32字节,请重新输入!");
  return;
 }
 
 //ECB模式
 if (((CButton*)GetDlgItem(IDC_RADIO1))->GetCheck())
 {
  for(i = 0;i < datalen/16;i++)
  {
   AES_ecb_encrypt(data_hex+i*16, temp+i*16,&key,AES_DECRYPT);
  }
 }
 //CBC模式
 else if (((CButton*)GetDlgItem(IDC_RADIO2))->GetCheck())
 {
  for(i = 0;i < datalen/16;i++)
  {
   AES_cbc_encrypt(data_hex+i*16, temp+i*16,16,&key,initval_hex, AES_DECRYPT);
  }
 }
 
 HexToStr(temp,datalen,m_result);
 
    UpdateData(FALSE);
}

5 示例2

#include <openssl/aes.h>
void Widget::aesInit()
{
    const char *key_string = "123456";
        AES_KEY  aes;
        int i = 0;
        unsigned char out1[16];
        unsigned char out2[16];
        memset(out1,0,16);
        memset(out2,0,16);
        if (AES_set_encrypt_key((unsigned char*)key_string, 128, &aes) < 0) {
           qDebug()<<"Unable to set encryption key in AES\n";
           exit(-1);
        }
        char temp[16] = "ABCDEDDFDSGFRSF";
        AES_encrypt((unsigned char*)temp,out1,&aes);
        for(i= 0;i < 16;i++){
            qDebug("%X",out1[i]);
        }
        if (AES_set_decrypt_key((unsigned char*)key_string, 128, &aes) < 0) {
            qDebug()<<"Unable to set encryption key in AES\n";
            exit(-1);
        }
        AES_decrypt(out1,out2,&aes);
        qDebug()<<"temp=\n"<<temp<<"out2=\n"<<out2;
		
}

注意事项:
1. 调用加密函数之前,必须先设置加密key:AES_set_encrypt_key
2. 调用解密函数之前,必须先设置解密key:AES_set_decrypt_key
3. 对于AES_cbc_模式加密解密,每次调用前必须先初始化ivec向量

5.1 使用AES加密/解密

" crypto/aes/ aes_ecb.c"
void AES_ecb_encrypt ( const unsigned char * in , unsigned char * out ,
const AES_KEY * key , const int enc ) {
assert ( in && out && key );
assert (( AES_ENCRYPT == enc )||( AES_DECRYPT == enc ));
if ( AES_ENCRYPT == enc )
AES_encrypt ( in , out , key );
else
AES_decrypt ( in , out , key );
}
从这里可以看出,ecb方式的加密,是由AES_encrypt接口实现的。

AES_encrypt 就是ecb加密的方式
AES_encrypt/AES_decrypt一次只处理16个字节。如果输入数据较长,你需要使用循环语句,每16个字节处理一次,直到所有数据处理完毕。如果数据不足16字节,可以用0填充至16字节。

5.2 使用AES CBC加密/解密

这个函数比AES_encrypt多了一个ivec参数,ivec的内容可以任意指定,但是加密和解密操作必须使用同样的数据。在AES_cbc_encrypt底层,实际上是每16个字节做一次处理,先和ivec做异或运算,然后调用AES_encrypt函数进行加密。
AES_cbc_encrypt在加密的过程中会修改ivec的内容,因此ivec参数不能是一个常量,而且不能在传递给加密函数后再立马传递给解密函数,必须重新赋值之后再传递给解密函数。

关于输出数据的长度
输出数据缓冲区的长度必须是16字节的倍数,加密完成后,比输入长度多出来的输出数据是不可以丢弃的。因此,存档的时候,需要记录原始数据的长度。

6 OpenSSL之AES加密算法-CFB128模式

原文链接:
https://blog.csdn.net/zyhse/article/details/112291862?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_utm_term~default-0.no_search_link&spm=1001.2101.3001.4242.1

加密反馈模式 Cipher Feedback Mode(CFB)。面向字符的应用程序的加密要使用流加密法,可以使用加密反馈模式。在此模式下, 数据用更小的单元加密,如可以是8 位,这个长度小于定义的块长(通常是64 位)。

6.1 函数说明

AES CFB128加密/解密:

void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
                        size_t length, const AES_KEY *key,
                        unsigned char *ivec, int *num, const int enc);

参数名称 含义
in 输入数据,长度任意
out 输出数据,长度与输入数据相等
length 输入数据的长度,字节数
key 使用AES_set_encrypt_key生成的Key
ivec 可读写的一块内存。长度必须是16字节。
num 应总是为0,否则会触发断言
enc AES_ENCRYPT 代表加密, AES_DECRYPT代表解密

AES_cfb128_encrypt在加密的过程中会修改ivec的内容,因此ivec参数不能是一个常量,而且不能在传递给加密函数后再立马传递给解密函数,必须重新赋值之后再传递给解密函数。

6.2 编程实现

(1)特别注意
CFB模式加密和解密均使用加密key,这一点比较反常,务必记住。
CFB模式不需要对输入数据进行填充。
AES_cfb128_encrypt函数length参数,为输入数据长度,字节数。这一点与CFB1模式中有所不同。
(2)实现CFB128模式加解密
下面,函数已经封装完毕,如下:

/**
 * @brief AES::cfb128_encrypt
 * CFB128模式加解密,支持对任意长度明文进行加解密。
 * @param in 输入数据
 * @param out 输出结果
 * @param key 密钥,长度必须是16/24/32字节,否则加密失败
 * @param ivec 初始向量,长度必须是16字节
 * @param enc true-加密,false-解密
 * @return 执行结果
 */
bool AES::cfb128_encrypt(const QByteArray &in, QByteArray &out, const QByteArray &key, const QByteArray &ivec, bool enc)
{
    // 检查密钥合法性(只能是16、24、32字节)
    Q_ASSERT(key.size() == 16 || key.size() == 24 || key.size() == 32);
    Q_ASSERT(ivec.size() == 16); // 初始向量为16字节

    // 特别注意:CFB模式加密和解密均使用加密key。
    // 生成加密key
    AES_KEY aes_key;
    if (AES_set_encrypt_key((const unsigned char*)key.data(), key.size() * 8, &aes_key) != 0)
    {
        return false;
    }

    // 执行CFB128模式加密或解密
    int num = 0;
    QByteArray ivecTemp = ivec; // ivec会被修改,故需要临时变量来暂存
    int encVal = enc ? AES_ENCRYPT : AES_DECRYPT;
    out.resize(in.size()); // 调整输出buf大小
    AES_cfb128_encrypt((const unsigned char*)in.data(),
                    (unsigned char*)out.data(),
                    in.size(),
                    &aes_key,
                    (unsigned char*)ivecTemp.data(),
                    &num,
                    encVal);
    return true;
}

加密过程:
生成加密key
执行加密

解密过程:
生成加密key
执行解密

经测试,本函数支持对任意长度输入数据进行加解密。

6.3 测试代码

void createTestData(QByteArray& data, int size)
{
    data.resize(size);
    for (int i = 0; i < size; i++)
    {
        data[i] = i % 128;
    }
}

void testAES(const QByteArray& data)
{
    QByteArray plainText = data;
    QByteArray encryptText;
    QByteArray decryptText;

    QByteArray key = QByteArray::fromHex("8cc72b05705d5c46f412af8cbed55aad");
    QByteArray ivec = QByteArray::fromHex("667b02a85c61c786def4521b060265e8");

    // AES cfb128模式加密验证
    AES aes;
    aes.cfb128_encrypt(plainText, encryptText, key, ivec, true);     // 加密
    aes.cfb128_encrypt(encryptText, decryptText, key, ivec, false);  // 解密
    qDebug() << "AES cfb128 encrypt verify" << ((decryptText == plainText) ? "succeeded" : "failed");
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 产生1MB+3B的测试数据,为了使该测试数据长度,不为8或16的整数倍
    QByteArray data;
    createTestData(data, 1*1024*1024+3);

    // 测试AES
    testAES(data);     // 测试,直接调用OpenSSL中AES算法函数

    return a.exec();
}

OpenSSL中AES加密的用法
OpenSSL中AES加密的用法

实战篇-OpenSSL之调用EVP框架实现AES多种加密模式文章来源地址https://www.toymoban.com/news/detail-479709.html

到了这里,关于OpenSSL中AES加密的用法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • AES 对称加密算法

    高级加密标准(英语:Advanced Encryption Standard,缩写:AES),是一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。 那么为什么原来的DES会被取代呢,,原因就在于其使用56位密钥,比较容易被破解。而AES可以使用128、192、和256位密钥,并且

    2023年04月17日
    浏览(26)
  • AES加密算法

    参考 “【AES加密算法】| AES加密过程详解| 对称加密| Rijndael-128| 密码学| 信息安全” https://www.bilibili.com/video/BV1i341187fK?from=searchseid=14609524973320441322 参考 《密码编码与信息安全——C++实践》 AES属于 分组加密 算法,属于对称加密,故在传递密钥途中有密钥泄露的风险 明文plai

    2024年02月05日
    浏览(27)
  • 信息安全4——AES加密算法

    ①算法简介 AES( Advanced Encryption Standard) 算法即高级加密标准,在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。在微信小程序的数据传输过程中用到的加密算法。AES算法是用来替代原先的DES,目前已经被全世界广泛使用,同时AES已经成为对称密钥加密

    2024年01月22日
    浏览(30)
  • 加密算法 AES和RSA

    通过互联网发送数据,数据可能会被第三者恶意窃听,造成损失。因此需要给重要的数据进行加密,加密后的数据被称为“密文”。接收方通过解除加密或得原本的数据,把密文恢复为原本数据的操作叫做“解密”。像这样就减少了数据被恶意窃听的风险。 那么加密是怎么操

    2024年02月06日
    浏览(43)
  • 安全:AES算法及其加密模式

    AES(高级加密标准)是一种对称密钥加密算法,被广泛用于保护数据的机密性。 AES算法: 结构: AES算法使用替代(SubBytes)、置换(ShiftRows)、混淆(MixColumns)和轮密钥加(AddRoundKey)等四种基本操作来处理数据块。 密钥长度: AES支持128位、192位和256位三种密钥长度,分别

    2024年01月23日
    浏览(38)
  • C# 实现对称加密算法(AES)与非对称加密算法(RSA),包含前端加密对应算法实现

    一种既简单速度又快的加密方式,加密与解密使用的都是同一个密钥,别名又叫做:单密钥加密;对称加密有很多公开算法,并且因为它效率很高,所以适用于加密大量数据的场合;但其密钥的传输过程是不安全的,并且容易被破解,密钥管理起来也相对麻烦。 需要两个密钥

    2024年02月09日
    浏览(48)
  • AES与DES加密解密算法

    AES(Advanced Encryption Standard,高级加密标准)的出现,是因为以前使用的DES算法密钥长度较短,已经不适应当今数据加密安 全性的要求,因此2000年10月2日,美国政府宣布将比利时密码学家Joan Daemen和Vincent Rijmen提出的密码算法RIJNDAEL作为高级加密标准。2001年11月26日,美国政府

    2024年04月28日
    浏览(35)
  • AES算法:加密通信的新选择

    AES(Advanced Encryption Standard)算法是一种对称密钥加密算法,由比利时密码学家Joan Daemen和Vincent Rijmen设计,于2001年被美国国家标准技术研究所(NIST)确定为新的数据加密标准。AES算法取代了DES算法,成为当前最流行的对称加密算法之一。 密钥扩展 :根据初始密钥生成多个轮

    2024年03月18日
    浏览(37)
  • 【密码算法 之二】对称加密算法 AES(Advanced Encryption Standard)浅析

      AES的全称是 Advanced Encryption Standard,意思就是“高级加密标准”。它的出现主要是用于取代其前任DES算法的,因为我们都知道EDS算法的秘钥长度实际为56bit,因此算法的理论安全强度为2的56次方,但是随着计算能力的大幅提高,虽然出现了3DES的加密方法,但由于它的加密

    2024年02月05日
    浏览(38)
  • 适合于物联网通信的数据加密AES算法

            AES加密算法全称是Advanced Encryption Standard(高级加密标准),是最为常见的对称加密算法之一。AES支持三种长度的密钥:128位、192位、256位。         在物联网通信应用中通常传输的是十六进制的数据,需要考虑数据的加密问题。         AES数据加密算法可

    2024年01月22日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包