mbedtls學習(5)僞隨機數生成器

隨機數生成器

真隨機數生成器(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;
}

運行結構
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章