真随机数生成器(TRNG)一般来自物理设备,伪随机数生成器(PRNG)可以分为”种子“(又称熵源)和内部结构2部分,实际应用中常用真随机数作为种子,再通过伪随机数生成指定长度序列。
伪随机数生成器也称为确定性随机生成器(DRBG),一种近似随机数序列的算法。具体方法有Hash_DRBG、HMAC_DRBG、CTR_DRBG、Hash_DRBG使用单项散列算法作为随机数生成器基础算法、HMAC_DRBG使用消息认证码算法作为随机数生成器基础算法、CTR_DRBG使用分组密码算法的计数器模式作为随机数生成器基础算法
需要开启如下宏
#define MBEDTLS_AES_C 使能AES算法
#define MBEDTLS_SHA256_C 使能SHA256算法
#define MBEDTLS_ENTROPY_C 使能熵源模块
#define MBEDTLS_CTR_DRBG_C 使能随机数模块
#define MBEDTLS_AES_ROM_TABLES 使能预定义S盒
#include
#include
#include
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/platform.h"
#define assert_exit(cond, ret) \
do { if (!(cond)) { \
printf(" !. assert: failed [line: %d, error: -0x%04X]\n", __LINE__, -ret); \
goto cleanup; \
} } while (0)
static void dump_buf(char *info, uint8_t *buf, uint32_t len)
{
mbedtls_printf("%s", info);
for (int i = 0; i < len; i++) {
mbedtls_printf("%s%02X%s", i % 16 == 0 ? "\n ":" ",
buf[i], i == len - 1 ? "\n":"");
}
}
/*
static int entropy_source(void *data, uint8_t *output, size_t len, size_t *olen)
{
uint32_t seed;
seed = sys_rand32_get();
if (len > sizeof(seed)) {
len = sizeof(seed);
}
memcpy(output, &seed, len);
*olen = len;
return 0;
}*/
int main(void)
{
int ret = 0;
uint8_t random[64];
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
const uint8_t *pers = "CTR_DRBG";
mbedtls_entropy_init(&entropy);//初始化熵结构体
mbedtls_ctr_drbg_init(&ctr_drbg);//初始化随机数结构体
/* mbedtls_entropy_add_source(&entropy, entropy_source, NULL,
MBEDTLS_ENTROPY_MAX_GATHER,//熵源可用阈值,随机数达到阈值时熵源才被使用
MBEDTLS_ENTROPY_SOURCE_STRONG);//强熵源,一般是硬件真随机数生成器
//添加熵源接口,设置熵源属性*/
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers, strlen(pers));//根据个性化字符串跟新种子
assert_exit(ret == 0, ret);
mbedtls_printf("\n . setup rng ... ok\n");
ret = mbedtls_ctr_drbg_random(&ctr_drbg, random, sizeof(random));//生成指定长度随机数,随机数长度小于MBEDTLS_CTR_DRBG_MAX_REQUEST,默认1024
assert_exit(ret == 0, ret);
dump_buf("\n . generate 64 byte random data ... ok", random, sizeof(random));
cleanup:
mbedtls_ctr_drbg_free(&ctr_drbg);//释放随机数结构体
mbedtls_entropy_free(&entropy);//释放熵结构体
return 0;
}
注意打开以下宏
#define MBEDTLS_AES_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_BIGNUM_C 使能大数计算
#define MBEDTLS_GENPRIME 使能素数生成
#define MBEDTLS_AES_ROM_TABLES
#include
#include
#include
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/bignum.h"
#include "mbedtls/platform.h"
#define assert_exit(cond, ret) \
do { if (!(cond)) { \
printf(" !. assert: failed [line: %d, error: -0x%04X]\n", __LINE__, -ret); \
goto cleanup; \
} } while (0)
static void dump_buf(char *info, uint8_t *buf, uint32_t len)
{
mbedtls_printf("%s", info);
for (int i = 0; i < len; i++) {
mbedtls_printf("%s%02X%s", i % 16 == 0 ? "\n ":" ",
buf[i], i == len - 1 ? "\n":"");
}
}
/*
static int entropy_source(void *data, uint8_t *output, size_t len, size_t *olen)
{
uint32_t seed;
seed = sys_rand32_get();
if(len > sizeof(seed)) {
len = sizeof(seed);
}
memcpy(output, &seed, len);
*olen = len;
return 0;
}*/
int main(void)
{
int ret = 0;
uint8_t prime[64];
mbedtls_mpi P, Q;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
const uint8_t *pers = "CTR_DRBG";
mbedtls_mpi_init(&P); //初始化大数结构体
mbedtls_mpi_init(&Q); //初始化大数结构体
mbedtls_entropy_init(&entropy);//初始化熵结构体
mbedtls_ctr_drbg_init(&ctr_drbg);//初始化随机数结构体
/* mbedtls_entropy_add_source(&entropy, entropy_source, NULL,
MBEDTLS_ENTROPY_MAX_GATHER,
MBEDTLS_ENTROPY_SOURCE_STRONG);*/
//根据个性化字符串更新种子
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers, strlen(pers));
assert_exit(ret == 0, ret);
mbedtls_printf("\n . setup rng ... ok\n");
mbedtls_printf("\n ! Generating large primes may take minutes!\n");
//生成大素数,可以指定生成长度
ret = mbedtls_mpi_gen_prime(&P, sizeof(prime)*8, //生成素数长度
1, //生成素数标志为1时(P-1)/2也为素数
mbedtls_ctr_drbg_random, //随机数生成接口
&ctr_drbg);//随机数结构体
assert_exit(ret == 0, ret);
//大整数减操作
ret = mbedtls_mpi_sub_int(&Q, &P, 1);//Q=P-1
assert_exit(ret == 0, ret);
//大整数除操作
ret = mbedtls_mpi_div_int(&Q, NULL, &Q, 2);//Q=Q/2
assert_exit(ret == 0, ret);
//判断Q是否为素数
ret = mbedtls_mpi_is_prime(&Q, mbedtls_ctr_drbg_random, &ctr_drbg);
assert_exit(ret == 0, ret);
mbedtls_printf("\n . Verifying that Q = (P-1)/2 is prime ... ok\n");
//将大整数写如数组
mbedtls_mpi_write_binary(&P, prime, sizeof(prime));
dump_buf("\n . generate 512 bit prime data ... ok", prime, sizeof(prime));
cleanup:
mbedtls_mpi_free(&P); //释放大数结构体
mbedtls_mpi_free(&Q);
mbedtls_entropy_free(&entropy);
mbedtls_ctr_drbg_free(&ctr_drbg);
return 0;
}