实战篇-OpenSSL之AES加密算法-CFB1模式

本文属于《OpenSSL加密算法库使用系列教程》之一,欢迎查看其它文章。实战篇-OpenSSL之AES加密算法-CFB1模式一、AES简介二、CFB1模式1、命令行操作2、函数说明3、编程实现(1)特别注意(2)实现CFB1模式加解密(3)测试代码一、AES简介密码学中的高级加密标准(AdvancedEncryptionStandard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程

大家好,又见面了,我是你们的朋友全栈君。

本文属于《OpenSSL加密算法库使用系列教程》之一,欢迎查看其它文章。

一、AES简介

密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。

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

AES属于对称加密算法,加解密使用同一个秘钥。

对称加密算法,一般有至少4种模式,即ECB、CBC、CFB、OFB等。

具体的加密原理,就不进行介绍了,本文主要从使用角度,进行说明。

以下命令行和编程实现,均基于OpenSSL开源库。在命令行中,我们可以使用命令实现对文件加解密,以验证我们的编程实现,是否正确。

二、CFB1模式

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

1、命令行操作

使用aes-128-cfb1对hello.txt加密,128位密钥为8cc72b05705d5c46f412af8cbed55aad,初始化向量为667b02a85c61c786def4521b060265e8,密文为hello.en。

openssl enc -e -aes-128-cfb1 -in hello.txt -out hello.en -K 8cc72b05705d5c46f412af8cbed55aad -iv 667b02a85c61c786def4521b060265e8

使用aes-128-cfb1对hello.en解密,密钥为8cc72b05705d5c46f412af8cbed55aad,初始化向量为667b02a85c61c786def4521b060265e8,解密后的文件为hello.de。

openssl enc -d -aes-128-cfb1 -in hello.en -out hello.de -K 8cc72b05705d5c46f412af8cbed55aad -iv 667b02a85c61c786def4521b060265e8

2、函数说明

AES CFB1加密/解密:

void AES_cfb1_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 输入数据的位数,即输入数据长度*8
key 使用AES_set_encrypt_key生成的Key
ivec 可读写的一块内存。长度必须是16字节。
num 应总是为0,否则会触发断言
enc AES_ENCRYPT 代表加密, AES_DECRYPT代表解密

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

3、编程实现

(1)特别注意

  • CFB模式加密和解密均使用加密key,这一点比较反常,务必记住。
  • CFB模式不需要对输入数据进行填充。
  • AES_cfb1_encrypt函数length参数,为输入数据的位数,即输入数据长度*8,而不是字节数。

(2)实现CFB1模式加解密

下面,函数已经封装完毕,如下:

/** * @brief AES::cfb1_encrypt * CFB1模式加解密,支持对任意长度明文进行加解密。 * @param in 输入数据 * @param out 输出结果 * @param key 密钥,长度必须是16/24/32字节,否则加密失败 * @param ivec 初始向量,长度必须是16字节 * @param enc true-加密,false-解密 * @return 执行结果 */
bool AES::cfb1_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;
    }

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

加密过程:

  • 生成加密key
  • 执行加密

解密过程:

  • 生成加密key
  • 执行解密

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

(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 cfb1模式加密验证
    AES aes;
    aes.cfb1_encrypt(plainText, encryptText, key, ivec, true);    // 加密
    aes.cfb1_encrypt(encryptText, decryptText, key, ivec, false); // 解密
    qDebug() << "AES cfb1 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();
}

执行结果:

在这里插入图片描述

本文涉及工程代码地址:https://gitee.com/bailiyang/cdemo/tree/master/Qt/49OpenSSL/OpenSSL


若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!

同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/127345.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • eclipse怎么导入一个Java项目(莫要错过,最详细教程!)

    eclipse怎么导入一个Java项目(莫要错过,最详细教程!)对于eclipse软件,常规的打开文件方法是无法打开一个项目的,那么怎样导入一个java项目呢?方法如下第一步在电脑打开eclipse软件,点击file->Import,如下图所示:第二步选择General->ExistingProjectsintoworkspace,点击next,如下图所示:第三步点击选择要导入的项目路径,选好,点击finish,如下图所示:到此为止,已经导入成功了如果对你产生了帮助,那么请给博主一个小小的赞哦。…

    2022年7月7日
    34
  • 三种线程安全的单例模式(哪些集合是线程安全的)

    三种线程安全的单例模式(哪些集合是线程安全的)在单线程开发环境中,我们经常使用ArrayList作容器来存储我们的数据,但它不是线程安全的,在多线程环境中使用它可能会出现意想不到的结果。多线程中的ArrayList:我们可以从一段代码了解并发环境下使用ArrayList的情况:publicclassConcurrentArrayList{publicstaticvoidmain(String[]args)throwsInterruptedException{List<Integer>l

    2022年4月18日
    39
  • 操作系统实验一进程管理实验报告(进程的管理和控制实验报告)

    实验一进程管理1.目的和要求通过实验理解进程的概念,进程的组成(PCB结构),进程的并发执行和操作系统进行进程管理的相关原语(主要是进程的创建、执行、撤消)。2.实验内容用C语言编程模拟进程管理,至少要有:创建新的进程;查看运行进程;换出某个进程;杀死运行进程以及进程之间通信等功能。3.实验环境Windows操作系统、VC++6.0C语言4.实验提示PCB结…

    2022年4月15日
    176
  • 大学四年,我把私藏的自学「学习网站/实用工具」都贡献出来了

    大学四年,我把私藏的自学「学习网站/实用工具」都贡献出来了在分享之前,先说说初学者如何学习编程,这个话题想必非常的重要,要学好编程,给你一些学习网站也好、实用工具也好,但前提是你知道如何去学习它。见过很多初学者,以及小鹿我刚开始学习的时候,也是自己瞎摸索,找不到路子,看什么书?看什么资料?编程的方向太多了,如果确定自己的方向?尤其是上大一、大二甚至大三还没有确定自己到底是学习前端还是后天,每天这学一点,那学一块,掌握那么多,没有一门精通的,去面试的时候…

    2022年6月12日
    33
  • Spring Cloud Greenwich.RELEASE 正式发布!一个非常有看头的版本!

    Spring Cloud Greenwich.RELEASE 正式发布!一个非常有看头的版本!译文来源 Spring 技术社区 SpringCloudG RELEASE 现已正式发布 可以在 SpringMilest 和 MavenCentral 库获取到 也可以查看 Greenwich 发布说明了解更多信息 寿命终止 EOL 提醒 Edgware 版本将于 2019 年 8 月 1 日进入 EOL 状态 详细说明参见 Spring

    2025年7月23日
    4
  • linux 权限详解rwx[通俗易懂]

    linux 权限详解rwx[通俗易懂]第2~10个字符当中的每3个为一组,左边三个字符表示所有者权限,中间3个字符表示与所有者同一组的用户的权限,右边3个字符是其他用户的权限。这三个一组共9个字符,代表的意义如下:r(Read,读取):对文件而言,具有读取文件内容的权限;对目录来说,具有浏览目录的权限。w(Write,写入):对文件而言,具有新增、修改文件内容的权限;对目录来说,具有删除、移动目录内文件的权限。x(eXec

    2022年6月1日
    92

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号