0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

极简加解密库--使数据传输更加安全

Rice嵌入式开发技术分享 来源:Rice 嵌入式开发技术分享 作者:Rice 嵌入式开发技 2023-02-22 16:31 次阅读

概述

  • 互联网时代,安全成为了一个沉重的话题。文件传输、电子邮件等的安全性尤为重要。我们为了保证安全性,必须对其内容加密,
  • 加密的作用就是防止有用或私有化信息在传输链路上被拦截和窃取。提高数据传输的可靠性。
  • 嵌入式开发中,我们会涉及到数据的传输,文件的传输。很多人都没有考虑其数据的安全性问题,往往都是明文的方式传输,最多增加CRC进行数据的完整性校验。这明显没有考虑数据的安全性问题。
  • 最近项目遇到安全性问题,所以也开始折磨一下加密相关知识,发现RT-THREAD有个比较好软件包--tinycrypt(一个简小并且可配置的加解密软件包,包含算法:aes,base64,md5,sha1,sha2)。其中:AES刚好符合我的项目需求。

AES加密算法

AES加密标准又称为高级加密标准Rijndael加密法,是美国国家标准技术研究所NIST旨在取代DES的21世纪的加密标准。AES的基本要求是,采用对称分组密码体制,密钥长度可以为128、192或256位,分组长度128位。AES算法是最为常见的额对称加密算法之一。

AES加密流程说明:

AES的加解密流程图如下:ca511a26-b13a-11ed-a826-dac502259ad0.png

加解密流程图部件说明:

  • 明文P:没有经过加密的数据或文件。
  • 密钥K:用来加密明文P的密钥,在对称加密算法中,加密与解密的密钥是相同的。密钥为接收方与发送方协商产生,但不可以直接在网络上传输,否则会导致密钥泄漏,通常是通过非对称加密算法加密密钥,然后再通过网络传输给对方,或者直接面对面商量密钥。密钥是绝对不可以泄漏的,否则会被攻击者还原密文,窃取机密数据。
  • AES加密函数:设AES加密函数为E,则 C = E(K + P),其中P为明文,K为密钥,C为密文。也就是说,把明文P和密钥K作为加密函数的参数输入,则加密函数E会输出密文C。
  • 密文C:通过密钥对明文进行加密处理后的数据或文件。
  • AES解密函数:设AES解密函数为D,则 P = D(K + C),其中C为密文,K为密钥,P为明文。也就是说,把密文C和密钥K作为解密函数的参数输入,则解密函数会输出明文P。

AES加密方法:

  1. AES为分组加密,分组加密也就是把明文分成一组一组的,每组的长度相等,每次加密一组数据,直到加密完整个明文。
AES 密钥长度(32bit) 分组长度(32bit) 加密轮数
AES-128 4 4 10
AES-192 6 4 12
AES-256 8 4 14
  1. 在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节,每个字节8位,密钥的长度可以使用128位、192位或者258位。密钥的长度不同,推荐加密轮数也不同,比如AES-128也就是密钥的长度为128位,加密轮数为10轮,AES-192为12轮,AES-256为14轮。以AES-128为例,加密中一轮的4个操作:
  • 字节代换:AES的字符代换其实就是一个简单的查表操作,AES定义了一个S盒和一个逆S盒。
  • 行位移:就是一个简单的左循环移位操作。
  • 列混合:是通过矩阵相乘来实现的,经过移位后的状态矩阵与固定的矩阵相乘,得到混淆后的状态矩阵。
  • 轮密钥加:是将128位轮密钥Ki同状态矩阵中的数据进行逐位异或操作。
ca623e64-b13a-11ed-a826-dac502259ad0.png
  1. 加密:加密第1轮到第9轮的轮函数一样,最后一轮迭代不执行列混合,另外,在第一轮迭代之前,先将明文和原始密钥进行一次异或加密操作。
  2. 解密:解密过程仍为10轮,每一轮的操作是加密操作的逆操作。由于AES的4个轮操作都是可逆的,因此,解密操作的一轮就是顺序执行逆行移位、逆字节代换、轮密钥加和逆列混合。同加密操作类似,最后一轮不执行逆列混合,在第1轮解密之前,要执行1次密钥加操作。

