最近研究隨機數檢測,主要學習了一下NIST和國密檢測,這里整理了國密15項檢測規項目的原理,數學表達式以及python源碼。
15項檢測項目分別為單比特頻數檢測、塊內頻數檢測、撲克檢測、重疊子序列檢測、游程總數檢測、游程分布檢測、塊內最大“1”游程檢測、二元推導檢測、自相關檢測、矩陣秩檢測、累加和檢測、近似熵檢測、線性復雜度檢測、 Maurer通用統計檢測、離散傅立葉檢測。
規定了商用密碼應用中的隨機性檢測指標和檢測方法,適用於對隨機數發生器產生的二元序列的隨機性檢測。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2/15 塊內頻數檢測
a) 將待檢序列 ε 分成 N = |n/m| 個長度為 m 的非重疊子序列,將多余的比特舍棄。本規范取m =100 。
b) 計算每個子序列中1所占的比例
c) 計算統計量
d) 計算
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)