当前位置:网站首页>Libtomcrypt AES 加密及解密
Libtomcrypt AES 加密及解密
2022-08-04 09:17:00 【Rose Island】
主控芯片: MM32F2377
开发环境: IAR 7.80.4
libtomcrypt: v1.18.2
AES 简介
加密算法主要分成三种:
- 对称加密: AES / DES / 3DES(加密和解密的秘钥相同)
- 非对称加密:RSA / DSA(加密和解密的秘钥不同,公钥 +私钥)
- 散列算法:SHA-1 / MD5(不需要秘钥)
AES (Advanced Encyption Standard) 为对称加密算法,即加密和解密使用的是相同的密钥。
AES 加密原理
明文 P
未经加密的原始数据
密钥 K
在对称加密中,加密和解密的密钥是相同的。由加密方和解密方确定,或者由加密方通过非对称加密算法对密钥进行加密,再发送给解密方。
密文 C
经过加密后的数据
加密函数: C = E ( K , P ) C = E(K,P) C=E(K,P)
解密函数: P = D ( K , C ) P = D(K,C) P=D(K,C)
AES Modes
AES 有 5 种加密模式:
ECB (Electronic Codebook)
ECB 为最简单的加密模式,根据加密块大小分成若干块,然后使用相同的密钥对每一块单独加密
C i = E k ( P i ) C_i = E_k(P_i) Ci=Ek(Pi)CBC (Cipher Block Chaining)
CBC 先将明文切分成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密
C i = E k ( P i ⊕ C i − 1 ) C_i = E_k(P_i \oplus C_{i-1}) Ci=Ek(Pi⊕Ci−1)CTR (Counter)
CTR 有一个自增的算子,这个算子用密钥加密之后的输出和明文异或的结果得到密文
C − 1 = C − 1 + 1 ( m o d 2 W ) C i = P i ⊕ E k ( C − 1 ) C_{-1} = C_{-1} + 1(mod 2^W) \\ C_i = P_i \oplus E_k(C_{-1}) C−1=C−1+1(mod2W)Ci=Pi⊕Ek(C−1)CFB (Ciphertext Feedback)
CFB 对加密得到的密文再次加密,再将这个加密得到的数据与当前的明文异或
C i = P i ⊕ C 1 C − 1 = E k ( C i ) C_i = P_i \oplus C_1 \\ C_{-1} = E_k(C_i) Ci=Pi⊕C1C−1=Ek(Ci)OFB (Output Feedback)
与 CFB 不同的是,OFB 先对之前的加密结果进行加密,然后再与当前的明文进行异或
C − 1 = E k ( C − 1 ) C i = P i ⊕ C − 1 C_{-1} = E_k(C_{-1}) \\ C_i = P_i \oplus C_{-1} C−1=Ek(C−1)Ci=Pi⊕C−1
AES Padding
当 AES 明文 P 的数据长度不是 16 的倍数时,需要在后面补齐,补齐的方法有多种。
Zero Padding
全部补 0
| AA AA AA AA AA AA AA AA | AA AA AA 00 00 00 00 00|
PKCS7 Padding
差几个字节就补几
| AA AA AA AA AA AA AA AA | AA AA AA 05 05 05 05 05|
ANSI X.923
最后一个字节补缺少的字节个数,前面的都补 0
| AA AA AA AA AA AA AA AA | AA AA AA 00 00 00 00 05|
ISO 10126
最后一个字节补缺少的字节个数,前面的随机补充
| AA AA AA AA AA AA AA AA | AA AA AA 89 12 A3 68 05|
Libtomcrypt 简介
Libtom 是一个开源的、可移植的密码库,分为 Libtomcrypt / Libtommath / Tomsfastmath / Libtompoly / Libtomfloat,其中用的比较多的是 Libtomcrypt 和 Libtommath。
Libtomcrypt 支持多种加密算法,包括 AES,MD5,RSA,HMAC,HKDF 等等。具体的可查看 Libtom 官网。也可查看 [Libtomcrypt 文档][lib_doc]。
使用 AES 算法
Libtomcrypt AES 移植
首先从 Libtomcrypt Github 克隆项目,AES 加密不需要用到 Libtommath 库,如果是 RSA 加密,还需要克隆 Libtommath。
这里选择的是 v1.18.2 Release 版本。
需要调用的文件主要是在 ./libtomcrypt/src
中,根据不同的算法类型进行了分组。
项目使用的 IDE 为 IAR,首先在项目中新建一个分组,为 libtomcrypt
,在该组下根据 ./libtomcrypt/src
中的文件新建分组。
AES 需要使用的文件包括以下:
- cipher
- aes.c
- aes_tab.c
- misc
- compare_testvector.c
- crypt_argchk.c
- crypt_cipher_descriptor.c
- crypt_cipher_is_valid.c
- crypt_find_cipher.c
- crypt_register_cipher.c
- crypt_unregister_cipher.c
- zeromem.c
- modes
- ecb_decrypt.c
- ecb_done.c
- ecb_encrypt.c
- ecb_start.c
将这些文件依次添加进项目分组中。
还需要在 Options -> C/C++ Compiler -> Preprocessor -> Defined symbols 中添加一些宏定义:
LTC_NO_MODES
LTC_NO_MACS
LTC_NO_PRNGS
LTC_NO_CIPHERS
LTC_NO_HASHES
LTC_NO_PK
LTC_NO_PKCS
LTC_NO_MISC
LTC_NO_FILE
LTC_ECB_MODE
LTC_RIJNDAEL
_CRT_SECURE_NO_WARNINGS
这样就完成移植啦
AES 加密 + 解密
这里选择 AES-128-ECB 方式。
首先新建一个 .c 和 一个 .h 文件,在 .h 文件中定义一个 symmetric_ECB
结构体变量名为 ecb
。其中包括了算法类型、块长度以及密钥。
/** A block cipher ECB structure */
typedef struct {
/** The index of the cipher chosen */
int cipher,
/** The block size of the given cipher */
blocklen;
/** The scheduled key */
symmetric_key key;
} symmetric_ECB;
之后定义密钥值以及引用 aes_desc
描述符,描述符里描述了密码算法需要的变量以及函数操作。
.h 里面主要是这三句话:
symmetric_ECB ecb;
unsigned char key[MAXBLOCKSIZE] = "0123456789abcdef";
extern const struct ltc_cipher_descriptor aes_desc;
接下来是 .c 文件。
根据官方文档 Symmetric Block Ciphers 可以知道 Libtomcrypt 对称加密算法调用的一个大致流程:
- 注册算法描述符:
register_cipher()
- 获取算法描述符:
find_cipher()
- 初始化算法结构体:
ecb_start()
- 加密或解密:
ecb_encrypt()
/ecb_decrypt()
- 结束运算:
ecb_done()
- 释放资源:
zeromem(key, sizeof(key))
+zeromem(&ecb, sizeof(ecb))
更详细的可参考文档3.4.8 Examples
。
接下来就模仿这个例子写 aes_ecb_128 的加密和解密函数:
- aes_ecb_128 加密
int mm32_aes_ecb_encrypt(const unsigned char pt[], unsigned char ct[], unsigned long ptLen)
{
int idx = 0;
int err = 0;
// register aes
if(register_cipher(&aes_desc) != CRYPT_OK){
printf("register_cipher failed! \n");
return CRYPT_INVALID_CIPHER;
}
// find aes
if((idx == find_cipher("aes")) == -1){
printf("find_cipher failed! \n");
return CRYPT_NOP;
}
// aes init
if((err = ecb_start(idx, key, cipher_descriptor[idx].min_key_length, 0, &ecb)) != CRYPT_OK){
// printf("ecb_start failed! \nError type is %d. \n", err);
return err;
}
// aes encrypt
if((err = ecb_encrypt(pt, ct, ptLen, &ecb)) != CRYPT_OK){
printf("ecb_encrypt failed! \nError type is %d. \n", err);
return err;
}
printf("********************************************\n");
printf("Encrypt result is %s \n", ct);
printf("********************************************\n");
// aes end
if((err = ecb_done(&ecb)) != CRYPT_OK){
printf("ecb_done failed! \nError type is %d. \n", err);
return err;
}
// unregister aes
if(unregister_cipher(&aes_desc) != CRYPT_OK){
printf("unregister_cipher failed! \n");
return CRYPT_INVALID_CIPHER;
}
// clear up
zeromem(key, sizeof(key));
zeromem(&ecb, sizeof(ecb));
return CRYPT_OK;
}
- aes_ecb_128 解密
int mm32_aes_ecb_decrypt(const unsigned char ct[], unsigned char pt[], unsigned long ptLen)
{
int idx = 0;
int err = 0;
// register aes
if(register_cipher(&aes_desc) != CRYPT_OK){
printf("register_cipher failed! \n");
return CRYPT_INVALID_CIPHER;
}
// find aes
if((idx == find_cipher("aes")) == -1){
printf("find_cipher failed! \n");
return CRYPT_NOP;
}
// aes init
if((err = ecb_start(idx, key, cipher_descriptor[idx].min_key_length, 0, &ecb)) != CRYPT_OK){
printf("ecb_start failed! \nError type is %d. \n", err);
return err;
}
// aes decrypt
if((err = ecb_decrypt(ct, pt, ptLen, &ecb)) != CRYPT_OK){
printf("ecb_decrypt failed! \nError type is %d. \n", err);
return err;
}
printf("********************************************\n");
printf("Decrypt result is %s \n", pt);
printf("********************************************\n");
// aes end
if((err = ecb_done(&ecb)) != CRYPT_OK){
printf("ecb_done failed! \nError type is %d. \n", err);
return err;
}
// unregister aes
if(unregister_cipher(&aes_desc) != CRYPT_OK){
printf("unregister_cipher failed! \n");
return CRYPT_INVALID_CIPHER;
}
// clear up
zeromem(key, sizeof(key));
zeromem(&ecb, sizeof(ecb));
return CRYPT_OK;
}
AES 在线加密 + 解密
推荐一个 AES 在线加密解密网站,支持 5 种加密模式和 5 种 padding 模式,同时也支持多种结果显示模式。
Conclusion
4 个月过去了,项目总算交掉了,CSDN 也是 3 个多月没更新了,想总结一些东西留个纪念吧。
搬完家也一个多月了,慢慢地把家布置成自己想要的样子。感觉加班的日子过的浑浑噩噩的,生活和工作快失去了平衡,所以这个星期想要躺平。休息完后,重新出发吧
明天是七夕,祝七夕快乐噢
边栏推荐
猜你喜欢
交换机链路聚合详解【华为eNSP】
After four years of outsourcing, the autumn recruits finally landed
I am 37 this year, and I was rushed by a big factory to...
陈春花发布声明,这场流量狂欢该到了收尾的时候
[Punctuality Atom STM32 Serial] Chapter 4 STM32 First Experience Excerpted from [Punctual Atom] MiniPro STM32H750 Development Guide_V1.1
Apache APISIX 2.15 版本发布,为插件增加更多灵活性
TiDB升级与案例分享(TiDB v4.0.1 → v5.4.1)
[Cloud Residency Co-Creation] HCSD Celebrity Live Streaming – Employment Guide
《福格行为模型》:如何养成好习惯?
ZbxTable 2.0 重磅发布!6大主要优化功能!
随机推荐
async - await
DOM简述
【正点原子STM32连载】第二章 STM32简介 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
他97年的,我既然卷不过他...
MySQL binlog都有哪些模式?
How to restore the Youxuan database with only data files
sync-diff-inspector 使用实践
leetcode动态规划系列(求路径篇)
GBsae 8c 数据库使用中报错,肿么办?
一道[CSCCTF 2019 Qual]FlaskLight的详解再遇SSTI
TiFlash 源码阅读(五) DeltaTree 存储引擎设计及实现分析 - Part 2
v-model原理,在“radio”、“checkbox”、“select”、修饰符
关于技术学习的6个观点
【正点原子STM32连载】第三章 开发环境搭建 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
【C补充】指针相关知识点收集01
Inheritance and the static keyword
张朝阳对话俞敏洪:谈宇宙、谈焦虑、谈创业、谈退休、谈人生
云函数实现网站自动化签到配置详解【Web函数/Nodejs/cookie】
如何快速将Zabbix5.0升级至6.0?
B站回应HR称“核心用户都是Loser”、求职者是“白嫖党”:已被劝退