math_stream(线性方程)

encrypt

from Crypto.Util.number import isPrime, getPrime, bytes_to_long
from random import randint

flag = b'DASCTF{********************************}'

def generate():
    n = getPrime(1024)
    a, c = randint(1, n), randint(1, n)
    b = a + 1
    return a, b, c, n


def get_stream(target):
    stream = []
    for i in range(target + 1):
        if i < 2:
            t = randint(1, n)
            stream.append(t)
        else:
            stream.append((a * stream[i - 2] + b * stream[i - 1] + c) % n)
        if i > 300 and i < 307:
            print(stream[i])
    return stream

target = 2**1024
a, b, c, n = generate()
print((a,b,c,n))
stream = get_stream(target)

plain = bytes_to_long(flag)
cipher = plain ^ stream[target]

print(cipher)

decrypt

这道题目首先需要还原模数n,考虑到在还原n的时候a,b,c的值并不知道,于是需要消去未知数a,b,c.
记题目给我们的六个已知的数分别为x1,x2,x3,x4,x5,x6
于是可以得到六个方程:
x3=ax1+bx2+c
x4=ax2+bx3+c
x5=ax3+bx4+c
x6=ax4+bx5+c
题目告诉了我们b=a+1
于是可以得到:
x3=a(x1+x2)+x2+c
x4=a(x2+x3)+x3+c
x5=a(x3+x4)+x4+c
x6=a(x4+x5)+x5+c
本着消参的原则,先消去c.,并且尽可能保留较多不冗余的方程.
(x4-x3)=a(x3-x1)+(x3-x2)
(x5-x4)=a(x4-x2)+(x4-x3)
(x6-x5)=a(x5-x3)+(x5-x4)
把右边常数移过去即:
x4-2x3+x2=a(x3-x1)
x5-2x4+x3=a(x4-x2)
x6-2x5+x4=a(x5-x3)
对于系数a的消去,可以采用通分的方式:
(x4-2x3+x2)(x4-x2)=a(x3-x1)(x4-x2)…1
(x5-2x4+x3)(x3-x1)=a(x4-x2)(x3-x1)…2
(x5-2x4+x3)(x5-x3)=a(x4-x2)(x5-x3)…3
(x6-2x5+x4)(x4-x2)=a(x5-x3)(x4-x2)…4
通过1-2 和 3-4
可以得到两个等于0的方程:
记为:
t=0 mod n
s=0 mod n
于是:
t=k1n
s=k2n
就可以通过求最大公因数得到kn,并尝试分解并与x系列的值进行比较从而得到n
在得到n后自然就可以很轻松得到 a,b,c的值了.
接下来就是构造矩阵乘法.(保证一边是已知矩阵)

x2 x1   1            b  1 0      x3  x2  1
0   0   0       *    a  0 0   =  0    0  0
0   0   0            c  0 1      0    0  0

于是就可以通过矩阵快速幂得到stream[target]的值.从而得到原文.(开一次stream[target]根)

你可能感兴趣的:(其他类型)