[从0到1搭嵌入式工程]常用加密方法之AES加解密及密码生成和获取、cyassl库

2019-07-13 03:09发布

在项目中,遇到两个终端之间的传输,就会遇到数据加密的问题,比如使用P2P协议音视频和命令的传输。这时,对于加密方法的选择,往往使用AES就可以满足需求了。 下文中还会介绍密码的生成和获取。 AES: 高级加密标准。是一种对称分组加密算法。 对称的意思是加密端和解密端使用相同的密码。分组的意思是把数据分成一小块一小块,进行加密。 AES加密相对于DES(数据加密标准),速度更快,安全级别更高,对称加密本身的速度也很快,所以我们在使用AES加密时,不需要过分担心加解密本身对资源的过多占用。一般来说,密钥越长,运行的速度就越慢,应该根据的我们实际需要的安全级别来选择,一般来说,RSA建议采用1024位的数字,ECC建议采用160位,AES采用128位(16字节)即可。 AES加密的特点: 加密前和加密后,数据长度不会发生改变。 在选择了AES加密之后, 还需要选择AES的加密模式,下面是四种常见的加密模式: 主要来自于:https://www.cnblogs.com/liangxuehui/p/4651351.html 1,ECB 电话本模式 将需要加密的数据分成若干个相同的小段,然后对每一小段分别进行加密。合在一起,就是密文。 优点: 1.简单;2.有利于并行计算;3.误差不会被传送; 缺点: 1.不能隐藏明文的模式;2.可能对明文进行主动攻击(不知道怎么个攻击方法); 2,CBC密码分组链接模式 优点:1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。 缺点:1.不利于并行计算;2.误差传递(前面的密文要传递给下一次加密);3.需要初始化向量IV 3,CFB密码反馈模式 优点:1.隐藏了明文模式;2.分组密码转化为流模式;3.可以及时加密传送小于分组的数据; 缺点:1.不利于并行计算;2.误差传送:一个明文单元损坏影响多个单元;3.唯一的IV; 4,OFB输出反馈模式 优点:1.隐藏了明文模式;2.分组密码转化为流模式;3.可以及时加密传送小于分组的数据; 缺点:1.不利于并行计算;2.对明文的主动攻击是可能的;3.误差传送:一个明文单元损坏影响多个单元; CFB和OFB没有用过,不知道什么时候适用。 对于嵌入式来说, AES加密可以使用cyassl 3.3.0,https://download.csdn.net/download/bingyu880101/10689018 以下围绕这个库的API展开。 首先是ECB模式,分块加密,需要自己分块,AesEncryptDirect一次只能对16个字节 128位进行加密。 Aes g_aes; char encrypt_buf[16] = {0}; char encrypt_key[20] = {0}; char data_buf[1024] = {0}; int data_len = 0; { int encrypt_block_len = data_len/16; AesSetKeyDirect(&g_aes, (const unsigned char *)encrypt_key, 16, NULL, AES_ENCRYPTION); int i = 0; for(i=0; i 然后是CBC模式,需要设置IV值,加密端和解密端需要设置一样的IV值。这里设置为NULL;对于不够16个字节的数据,我们保留原文,不进行加密处理。对于CBC方式,也可以自己分段,每次加密16字节,但是在循环时,每一次都必须调用AesSetKey,对IV值进行重置。 Aes g_aes; char encrypt_buf[1024] = {0}; char encrypt_key[20] = {0}; char data_buf[1024] = {0}; int data_len = 0; { AesSetKey(&g_aes, (const unsigned char *)encrypt_key, 16, NULL, AES_ENCRYPTION); AesCbcEncrypt(&g_aes, (unsigned char *)encrypt_buf, (const unsigned char*)(data_buf), (data_len/16 * 16)); memcpy(data_buf, encrypt_buf, (data_len/16 * 16)); } 对于解密,操作是一样的。 在AesSetKey时,最后的参数需要传入 AES_DECRYPTION。 对数据的加解密,对于音频,因为数据量小,另外从中间截取就可以播放,所以需要全加密,而对于视频数据来说,因为数据量较大,而P帧的解析又依赖于I帧,同时在I帧中自身也有对数据的校验,所以只需要对I帧的前32个字节加密,就可以保证视频数据不会被窃取。 下面是密码生成和获取方式 密码在设备启动时随机生成一次,每隔一段时间,定期随机生成, 然后通过HTTPS协议,上报到后台服务器,手机app去连接设备时,如果密码认证失败,就去后台获取最新的密码,再次连接。 随机密码串的生成方式: Nonce是或Number once的缩写,在密码学中Nonce是一个只被使用一次的任意或非重复的随机数值。 这里用时间戳做种子,随机生成数,映射出一个字符串,作为nonce密码。生成一个15位的字符串,然后在用密码的时候,在第16位赋值一个字符 '0' 过去凑成16位的密码。 char NonceChars[63] = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789”; int gen_nonce(unsigned int length, char* nonce, unsigned int size) { unsigned int i = 0; struct timeval tv; unsigned int seed; int chars_len = strlen(NonceChars); if(size <= length) { return -1; } (void)gettimeofday(&tv, NULL); seed = (int)tv.tv_usec+tv.tv_sec+time(NULL); (void)srand(seed); for(i=0;i