tinycrypt的AES使用

  1. tinycrypt这个软件包精简使用起来很方便,其包含了源码和测试用例(AES和MD5),tinycrypt软件包的目录结构如下:
.
├──include
│├──tiny_aes.h//aes头文件
│├──tiny_base64.h//base64头文件
│├──tinycrypt_config.h//tinycrypt配置头文件
│├──tinycrypt.h//tinycrypt头文件
│├──tiny_md5.h//md5头文件
│├──tiny_sha1.h//sha1头文件
│└──tiny_sha2.h//sha2头文件
├──LICENSE
├──README.md
├──samples
│├──aes_sample.c//aes测试用例头文件
│└──md5_sample.c//md5测试用例头文件
└──src
├──tiny_aes.c//aes源文件
├──tiny_base64.c//base64源文件
├──tiny_md5.c//md5头文件
├──tiny_sha1.c//sha1头文件
└──tiny_sha2.c//sha2头文件
  1. 在Ubuntu环境下,搭建tinycrypt的环境,测试加解密文件,目录结构如下:
.
├──main.c
├──makefile
└──tinycrypt
├──include
│├──tiny_aes.h
│├──tiny_base64.h
│├──tinycrypt_config.h
│├──tinycrypt.h
│├──tiny_md5.h
│├──tiny_sha1.h
│└──tiny_sha2.h
├──LICENSE
├──README.md
├──samples
│├──aes_sample.c
│└──md5_sample.c
└──src
├──tiny_aes.c
├──tiny_base64.c
├──tiny_md5.c
├──tiny_sha1.c
└──tiny_sha2.c
  • 在目录中增加makefile文件和main.c,其中makefile用于构建工程,main.c用于编写我们的测试代码,其中:

  • makefile文件内容:

VERSION=1.0.0#版本号

