隨機數生成器
真隨機數生成器(TRNG)一般來自物理設備,僞隨機數生成器(PRNG)可以分爲”種子“(又稱熵源)和內部結構2部分,實際應用中常用真隨機數作爲種子,再通過僞隨機數生成指定長度序列。
CTR_DRBG
僞隨機數生成器也稱爲確定性隨機生成器(DRBG),一種近似隨機數序列的算法。具體方法有Hash_DRBG、HMAC_DRBG、CTR_DRBG、Hash_DRBG使用單項散列算法作爲隨機數生成器基礎算法、HMAC_DRBG使用消息認證碼算法作爲隨機數生成器基礎算法、CTR_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 <stdio.h>
#include <string.h>
#include <stdint.h>
#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 <stdio.h>
#include <string.h>
#include <stdint.h>
#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;
}
運行結構