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]根)