随机数安全 学习记录

本文探讨了随机数安全问题,包括开发者不使用随机数和使用弱伪随机数的风险。重点介绍了伪随机数生成器(PRNG)的工作原理,如线性同余生成器(LCG)、平方取中法以及梅森旋转算法,并讨论了它们的安全性和潜在的攻击。文章还提到了PRNG攻击,如针对LCG的攻击策略,并提及了如何预测和破解随机数生成器。
摘要由CSDN通过智能技术生成

PRNG学习记录

随机数安全

随机数安全问题主要是两种

1.开发者没有使用随机数。这里,sb才不会用随机数,当然也可能是开发者没有脑子不知道要用随机数。

2.开发者使用了弱伪随机数,导致随机数生成可以被预测。例如有些开发使用时间戳作为随机数,就很容易被预测;另外,如果seed即种子泄露,那么就相当于随机数已经泄露了,除了种子外还有一个随机数池,如果随机数池不足,那么意味着攻击者可以暴力破解。

PRNG

我们知道PRNG是伪随机数生成器,其中心的是确定的,如果我们知道其内部的完整状态,就可以对其进行预测。那么此时如果PRNG用于加密密钥或者生成签名证书时,就会存在完全问题。

PRNG:将固定值(seed)传入,并产生使用确定性的算法的输出位序列,种子是由 TPNG 生成。

PRF:用于产生一定长度固定长度的伪随机字符串,如对称加密密钥和随机数。

PRNG一般有:

1.线性同余法(例如c语言的rand库和java的java.util,Random类)

2.单向散列函数法

3.密码法

4.ANSI X9.17

平方取中法

冯诺依曼提出

基本思想是从一个随机数种子开始,对其平方,然后取中间值,然后重复对得到的数取平方并取中间值,即

1.选择m位数N(i)作为种子seed

2.取其平方数,N(i)^2

3.N(i)^2不足2m位,前面补0,选择中间m个位的数,将其作为N(i+1)

(例子:65537 —> 4295098369)

4.重复2、3

#random随机数生成(迭代取中)
import datetime
import math
import numpy as np

time=datetime.datetime.now()#时间戳
a=np.arange(100)
a0=str(time)[-6:] #取时间为随机数种子 存在安全漏洞,容易被预测
a1=str(int(a0)**2) #取seed的平方
for i in range(100): #产生随机的100位数,放在a[i]数组,即a[i]数组为随机数序列
    while(len(a1)!=len(a0)*2):#a1不足2m位,前面补0
        a1='0'+a1
    a2=a1[3:9] #取中间m位数
    j=0
    while(a2[j]=='0'): #若取出数字位数减少时,后面补0,将其恢复成m位的数,例如002756,改成275600
        a2=a2+'0'
        j=j+1
    a[i]=int(a2) #重复前面步骤
    a0=a2 
    a1=str(int(a2)**2)
print(a)
a=a/a.max()
print(a)    


#输出结果
[895982 783744 254657 850187 817934 160280 256896 995554 127766 324150
 732220 361461 654054 786634 793049 926716 802544 768710 909150 553722
 608053 728450 639402 834917 863960 464268 544775 779800 880400 751041
 625830 916631 212390 109512 992878 806722 800385 616148 638357 499659
 659116 433901 270077 941585 582312 872650 615180 446432 301530 920340
 257150 661261 266110 814532 462379 794339 974446 545006 315400 994771
 569342 150312 593697 476127 696920 697486 486720 896358 457664 456336
 242544 827591 906863 400500 400250 200062 248030 615188 456275 186875
 922265 572730 196520 386201 151212 865068 342644 404910 952108 509643
 735987 676864 144874 988475 828250 859980 565600 903360 592890 515185]
[0.89998333 0.78724409 0.25579426 0.85398381 0.82158677 0.16099579
 0.25804326 1.         0.12833658 0.32559761 0.73548999 0.36307523
 0.65697491 0.79014699 0.79659064 0.93085458 0.80612805 0.77214295
 0.91321013 0.55619484 0.61076848 0.73170315 0.64225748 0.83864562
 0.86781832 0.46634135 0.54720789 0.78328247 0.88433174 0.75439504
 0.62862487 0.92072454 0.2133385  0.11000106 0.99731205 0.8103247
 0.8039594  0.61889963 0.64120781 0.5018904  0.66205952 0.43583874
 0.27128312 0.94578998 0.58491252 0.87654713 0.6179273  0.4484257
 0.30287659 0.92445011 0.25829839 0.6642141  0.26729841 0.81816958
 0.46444392 0.7978864  0.97879773 0.54743992 0.31680853 0.9992135
 0.5718846  0.15098327 0.59634836 0.47825331 0.70003234 0.70060087
 0.48889362 0.90036101 0.45970786 0.45837393 0.24362717 0.8312869
 0.91091292 0.40228858 0.40203746 0.20095545 0.24913767 0.61793534
 0.45831266 0.18770956 0.9263837  0.57528773 0.19739763 0.38792572
 0.15188729 0.86893127 0.3441742  0.40671827 0.95635998 0.51191899
 0.73927381 0.67988678 0.14552099 0.99288939 0.83194884 0.86382055
 0.56812589 0.90739427 0.59553776 0.51748574]

