线性同余发生器题

线性同余发生器密码解题

题目

贴出原题

线性同余发生器题_第1张图片

解题思路

  • 根据题目我们可以看出,这道题目有几点需要注意。
  • 第一:用线性同余发生器产生一个随机数字串,题目已经给出了4个随机数,可以初步判定是前四个随机数,因此我们需要根据这四个数来生成后面的随机数,用以随机数作偏移产生明文;
  • 第二:密文格式,可以明显看出是ASCII值,因此也相当于个变异凯撒;
  • 第三:同时要注意flag格式问题,可以看出最后flag只有27位,而密文有31位。

解题过程

1. 根据已知四位随机数求解变量:

  • 线性同余发生器的公式:

线性同余发生器题_第2张图片

  • a,c,m的方法有两种,一个是数学求解,另一个是爆破。两种方法都很简单。
  • 数学求解可以通过已知的四个随机数,列得三个方程,彼此相减消元,得到一个只有模数m变量的方程,得出结果,但得到的结果不唯一,由线性同余发生器的公式可知,a和m都是素数,因此求出最大公因子是181。已知m后,随意带入一个方程,求乘法逆元,得出a和b,但可以解出许多种,仔细观察相差都是模m的倍数,相当于这些数得出的结果都是一样的,随意取一个,a为17,b为102
  • 爆破的方法直接贴代码:
def is_prime(n):
    while True:
        for i in range(2,n):
            if n%i==0:
                return False
        return True
def xxx():#解出a和m
    x = []
    for i in range (1,10000):
        for j in range(1,10000):
            if ((-73*i)%j == 26 and (26*i)%j == 80 and (-47*i)%j == 106 and is_prime(i) and is_prime(j)):
                x.append((i,j))
    return x
def xxx1():#解出可能的a和b
    x = []
    for i in range (1,10000):
        for j in range(1,10000):
            if ((100*i+j)%181 == 173 and (173*i+j)%181 == 147 and (147*i+j)%181 == 67 and is_prime(i) ):
                x.append((i,j))
    return x

这里m直接解出一个值,就是181,但a和b有多种可能,但仔细观察可以看出,不同的(a,b)组合之间相差都是181的倍数。也可以找出a和b。

2.生成后续随机数

  • 根据公式直接生成之后的随机数
def cr41(sed,a,b,c,d):#d是生成随机数的个数
    key = np.zeros(d+4,dtype=int)
    key[0] = sed
    for i in range(1,d+4):
        key[i] = (a*key[i-1] + b) % c
    return key
  • 得到之后的随机数
    线性同余发生器题_第3张图片

3.进行解密

  • 根据算出的随机数对密文进行偏移 得到:
    在这里插入图片描述

  • 可以看出flag中带有英文单词,百度一下,是

需要_变异_凯撒
  • 明显这不是最终的flag。
  • 但看到提示的flag总共只有27位,而密文有31位差四位,而flag到need_variation_caeser有5个乱码字符‘afZ_r’,那去掉flag,不正好有27位了吗,那说明密文的flag的就是从我们现在解密的明文第五个字符开始,也就是说,明文 ‘flag{’ 对应的是解密出来的 ‘afZ_r’,算出对应的偏移量,是 ‘5,6,7,8,9’,说明这的确是一个变异凯撒。
  • 变异凯撒就简单了。得到最后的密文flag{xpqqmq{~w|}

完结

你可能感兴趣的:(密码)