SOURCE=main.c#源文件
SOURCE+=$(wildcard./tinycrypt/src/*.c)#通过wildcard函数获取tinycrypt源文件
OBJECT=$(patsubst%.c,%.o,$(SOURCE))#通过patsubst函数替换源文件为目标文件

INCLUDE=-I./tinycrypt/include#包含头文件路径

TARGET=tinycrypt#目标文件名字
CC=gcc#工具链
CFLAGS=-Wall-g#编译选项

OUTPUT=output#输出目录

$(TARGET):$(OBJECT)#构建执行命令
@mkdir-p$(OUTPUT)#创建输出目录
$(CC)$^$(CFLAGS)-o$(OUTPUT)/$(TARGET)_$(VERSION)#编译

%.o:%.c#将源文件编译成目标文件
$(CC)$(INCLUDE)$(CFLAGS)-c$< -o $@                  

.PHONY:clean                                                # 执行make clean之后,清除过程文件
clean:
 @rm -rf $(OBJECT) $(OUTPUT)
  • main.c文件内容,测试历程说明:将一个文件(index.js)通过AES加密,然后生成加密文件(encrypt_index.js),再将加密文件(encrypt_index.js)通过AES解密,生成解密文件(decrypt_index.js)。
#include
#include
#include
#include

#include
#include

#include
#include

#include"tiny_aes.h"

#defineENCRYPT_TEST_FILE"./index.js"
#defineENCRYPT_TEST_ENCRYPT_FILE"./encrypt_index.js"
#defineENCRYPT_TEST_DECRYPT_FILE"./decrypt_index.js"

#defineENCRYPT_SINGLE_SIZE1024//加密单包长度

#defineENCRYPT_AES_IV_LEN16//AES向量长度
#defineENCRYPT_AES_KEY_LEN256//AES密钥长度
#defineENCRYPT_AES_IV"0123456789ABCDEF"//AES向量
#defineENCRYPT_AES_KEY"0123456789ABCDEF0123456789ABCDEF"//AES密钥
//AES参数结构体定义
typedefstruct
{
uint8_taesIv[ENCRYPT_AES_IV_LEN];
uint8_taesKey[ENCRYPT_AES_KEY_LEN];
tiny_aes_contextaes_ctx;
}EncryptInfo;

staticEncryptInfog_info={0};
//aes参数初始化
voidaes_init(constchar*iv,constchar*key)
{
memset(g_info.aesIv,0,ENCRYPT_AES_IV_LEN);
memset(g_info.aesKey,0,ENCRYPT_AES_KEY_LEN);
if(iv==NULL){
memcpy(g_info.aesIv,ENCRYPT_AES_IV,strlen(ENCRYPT_AES_IV));
}
else{
memcpy(g_info.aesIv,iv,strlen(iv));
}
if(key==NULL){
memcpy(g_info.aesKey,ENCRYPT_AES_KEY,strlen(ENCRYPT_AES_KEY));
}
else{
memcpy(g_info.aesKey,key,strlen(key));
}
}
//aes加密函数的封装
voidaes_encrypt(uint8_t*dest_buff,constuint8_t*src_buff,uint32_tlen)
{
tiny_aes_crypt_cbc(&g_info.aes_ctx,AES_ENCRYPT,len,g_info.aesIv,(uint8_t*)src_buff,dest_buff);
}
//aes解密函数的封装
voidaes_decrypt(uint8_t*dest_buff,constuint8_t*src_buff,uint32_tlen)
{
tiny_aes_crypt_cbc(&g_info.aes_ctx,AES_DECRYPT,len,g_info.aesIv,(uint8_t*)src_buff,dest_buff);
}

intmain(intargc,char*argv[])
{
intraw_size=0;
intsrc_fd=-1;
intencrypt_fd=-1;
intdecrypt_fd=-1;
intsrc_file_size=0;
intsrv_file_offset=0;
uint8_tsrc_buff[ENCRYPT_SINGLE_SIZE];
uint8_tencrypt_buff[ENCRYPT_SINGLE_SIZE];
uint8_tdecrypt_buff[ENCRYPT_SINGLE_SIZE];

//加密文件,将明文文件(index.js)通过AES加密为加密文件(encrypt_index.js)
{
aes_init(NULL,NULL);//aes初始化
tiny_aes_setkey_enc(&g_info.aes_ctx,(uint8_t*)g_info.aesKey,ENCRYPT_AES_KEY_LEN);//设置密钥
src_fd=open(ENCRYPT_TEST_FILE,O_RDONLY,0777);//打开明文文件
if(src_fd==-1){
printf("%d-ERR:openfile(%s)failedrn",__LINE__,ENCRYPT_TEST_FILE);
return-1;
}

encrypt_fd=open(ENCRYPT_TEST_ENCRYPT_FILE,O_RDWR|O_CREAT|O_TRUNC,0777);//打开加密文件
if(encrypt_fd==-1){
printf("%d-ERR:openfile(%s)failedrn",__LINE__,ENCRYPT_TEST_ENCRYPT_FILE);
return-1;
}

raw_size=lseek(src_fd,0,SEEK_END);//获取明文文件的大小
srv_file_offset=0;
lseek(src_fd,0,SEEK_SET);
printf("%d-INFO:sourcefilesize:%drn",__LINE__,raw_size);

while(srv_file_offset< raw_size) {
            memset(src_buff,0,ENCRYPT_SINGLE_SIZE);
memset(encrypt_buff,0,ENCRYPT_SINGLE_SIZE);
read(src_fd,src_buff,ENCRYPT_SINGLE_SIZE);//读取明文文件内容
aes_encrypt(encrypt_buff,src_buff,ENCRYPT_SINGLE_SIZE);//明文文件内容加密
write(encrypt_fd,encrypt_buff,ENCRYPT_SINGLE_SIZE);//将加密内容写入加密文件中
srv_file_offset+=ENCRYPT_SINGLE_SIZE;
}
close(src_fd);
src_fd=-1;
close(encrypt_fd);
encrypt_fd=-1;
}

//解密文件,将加密文件(encrypt_index.js)通过AES解密为解密文件(decrypt_index.js)
{
aes_init(NULL,NULL);//aes初始化
tiny_aes_setkey_dec(&g_info.aes_ctx,(uint8_t*)g_info.aesKey,ENCRYPT_AES_KEY_LEN);//设置密钥
src_fd=open(ENCRYPT_TEST_ENCRYPT_FILE,O_RDONLY,0777);//打开密文文件
if(src_fd==-1){
printf("%d-ERR:openfile(%s)failedrn",__LINE__,ENCRYPT_TEST_ENCRYPT_FILE);
return-1;
}

decrypt_fd=open(ENCRYPT_TEST_DECRYPT_FILE,O_RDWR|O_CREAT|O_TRUNC,0777);//打开解密文件
if(decrypt_fd==-1){
printf("%d-ERR:openfile(%s)failedrn",__LINE__,ENCRYPT_TEST_DECRYPT_FILE);
return-1;
}

src_file_size=raw_size;//设置明文文件的大小
srv_file_offset=0;
lseek(src_fd,0,SEEK_SET);
printf("%d-INFO:encryptfilesize:%drn",__LINE__,src_file_size);

while(srv_file_offset< src_file_size) {
            memset(src_buff,0,ENCRYPT_SINGLE_SIZE);
memset(decrypt_buff,0,ENCRYPT_SINGLE_SIZE);
if((srv_file_offset+ENCRYPT_SINGLE_SIZE)< src_file_size)
            {
                read(src_fd, src_buff, ENCRYPT_SINGLE_SIZE);                                    //读取密文文件内容
aes_decrypt(decrypt_buff,src_buff,ENCRYPT_SINGLE_SIZE);//密文文件解密
write(decrypt_fd,decrypt_buff,ENCRYPT_SINGLE_SIZE);//将解密内容写入解密文件中
srv_file_offset+=ENCRYPT_SINGLE_SIZE;
}
else
{
read(src_fd,src_buff,ENCRYPT_SINGLE_SIZE);//读取最后一包密文文件内容
aes_decrypt(decrypt_buff,src_buff,(ENCRYPT_SINGLE_SIZE));//密文文件解密
write(decrypt_fd,decrypt_buff,(src_file_size-srv_file_offset));//将最后一包解密内容写入解密文件中
break;
}
}
close(src_fd);
src_fd=-1;
close(decrypt_fd);
decrypt_fd=-1;
}

return0;
}
  1. 验证时发现一个问题,加密内容的长度需要16字节的整数倍,所以加密完的文件大小也为16字节的整数倍。值得注意的是,解密的最后一包要根据明文文件的大小算出来的,然后写进解密文件中,因为加密文件是16字节对齐的,所以要去除16字节对齐。

  2. 编译及运行:

rice@rice:~/project/encrypt$make
gcc-I./tinycrypt/include-Wall-g-cmain.c-omain.o
gcc-I./tinycrypt/include-Wall-g-ctinycrypt/src/tiny_sha1.c-otinycrypt/src/tiny_sha1.o
gcc-I./tinycrypt/include-Wall-g-ctinycrypt/src/tiny_aes.c-otinycrypt/src/tiny_aes.o
gcc-I./tinycrypt/include-Wall-g-ctinycrypt/src/tiny_md5.c-otinycrypt/src/tiny_md5.o
gcc-I./tinycrypt/include-Wall-g-ctinycrypt/src/tiny_sha2.c-otinycrypt/src/tiny_sha2.o
gcc-I./tinycrypt/include-Wall-g-ctinycrypt/src/tiny_base64.c-otinycrypt/src/tiny_base64.o
gccmain.otinycrypt/src/tiny_sha1.otinycrypt/src/tiny_aes.otinycrypt/src/tiny_md5.otinycrypt/src/tiny_sha2.otinycrypt/src/tiny_base64.o-Wall-g-ooutput/tinycrypt_1.0.0
rice@rice:~/ohos/project/encrypt$./output/tinycrypt_1.0.0
136-INFO:sourcefilesize:445
171-INFO:encryptfilesize:445
rice@rice:~/ohos/project/encrypt$
  1. 演示结果:
ca7fbeb2-b13a-11ed-a826-dac502259ad0.png

结论:

  1. 通过加密方式,提高数据的安全性,避免了数据的泄露
  2. AES加密方式,加密内容的长度需要16字节的整数倍,加密之后长度比实际明文可能要长。所以明文的长度需要告知解密方。
  3. AES是对称加密,所以加密方和解密方的密钥需要一直。

审核编辑黄宇


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据传输
    +关注

    关注

    9

    文章

    1533

    浏览量

    63572
  • 加密
    +关注

    关注

    0

    文章

    293

    浏览量

    23593
收藏 人收藏

    评论

    相关推荐

    请问NFC数据传输如何保证数据安全

    NFC数据传输如何保证数据安全
    发表于 04-07 06:18

    无线数据传输传送收发遥控器

    无线数据传输传送收发遥控器dw-m11明的数据传输设备,代替有线的485通信,应用于电厂,钢厂,码头,煤矿等工业场合,抗干扰能力强,性能稳定。线数据传输传送收发遥控器,用于代替有线的485通信。采用
    发表于 07-08 14:29

    无线数据传输模块的实际应用

    使设备厂商可以远程随时随地对设备进行监控、升级和维护等操作,无线数据传输模块又将这些监测的数据传输给处理系统,是用户可以了解产品的使用状况,完成产品全生命周期的信息收集,指导产品设计和售后服务
    发表于 06-18 04:21

    如何利用MEMS和FPGA设计移动硬盘数据加解密系统?

    来源:维电子随着信息量的急剧增长,信息安全日益受到人们重视。一个完整的数据加解密系统应该 具备安全可靠的密码认证机制和
    发表于 07-31 07:40

    如何利用MEMS强链和FPGA设计USB移动硬盘数据加解密系统?

    随着信息量的急剧增长,信息安全日益受到人们重视。一个完整的数据加解密系统应该具备安全可靠的密码认证机制和加解密算法。利用MEMS强链和FPG
    发表于 08-01 06:48

    mbedtls开源在单片机的数据加解密中有何作用

    单片机常用的数据加解密是什么?mbedtls开源有哪些移植注意事项呢?
    发表于 01-20 07:06

    DMA进行数据传输和CPU进行数据传输的疑问

    求大佬解答,本人正在学习STM32单片机中DMA直接数据存储部分的内容 看了DMA简介后,也上手过实例代码,但是没有实际的项目经验,所以有以下疑问: DMA外设在进行数据传输的操作,是否也是需要经过
    发表于 05-25 17:18

    硬件加解密主要优点及引擎种类

    IoT联网装置日渐普及,大家在享受联网装置所带来便利性的同时,也必须同时承担联网装置的风险,即数据传输过程可能遭窃取、伪造,因此数据传输过程的安全性,对于IoT联网装置是基本的要求,
    发表于 08-28 07:29

    STM32加解密技术

    没有加解密技术是万万不能的• 通讯安全• 平台安全• *例外:STM32 RDP保护知识产权• 加解密技术不是万能的• 只是工具• 无法代替其它STM32
    发表于 09-08 08:18

    基于MEMS和FPGA的移动硬盘数据加解密系统

    基于MEMS和FPGA的移动硬盘数据加解密系统 随着信息量的急剧增长,信息安全日益受到人们重视。一个完整的数据加解密系统应该 具备
    发表于 11-05 08:57 723次阅读
    基于MEMS和FPGA的移动硬盘<b class='flag-5'>数据</b><b class='flag-5'>加解密</b>系统

    Modem数据传输标准

     Modem数据传输标准 数据传输标准是指MODEM的
    发表于 12-28 13:29 922次阅读

    什么是U盘的数据传输

    什么是U盘的数据传输率     便携存储是依靠USB接口与系统相连,其接口的速度就限制着移动硬盘的数据传输率。目前的US
    发表于 01-30 10:21 630次阅读

    数据传输速率是什么意思

    数据传输速率是什么意思 数据传输速率是通过信道每秒可传输的数字信息量的量度。数据传输速率也称为吞吐率。数据传输速率由很
    发表于 03-18 14:45 4942次阅读

    数据传输中的成帧

    什么是数据传输中的成帧 数据传输中的成帧 成帧技术是一种用来在一个比特流内分配或标记信道的技术,为电信提供选择基本的时隙结构和管理方式、错误
    发表于 03-18 14:46 3672次阅读

    网络高效安全数据传输方法设计

      网络数据传输安全的核心是通过对数据发送、网络传输数据接收各个环节中的数据进行加密处理,以达
    发表于 12-25 09:42 1884次阅读
    网络高效<b class='flag-5'>安全数据传输</b>方法设计