零、随机数应用
生成盐,用于基于口令的密码
生成密钥,用于加密和认证
生成一次性整数Nonce,防止重放攻击
生成初始化向量IV
构成
种子,真随机数生成器的种子来源于物理现象
内部状态,种子用来初始化内部状态
一、真随机数和伪随机数
1.区别
随机数在安全技术中通常被用于生成随机序列(eg. 秘钥),对于一个随机数的生成而言,是否真正的做到“随机”是最重要的。
真随机数通常来源于硬件随机数生成器,每次生成的随机数都是真正的随机数,但是因为物理因素,生成的时间较慢。比如STM32中提供的RNG硬件外设。
伪随机数通常来源于某个生成算法,每次生成的随机数虽然是随机的,但还是遵循生成算法的规则,优点是生成速度较快。比如C库中提供的rand函数,在相同的种子下,其生成的随机数序列相同,所以称之为伪随机数。
所以一般情况下,有一种比较巧妙的办法:将两者结合起来,先使用真随机数生成种子,然后使用伪随机数生成算法,这样既保证了生成速度,又保证了生成的序列是真正的随机数。
对应到 mbedtls 中,将产生真随机数的模块称为真随机数生成器(TRNG),将产生伪随机数的模块称为伪随机数发生器(PRNG)(也叫做确定性随机数生成器,DRBG),其中伪随机数所使用的种子称为熵源(熵池)。
2.伪随机数生成算法
NIST SP 800-90A规范中描述了三种产生伪随机数的算法:
Hash_DRBG:使用单向散列算法作为伪随机数生成的基础算法;
HMAC_DRBG:使用消息认证码算法作为随机数生成的基础算法;
CRT_DRBG:使用分组密码算法的计数器模式作为随机数生成的基础算法(重点)。
CRT_DRBG 可以理解为一个AES加密过程,加密结果为期望随机数序列。
二、自定义熵源接口
mbedtls中可以通过开启宏定义 MBEDTLS_ENTROPY_HARDWARE_ALT 来开启熵源接口,用户可以在熵源接口中实现自己的硬件获取真随机数代码。
1.开启宏定义
/**
* \def MBEDTLS_ENTROPY_HARDWARE_ALT
*
* Uncomment this macro to let mbed TLS use your own implementation of a
* hardware entropy collector.
*
* Your function must be called \c mbedtls_hardware_poll(), have the same
* prototype as declared in entropy_poll.h, and accept NULL as first argument.
*
* Uncomment to use your own hardware entropy collector.
*/
#define MBEDTLS_ENTROPY_HARDWARE_ALT
2.自定义实现mbedtls_hardware_poll函数
创建一个新文件用于存放我们编写的该函数实现,这里我创建文件entropy_hardware_alt.c。
实现时需要包含头文件entropy_poll.h,其中包含了 mbedtls_hardware_poll() 函数的原型定义:
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
/**
* \brief Entropy poll callback for a hardware source
*
* \warning This is not provided by mbed TLS!
* See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h.
*
* \note This must accept NULL as its first argument.
*/
int mbedtls_hardware_poll( void *data,
unsigned char *output, size_t len, size_t *olen );
#endif
① 开启硬件RNG外设:
② 编辑文件entropy_hardware_alt.c,实现函数
#include "mbedtls/entropy_poll.h"
#ifdef MBEDTLS_ENTROPY_HARDWARE_ALT
#include "main.h"
#include "string.h"
#include "stm32l4xx_hal.h"
#include "mbedtls/entropy_poll.h"
extern RNG_HandleTypeDef hrng;
int mbedtls_hardware_poll( void *Data, unsigned char *Output, size_t Len, size_t *oLen )
{
uint32_t index;
uint32_t randomValue;
for (index = 0; index < Len/4; index++)
{
if (HAL_RNG_GenerateRandomNumber(&hrng, &randomValue) == HAL_OK)
{
*oLen += 4;
memset(&(Output[index * 4]), (int)randomValue, 4);
}