以上是100个随机数的结果,如果我们将它扩展为万,十万甚至更大,并使用python可视图,我们会发现这些点在某些地方没有覆盖,任留有大片空白,那么我们可以很清楚的从图像看出,冯诺依曼的这个迭代取中的方法来生成随机数不够理想。

python plotly+jupyter

线性同余生成器(LCG)

LCG,即线性同余生成器,一种PRNG,产生伪随机数的一种算法。

其数学递推式是:

N(k+1) ≡ (A * N(k) + B ) ( mod M )

其中,A、B、M为随机数生成器确定值。

M>0 , 0<A<M , 0<= B <M , 0<=N(0)<M

当上述的递推式中B的值为0时,此时的线性同余生成器称为乘同余发生器,B>0时称为混合同余发生器。

从递推式可以看出,线性同余的递推式仅仅依赖于前一项,且随机序列只有M个可能取值,那么用该种方式产生的随机数序列必定会重复。

我们假定存在正整数n、m(m<n),使得 N(n) = N(m),那么就有 N(n) + k == N(m) + k ,那么,N(n)、N(n+1)、N(n+2)……N(m)、N(m+1)、N(m+2)……会重复,我们将n-m的最小值取为TT为该随机数发生器在初值 N(0)的周期。

T <= M,设想下假设递推公式为N(k+1) ≡ (A * N(k) + B ) ( mod M ) ,若周期为T,则N(k+T) =N(k) , 由于N(k+1) ≡ (A * N(k) + B ) ( mod M )也就是说唯一的 N(k)决定唯一的N(k+1),那么T必小于等于M,因为取模M共有M个不同的整数结果,第M+1个数一定和前面某一个数相同,而由于一一对应的递推关系,后面的序列也会依次与前面的数相同,最后必有周期T<=M

from Crypto.Util.number import *
#基本LCG
class LCG():
    def __init__(self, n0=getRandomInteger(128)):
        self.a = getPrime(128)
        self.b = getPrime(128)
        self.m = getPrime(256)
        self.n = n0

    def next(self):
        self.n = (self.n * self.a + self.b) % self.m
        print(self.n)
        return self.n

lcg = LCG()
print (lcg.next())
print (lcg.next())
print (lcg.next())
乘同余法

B=0,递推式为:

N(k+1) ≡ A * N(k) ( mod M )

我们应该选取合适的M、A,以达到满周期,且统计性质良好。首先是N(k) != 0 ,如果我们正在产生随机数时取到某个 N(k)0,则,N(k+1) = N(k+2) = …… = 0。则随机数直接进入0,并不发生周期变化,即退化情况。

通过一定的证明和推算,我们可以得出:AM互素,且MN(0)互素时,N(n) = a^n * N(0) ( mod M ),易得N(k)M 互素,这样不会出现退化的情况。

对于上述,我在这里仅仅证明A与M互质,如下

N(k+1) ≡ A * N(k) ( mod M )

如果AM不互质,那么我们可以令A = a * dM = m * d

则上诉式子变为N(k+1) = A * N(k) + k * M

(此处B=0,若B不为0,则将B当做一个偏移量,两边都减去B,即可)

N(k+1) = d * (a * N(k) + k * m)

d = 2为例,序列中原有的M个可能数字在循环中只能取到偶数值,也就是表明周期为T <= M/2

再列举一下,

A=6,M=10,N(0)=2,序列为{2,2,2,……},周期为1;

A=3,M=5,N(0)=2,序列为{2,1,3,4,2,1,……},周期为5;

混合同余发生器

此处B>0,

混合同余发生器可以达到满周期的条件

1.B 与M互素;

2.对于M的任一个素因子p,a-1 被p整除;

3.如果 4 是 M 的因子,则 a − 1 被 4 整除;

一般而言,我们取 M=2^L,L 为计算机中整数的尾数字长。这时根据上述定理,建议取 a=4α+1, b=2β+1, α 和 β 为任意正整数,N(0) 为任意非负整数,这样的混合同余发生器是满周期的,周期为 2^L

关于同余法生成的随机变量序列的均匀分布状况以及其序列前后自相关系数的一些东西,可以详康Random number统计计算

#random随机数生成(LCG)
import datetime
import math
import numpy as np
def _random():
    time=datetime.datetime.now()#时间戳
    a=np.arange(100)
    a0=str(time)[-6:] #取时间为随机数种子 存在安全漏洞,容易被预测v
    a0=int(a0)
    print("alpha=")
    alpha=int(input()) 
    print("beta=")
    beta=int(input()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值