Lattice练习
题目:
from Crypto.Util.number import *
flag = b'******'
m = bytes_to_long(flag)
p = getPrime(512)
s = [getPrime(32) for i in range(3)]
a = [getPrime(512) for i in range(3)]
c = (a[0]*s[0]**2*s[1]**2 + a[1]*s[0]*s[2]**2 + a[2]*s[1]*s[2]) % p
flag = m*s[0]*s[1]*s[2]
print(f'c = {c}')
print(f'flag = {flag}')
print(f'a = {a}')
print(f'p = {p}')
拿来检测Lattice的学习效果还是不错的。
先拿关系式:
c=a0s02s12+a1s0s22+a2s1s2+kp
enc=ms0s1s2
分析已知和未知条件:
已知 | 未知 |
---|---|
ai | si |
c,p,enc |
思路就是求出s0,s1,s2的值。
处理这种关系式,为了简化式子,我们选择把次数少的拎出来:
a2s1s2=c−a0s02s12−a1s0s22+kp
把系数变成1:
s1s2=a2−1c−a2−1a0s02s1−a2−1a1s0s2+kp
然后就可以构造格了:
L=100001000010−a0a2−1−a1a2−1ca2−1p
这样就有:
(s02s12,s0s22,1,k)L=(s02s12,s0s22,1,s1s2)=v
看看长度:
∣∣v∣∣=∣s02s12∣2+∣s0s22∣2+12+∣s1s2∣2≈2129>∣p∣1/4=2128
显然这规约不了一点,但是我们可以将对角线配平,这样会好一点。
目前向量v的对角线大小为:
(128,96,1,64)
我们就乘上这样一个矩阵:
M=10000232000021280000264
这样,
∣∣v∗M∣∣=2130<∣232+128+64p∣1/4=2184
就可以规约出来了。
exp:
from Crypto.Util.number import *
c =
flag =
a = []
p =
ia = inverse_mod(a[2], p)
L = Matrix(ZZ, [[1, 0, 0, -a[0]*ia%p],
[0, 1, 0, -a[1]*ia%p],
[0, 0, 1, c*ia%p],
[0, 0, 0, p]])
L *= diagonal_matrix(ZZ, [1, 2^32, 2^128, 2^64])
v = L.LLL()[0]
s0s1 = isqrt(abs(v[0]))
s1s2 = abs(v[3]) >> 64
s1 = gcd(s0s1, s1s2)
s0 = s0s1 // s1
s2 = s1s2 // s1
flag = flag // s0 // s1 // s2
print(long_to_bytes(flag))