在项目中,遇到两个终端之间的传输,就会遇到数据加密的问题,比如使用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