二元LCG
题目:
from secret import flag
assert flag[:5] == b'cazy{'
assert flag[-1:] == b'}'
flag = flag[5:-1]
assert (len(flag) == 24)
class my_LCG:
def __init__(self, seed1, seed2):
self.state = [seed1, seed2]
self.n = getPrime(64)
while 1:
self.a = bytes_to_long(flag[:8])
self.b = bytes_to_long(flag[8:16])
self.c = bytes_to_long(flag[16:])
if self.a < self.n and self.b < self.n and self.c < self.n:
break
def next(self):
new = (self.a * self.state[-1] + self.b * self.state[-2] + self.c) % self.n
self.state.append(new)
return new
def main():
lcg = my_LCG(getRandomInteger(64), getRandomInteger(64))
print("data = " + str([lcg.next() for _ in range(5)]))
print("n = " + str(lcg.n))
if __name__ == "__main__":
main()
# data = [2626199569775466793, 8922951687182166500, 454458498974504742, 7289424376539417914, 8673638837300855396]
# n = 10104483468358610819
解题思路:
- 二元LCG就是多了一组生成器,解题思路和一元一样,还是推出相关等式
- tmp[1] = data[1] - data[0]
tmp[2] = data[2] - data[1]
tmp[3] = data[3] - data[2]
tmp[4] = data[4] - data[3]
data[2] = (a * data[1] + b * data[0] + c) % n
data[3] = (a * data[2] + b * data[1] + c) % n
data[4] = (a * data[3] + b * data[2] + c) % n
- tmp[3] = (a * tmp[2] + b * tmp[1]) % n ①
tmp[4] = (a * tmp[3] + b * tmp[2]) % n ②
- ①式 × tmp[2] - ②式 × tmp[1]
解答:
import gmpy2
from Crypto.Util.number import *
data = [2626199569775466793, 8922951687182166500, 454458498974504742, 7289424376539417914, 8673638837300855396]
n = 10104483468358610819
tmp = [0]
for i in range(1,5):
tmp.append(data[i] - data[i-1])
a = ((tmp[3] * tmp[2] - tmp[4] * tmp[1]) * gmpy2.invert(tmp[2] * tmp[2] - tmp[3] * tmp[1],n)) % n
b = ((tmp[3] - a * tmp[2]) * gmpy2.invert(tmp[1],n)) % n
c = (data[2] - a * data[1] - b * data[0]) % n
print(b'cazy{' + long_to_bytes(a) + long_to_bytes(b) + long_to_bytes(c) + b'}')
#cazy{L1near_Equ4t1on6_1s_34sy}
ai一把梭
AI思路:
代码功能分析
**my_LCG**
类- 初始化 (
**__init__**
方法):- 接收两个初始种子
seed1
和seed2
,并将其存储到self.state
列表中 - 随机生成一个 64 位的素数
n
,作为模数 - 从
flag
中提取三个参数a
、b
和c
,并确保它们小于n
a
来自flag
的前 8 字节b
来自flag
的第 8 到第 16 字节c
来自flag
的第 16 到第 24 字节
- 接收两个初始种子
- 生成下一个随机数 (
**next**
方法):- 根据线性同余公式计算新的随机数:new=(a⋅state[−1]+b⋅state[−2]+c) mod n
- 将新生成的随机数追加到
self.state
列表中,并返回该值
- 初始化 (
**main**
函数- 创建一个
my_LCG
实例,初始种子为两个随机的 64 位整数 - 生成 5 个随机数并打印出来
- 打印模数
n
- 创建一个
- 已知输出
- 已知生成的 5 个随机数:
- data=[2626199569775466793,8922951687182166500,454458498974504742,7289424376539417914,8673638837300855396]
- 模数:n=10104483468358610819
正确的分析和求解过程
我们需要从已知的线性同余方程组中解出 a、b 和 c,已知的方程组如下:
x3=(a⋅x2+b⋅x1+c) mod n
x4=(a⋅x3+b⋅x2+c) mod n
x5=(a⋅x4+b⋅x3+c) mod n
其中:
- x1=2626199569775466793
- x2=8922951687182166500
- x3=454458498974504742
- x4=7289424376539417914
- x5=8673638837300855396
- n=10104483468358610819
正确的求解步骤
- 建立方程组
- 从第一个方程:x3=(a⋅x2+b⋅x1+c) mod n
- 从第二个方程:x4=(a⋅x3+b⋅x2+c) mod n
- 从第三个方程:x5=(a⋅x4+b⋅x3+c) mod n
- **消去 **c
- 从第一个方程中解出 c:c=(x3−a⋅x2−b⋅x1) mod n
- 将 c 代入第二个方程:x4=(a⋅x3+b⋅x2+x3−a⋅x2−b⋅x1) mod n
- 化简得:x4=(a⋅(x3−x2)+b⋅(x2−x1)+x3) mod n
- 将 c 代入第三个方程:x5=(a⋅x4+b⋅x3+x3−a⋅x2−b⋅x1) mod n
- 化简得:x5=(a⋅(x4−x2)+b⋅(x3−x1)+x3) mod n
- **求解 a 和 **b
- 从第二个方程:x4=(a⋅(x3−x2)+b⋅(x2−x1)+x3) mod n
- 重新整理:a⋅(x3−x2)+b⋅(x2−x1)=(x4−x3) mod n
- 从第三个方程:x5=(a⋅(x4−x2)+b⋅(x3−x1)+x3) mod n
- 重新整理:a⋅(x4−x2)+b⋅(x3−x1)=(x5−x3) mod n
- 线性方程组求解
- 我们得到了两个线性方程:
a⋅(x3−x2)+b⋅(x2−x1)=(x4−x3) mod n
a⋅(x4−x2)+b⋅(x3−x1)=(x5−x3) mod n
- 这是一个二元一次线性方程组,可以使用矩阵求逆或高斯消元法求解 a 和 b
from Crypto.Util.number import long_to_bytes, getPrime
from Crypto.Random import get_random_bytes
# 已知数据
data = [2626199569775466793, 8922951687182166500, 454458498974504742, 7289424376539417914, 8673638837300855396]
n = 10104483468358610819
# 提取已知值
x1, x2, x3, x4, x5 = data
# 建立方程组
# a * (x3 - x2) + b * (x2 - x1) = (x4 - x3) % n
# a * (x4 - x2) + b * (x3 - x1) = (x5 - x3) % n
# 系数矩阵
A = [
[x3 - x2, x2 - x1],
[x4 - x2, x3 - x1]
]
# 常数向量
B = [
(x4 - x3) % n,
(x5 - x3) % n
]
# 求解线性方程组
def matrix_inverse(A, n):
det = (A[0][0] * A[1][1] - A[0][1] * A[1][0]) % n
det_inv = pow(det, -1, n)
inv_A = [
[A[1][1], -A[0][1]],
[-A[1][0], A[0][0]]
]
for i in range(2):
for j in range(2):
inv_A[i][j] = (inv_A[i][j] * det_inv) % n
return inv_A
# 计算矩阵的逆
inv_A = matrix_inverse(A, n)
# 求解 a 和 b
a = (inv_A[0][0] * B[0] + inv_A[0][1] * B[1]) % n
b = (inv_A[1][0] * B[0] + inv_A[1][1] * B[1]) % n
# 求解 c
c = (x3 - a * x2 - b * x1) % n
# 转换为字节形式
flag = b'cazy{' + long_to_bytes(a, 8) + long_to_bytes(b, 8) + long_to_bytes(c, 8) + b'}'
print(flag)
#cazy{L1near_Equ4t1on6_1s_34sy}