国密随机数检测--2/15 块内频数检测

最近研究随机数检测,主要学习了一下NIST和国密检测,这里整理了国密15项检测规项目的原理,数学表达式以及python源码。

15项检测项目分别为单比特频数检测、块内频数检测、扑克检测、重叠子序列检测、游程总数检测、游程分布检测、块内最大“1”游程检测、二元推导检测、自相关检测、矩阵秩检测、累加和检测、近似熵检测、线性复杂度检测、 Maurer通用统计检测、离散傅立叶检测。

规定了商用密码应用中的随机性检测指标和检测方法,适用于对随机数发生器产生的二元序列的随机性检测。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2/15 块内频数检测

a) 将待检序列 ε 分成 N = |n/m| 个长度为 m 的非重叠子序列,将多余的比特舍弃。本规范取m =100 。

b) 计算每个子序列中1所占的比例
国密随机数检测--2/15 块内频数检测

 

 

 c) 计算统计量
国密随机数检测--2/15 块内频数检测

 

 

 国密随机数检测--2/15 块内频数检测

 

 

 d) 计算

国密随机数检测--2/15 块内频数检测

igamc 为不完全伽马函数。

 

 

 

e) 如果 P-value  ≥ α , 则认为待检序列通过块内频数检测。 

 

 

原理:

块内频数检测用来检测待检序列的m位子序列中1的个数是否接近m/2。对随机序列来说,其任意长度为m位中子序列中1的个数都应该接近m/2。

 

参数要求:

n>=100; m>=20

 

不通过分析:

m位子序列0、1分布不均衡

 

测试demo

import math
from fractions import Fraction
#from scipy.special import gamma, gammainc, gammaincc
from gamma_functions import *

#ones_table = [bin(i)[2:].count('1') for i in range(256)]
def count_ones_zeroes(bits):
    ones = 0
    zeroes = 0
    for bit in bits:
        if (bit == 1):
            ones += 1
        else:
            zeroes += 1
    return (zeroes,ones)

def frequency_within_block_test(bits):
    # Compute number of blocks M = block size. N=num of blocks
    # N = floor(n/M)
    # miniumum block size 20 bits, most blocks 100
    n = len(bits)
    M = 20
    N = int(math.floor(n/M))
    if N > 99:
        N=99
        M = int(math.floor(n/N))
    
    if len(bits) < 100:
        print ("Too little data for test. Supply at least 100 bits")
        #return (FAIL,1.0,None)
    
    print ("  n = %d" % len(bits))
    print ("  N = %d" % N)
    print ("  M = %d" % M)
    
    num_of_blocks = N
    block_size = M #int(math.floor(len(bits)/num_of_blocks))
    #n = int(block_size * num_of_blocks)
    
    proportions = list()
    for i in range(num_of_blocks):
        block = bits[i*(block_size):((i+1)*(block_size))]
        zeroes,ones= count_ones_zeroes(block)
        proportions.append(Fraction(ones,block_size))

    chisq = 0.0
    for prop in proportions:  #
        chisq += 4.0*block_size*((prop - Fraction(1,2))**2)
    
    p = gammaincc((num_of_blocks/2.0),float(chisq)/2.0)
    success = (p >= 0.01)
    return success,p,None
    


if __name__ == "__main__":
    #bit2='0111011010111101111101010000110100011000111011000101010111110001010100010011110110100111010000101010111000101'
    bits=[1,1,0,1,0,0,1,1,0,1,0,1,0,1,0,1,1,0,0,1,0,1,1,1,1,1,
        0,1,1,1,1,1,0,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0,
        0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,1,0,0,0,0,1,0,1,0,
        0,1,1,0,0,0,1,1,1,0,1,0,0,0,0,1,0,0,1,0,1,0,1,0,0,1,1,
        0,0,0,1,1,0,1,0,1,1,1,0,0,1,1,1,1,1,0,0,0] 
    s1,s2,s3= frequency_within_block_test(bits)
    print(s1)
    print("p value is %s" %s2)
    

 

 


 

 

上一篇:LeetCode 1286. 字母组合迭代器(回溯/位运算)


下一篇:java – 提取二进制的最后2位