You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

双AES加密及Linux随机密钥生成相关技术问询

关于AES加密一致性与Linux随机密钥生成的问题解答

我目前在两台嵌入式GSM设备间实现数据传输,需要多次发送命令字符串ring。最初的方案是用固定AES密钥加密输入数据boom,再通过Socket传输,接收方用相同密钥解密。结合我写的AES代码示例,现在有三个疑问需要解答:

unsigned char aes_key[]= "asytfuhcilejnco"; 
unsigned char input_data[]= "Sandeep"; 
int data_size= strlen((char*)input_data); 
int buffer_size = ((int)(data_size/AES_BLOCK_SIZE) + 1)*AES_BLOCK_SIZE; 
AES_KEY enc_key,dec_key; 
unsigned char iv[AES_BLOCK_SIZE]; 

int main() { 
    unsigned char enc_buffer[buffer_size+1]; 
    unsigned char dec_buffer[buffer_size+1]; 
    memset(iv,0x00,AES_BLOCK_SIZE); 
    AES_set_encrypt_key(aes_key,sizeof(aes_key)*8,&enc_key); 
    AES_cbc_encrypt(input_data,enc_buffer,sizeof(input_data),&enc_key,iv,AES_ENCRYPT); 
    enc_buffer[buffer_size+1]='\0'; 
    memset(iv,0x00,AES_BLOCK_SIZE); 
    AES_set_decrypt_key(aes_key,sizeof(aes_key)*8,&dec_key); 
    AES_cbc_encrypt(enc_buffer,dec_buffer,sizeof(input_data),&dec_key,iv,AES_DECRYPT); 
    dec_buffer[buffer_size+1]='\0'; 
    cout<<"input_data="<<input_data<<endl; 
    cout<<"enc_buffer="<<enc_buffer<<endl; 
    cout<<"dec_buffer="<<dec_buffer<<endl; 
}

问题1:相同input_data与aes_key下,加密数据是否始终相同?

答案是是的,在你当前的代码实现下,每次加密结果都会完全一致。原因在于你使用了AES-CBC模式,并且把初始化向量(IV)通过memset(iv,0x00,AES_BLOCK_SIZE)固定成了全0。CBC模式的加密过程依赖IV:第一个明文块会和IV异或后再加密,后续块则和前一个密文块异或。当IV、密钥、明文三者都固定时,加密结果必然完全相同。

不过要提醒一句:固定IV在安全性上有风险,尤其是用同一个密钥加密多个相同明文时,容易被攻击者破解。如果要提升安全性,建议每次加密都使用随机生成的IV,然后把IV和密文一起传给接收方(IV不需要加密)。

问题2:是否存在随机密钥生成API?

当然有,而且推荐使用专门的安全随机密钥生成API,比自己用随机数转字符的方式更可靠。常用的有:

  • OpenSSL库的RAND_bytes()函数:这是生成加密安全随机密钥的标准方式,它会从系统的安全随机源获取熵,生成的密钥不可预测,适合AES等加密场景。
  • Linux系统调用getrandom():直接从内核的随机数生成器获取安全随机字节,不需要依赖第三方库,适合嵌入式环境。
  • 读取/dev/urandom设备文件:这是传统方式,打开该文件后读取的字节都是加密安全的随机数据,不过用系统调用会更高效。

不推荐自己用循环生成0-26随机数转字符的方式,这种方式生成的密钥熵值很低,容易被暴力破解,安全性不足。

问题3:Linux C++中用于生成随机数的系统调用是什么?

在Linux下,C++中可以直接调用的安全随机数系统调用主要有两个:

  1. getrandom():这是较新的系统调用(Linux 3.17+支持),可以直接从内核的/dev/urandom等价的随机源获取加密安全的随机字节,不需要打开文件描述符,使用起来更方便。调用示例:
    #include <sys/random.h>
    unsigned char key[16]; // AES-128密钥
    ssize_t ret = getrandom(key, sizeof(key), GRND_RANDOM);
    if (ret != sizeof(key)) {
        // 处理错误
    }
    
  2. getentropy():这是getrandom()的简化版本,只能获取少量随机字节(最多256字节),不需要指定标志,同样从安全随机源获取数据。

另外,如果你需要兼容更老的Linux版本,也可以通过打开/dev/urandom文件并读取的方式获取随机数,但getrandom()是更优的选择。注意不要使用标准库的rand()函数,它生成的是伪随机数,可预测性强,完全不适合生成加密密钥。


内容的提问来源于stack exchange,提问作者hari

火山引擎 最新活动