• 随机数发生器设计(四)


    概述

    本示例DRNG设计参考了GM/T 0105 ,基于SM3算法实现,内部功能接口包括初始化函数、重播种函数、输出函数和已知答案自测试函数,同时还具备DRNG内部状态和错误状态两种内部工作状态。整体框图如下图所示。
    DRNG结构

    1 内部状态

    内部状态包括{V, C, reseed_counter, last_reseed_time, reseed_counter_interval, reseed_time_interval },定义如下:
    ——比特串V,长度为440比特,每次随机数生成时会进行更新;
    ——比特串C,长度为440,每次重播种时会进行更新;
    ——reseed_counter, 在初始化或重播种之后,请求随机数的次数,每次执行随机数生成操作时会加1;
    ——last_reseed_time,上次重播种的时间值,Unix 时间戳,单位为秒;
    ——reseed_counter_interval,重播种计数器阈值,该值为常量值1024;
    ——reseed_time_interval,重播种时间阈值,单位为秒,该值为常量值60s。

    2 初始化函数

    初始化函数中利用熵源数据对初始状态进行赋值,包含变量初始化和初始化种子函数:
    SM3_RNG_Instantiate(nonce)
    输入:
    ——entropy_input:从熵池获取熵压缩函数处理后的结果,长度为440比特。
    ——nonce: 系统启动时间、当前时间戳、递增计数器信息和固定的随机比特串。
    输出:
    ——初始化内部状态,即V, C, reseed_counter, last_reseed_time, reseed_counter_interval, reseed_time_interval的初始值。
    Nonce包括系统启动时间、当前时间戳、递增计数器信息和固定的随机比特串。如下表所示。

    熵源说明长度(字节)
    CPU信息系统时间(精确到微妙)4
    时间信息UTC时间信息(精确到纳秒)4
    递增计数器每次调用增14
    固定随机值产生自真随机数发生器的随机数128

    初始化流程如下:
    a) 获取440比特的熵输入entropy_input;
    b) 生成种子seed = SM3_df(entropy_input || nonce, seedlen)。Seedlen为440比特;
    c) 初始化内部状态变量,包括V、C、reseed_counter。其中V = seed,C = SM3_df (0x00||V, seedlen),reseed_counter = 1;
    d) 返回内部状态变量。

    #generate nonce
    def RNG_Gen_Nonce():
        global nonce_counter
        boottime = (int(psutil.boot_time()) & 0xFFFFFFFF).to_bytes(4, byteorder = 'big', signed=False)
        timestamp = (int(time_ns()) & 0xFFFFFFFF).to_bytes(4, byteorder = 'big', signed=False)
        counterbytes = nonce_counter.to_bytes(4, byteorder = 'big', signed=False)
        fixrandom = bytes.fromhex("331051e42be3c2139b4077728785ff2553d1d7ffc7c98377875581837ee6a99501bd28a12c491ea656e5666286fdabc56bb05d811596e9667b165367c7d2e4c8")
        nonce_counter += 1
        return boottime + timestamp + counterbytes + fixrandom
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    def SM3_RNG_Instantiate(nonce):
        global min_length
        global max_length
        # min_entropy = min_length
    
        while True:
            (status, entropy_input) = Get_entropy (256, min_length, max_length)
            if status == -2:#need time to generate entropy
                continue
            if status != 0:
                print('entropy source error! please check system source.')
                return -1
            break
        seed = SM3_df(entropy_input + nonce, seedlen)
        reseed_counter = 1
        return Working_state(seed, SM3_df ((bytes([0x00])+ seed), seedlen), reseed_counter)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    def Get_entropy (min_entropy, min_length, max_length):
        global drngentropy
        global drngentropylock
        #compress functiong output is about 340*8bits
        if min_entropy > 340*8:#min entropy is too big
            return (-1, bytes()) 
        drngentropylock.acquire()
        #drngentropy is 440 bits fixed, min_length is not expected bigger than 440
        if min_length > (len(drngentropy)*8):#need time to generate entropy
            drngentropylock.release()
            return (-2, bytes()) 
        #retdrngentropy is the var to return
        retdrngentropy = drngentropy
        #clear drngentropy
        drngentropy = bytes()
        drngentropylock.release()
        # print('main thread get entropy OK----')
        return (0,retdrngentropy)
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3 SM3派生函数

    SM3_df在软件随机数发生器的初始化和重播种阶段使用,对输入字符串进行杂凑运算,并返回请求的随机比特串。定义如下:
    函数定义: SM3_df(input_string, no_of_bits_to_return)
    输入:
    ——input_ string:输入字符串
    ——number_of_bits_to_return:SM3_df函数返回的比特长度
    输出:
    requested_bits:SM3_df函数返回的结果。
    SM3_df函数作为扩展函数,实现流程如下。
    1) 根据输入的返回数据长度(实际为440比特)和输出数据长度256比特计算循环次数。计算循环次数时使用向上取整方式。
    2) 对计数器赋初值1,对临时数据赋初值空。
    3) 计算SM3(计数器值||返回数据长度||输入熵源数据)。
    4) 临时数据更新为临时数据||SM3结果。
    5) 计数器增1。
    6) 判断循环是否结果,若结束则跳转至第7步,否则跳转至第3步。
    7) 取临时数据左侧指定长度数据,返回。

    def sm3Hash(hashbytes:bytes):
        temp = sm3_hash([i for i in hashbytes])
        return bytes.fromhex(temp)
    
    def SM3_df(input_string, no_of_bits_to_return):
        temp = bytes([])
        len = math.ceil(no_of_bits_to_return/outlen)
        counter = 0x01
        for i in range(len):
            temp = temp + sm3Hash(bytes([counter]) + no_of_bits_to_return.to_bytes(4, 'big') + input_string)
            counter = counter + 1
        return temp[0:int(no_of_bits_to_return/8)]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4 其他部分

    随机数发生器中的重播种函数函数、输出函数、自测试函数放在下篇文章介绍。

    如果商用密码产品认证中遇到问题,欢迎加微信symmrz沟通。

  • 相关阅读:
    (十一)PostgreSQL的wal日志(2)-默认wal日志大小
    数据逻辑校验机制
    配置ftp及java链接上传文件到ftp
    详解Native Memory Tracking之追踪区域分析
    Linux虚拟机和开发板scp命令互传文件
    PaO2/FiO2在临床中的应用 氧合指数
    结构思考力~结构化接收信息的三个步骤
    5.过拟合,dropout,正则化
    【摘抄】quant4j
    【ccf-csp题解】第5次csp认证-第三题-模板生成系统-字符串模拟
  • 原文地址:https://blog.csdn.net/Lapedius/article/details/131146637