随机数检测(二)

随机数检测(二)- 扑克检测、重叠子序列、游程总数、游程分布

3.4 扑克检测方法

扑克检测方法如下图。
扑克检测方法

以下实现代码供参考。

def alterOffsetBit(m, offset, listSub:list):
    ret = []
    listSub[offset] = 0
    if offset == (m-1):
        ret.append(listSub.copy())
    else: 
        ret += (alterOffsetBit(m, offset+1, listSub))

    listSub[offset] = 1
    if offset == (m-1):
        ret.append(listSub.copy())
    else: 
        ret += (alterOffsetBit(m, offset+1, listSub))
    return ret
    

def seedSequence(m):
    sequencelist = [0]*m
    return alterOffsetBit(m, 0, sequencelist)

#get poker param, follow GM/T 0005-2021 appendix A
def getpokerM(len):
    if len < 20000:
        m = [2]
    else:
        m = [4, 8]
    return m    

def poker(epsilon:bitarray, m):
    seedList = seedSequence(m)
    listNi = [0]*(2**m)
    N = int(len(epsilon)/m)
    epsilonList = epsilon.tolist()
    for i in range(N):
        listNi[seedList.index(epsilonList[i*m:(i+1)*m:1])] += 1
    sum = 0
    for i in range(2**m):
        sum += listNi[i]**2
    V = (2**m)*sum/N - N
    pvalue = scipy.special.gammaincc((2**m - 1)/2, V/2)
    qvalue = pvalue
    return {'p':pvalue, 'q':qvalue}

3.5 重叠子序列检测方法

重叠子序列检测方法如下图。
重叠子序列
重叠子序列2
以下实现代码供参考。

#get serial param, follow GM/T 0005-2021 appendix A
def getserialM(len):
    if len < 20000:
        m = [2]
    elif len < 100000000:
        m = [3, 5]
    else:
        m = [3, 5, 7]
    return m    

def alterOffsetBit(m, offset, listSub:list):
    ret = []
    listSub[offset] = 0
    if offset == (m-1):
        ret.append(listSub.copy())
    else: 
        ret += (alterOffsetBit(m, offset+1, listSub))

    listSub[offset] = 1
    if offset == (m-1):
        ret.append(listSub.copy())
    else: 
        ret += (alterOffsetBit(m, offset+1, listSub))
    return ret
    

def seedSequence(m):
    sequencelist = [0]*m
    # print('sequencelist:' , sequencelist)
    return alterOffsetBit(m, 0, sequencelist)

def getV2(epsilonList:list, mlen):
    seedList = seedSequence(mlen)
    # print(seedList)
    V = [0] * (2**mlen)
    for i in range(len(epsilonList)-mlen+1):
        # print(epsilonList[i:i+mlen:1])
        seedindex = seedList.index(epsilonList[i:i+mlen:1])
        V[seedindex] += 1
    for i in range(len(V)):
        V[i] = V[i]**2
    return V
def calcPhym(epsilonlist:list, m):
    if m <= 0:#phy0 and phy-1 is 0
        return 0
    prefixM = epsilonlist[:m-1:1]

    n = len(epsilonlist)
    epsilonlist += prefixM

    Vm = getV2(epsilonlist, m)
    return (2**m)*sum(Vm)/n - n

def serial(epsilon:bitarray, m):

    # n = int(len(epsilon))
    epsilonList = epsilon.tolist()
    phym2 = calcPhym(epsilonList, m)
    phym_12 = calcPhym(epsilonList, m-1)
    phym_22 = calcPhym(epsilonList, m-2)

    deltaPhyM2 = phym2 - phym_12
    delta2PhyM2 = phym2 - 2*phym_12 + phym_22

    pvalue1 = scipy.special.gammaincc(2**(m-2), deltaPhyM2/2)
    pvalue2 = scipy.special.gammaincc(2**(m-3), delta2PhyM2/2)
    qvalue1 = pvalue1
    qvalue2 = pvalue2
    return {'p1':pvalue1, 'q1':qvalue1, 'p2':pvalue2, 'q2':qvalue2}

3.6 游程总数检测

游程总数检测方法如下图。
游程总数检测
游程总数检测2
以下实现代码供参考。

def runs(epsilon:bitarray):
    n = int(len(epsilon))
    epsilonList = epsilon.tolist()
    Vn = 1
    for i in range(int(len(epsilonList))-1):
        #r.append([1,0][epsilonList[i] == epsilonList[i+1]])
        if epsilonList[i] != epsilonList[i+1]:
            Vn += 1

    pi = sum(epsilonList)/n

    if abs(pi - 0.5) > (2.0 / sqrt(n)):
        pvalue = 0.0
        print('runs Test Failed : pvalue ', pvalue)
        return 1
    
    pvalue = math.erfc(abs(Vn-2*n*pi*(1-pi))/(2*sqrt(2*n)*pi*(1-pi)))
    qvalue = math.erfc((Vn-2*n*pi*(1-pi))/(2*sqrt(2*n)*pi*(1-pi)))/2
    return {'p':pvalue, 'q':qvalue}

3.7 游程分布检测

游程分布检测方法如下图。
游程分布
以下实现代码供参考。

def runsDistribution(epsilon:bitarray):

    n = int(len(epsilon))
    epsilonList = epsilon.tolist()
    e = []
    for i in range(1,int(len(epsilonList)+1)):
        e.append((n-i+3)/(2**(2+i)))
        if e[i-1] >= 5:
            k = i 
        else:
            break;

    gi = [0]*n
    bi = [0]*n
    runFlag = epsilonList[0]
    j = 1
    for i in range(1, n):
        if epsilonList[i] != runFlag:
            if runFlag == 0x00:
                gi[j - 1] += 1
            else:
                bi[j - 1] += 1
            runFlag = epsilonList[i]
            j = 1
        else:
            j += 1
    #GM/T 0005-2021 demands add all subfix to bk and gk
    bi[14] = sum(bi[14:len(bi)])
    gi[14] = sum(gi[14:len(gi)])
    #calc T
    T = 0
    for i in range(k):
        T += bi[i] + gi[i]
    #calc e'
    epie = [T/(2**(i+1)) for i in range(1, k+1)]
    epie[k-1] = T/(2**k)
    #calc V
    
    V1 = []
    V2 = []
    for i in range(k):
       V1.append(((bi[i] - epie[i])**2)/epie[i])
       #V1.append((bi[i] - e[i])**2/e[i])
    for i in range(k):
       V2.append(((gi[i] - epie[i])**2)/epie[i])
       #V2.append((gi[i] - e[i])**2/e[i])

    V = sum(V1) + sum(V2)
    pvalue = scipy.special.gammaincc(k-1, V/2)
    qvalue = pvalue
    return {'p':pvalue, 'q':qvalue}

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

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值