【2022 第五空间】5_vgcd WriteUP

5_vgcd

题目:

from random import getrandbits, seed
from Crypto.Util.number import getPrime, inverse, bytes_to_long, isPrime
from os import urandom
from secret import flag

def sample(rho, eta, gamma, p):
    seed(urandom(8))
    return p * getrandbits(gamma - eta) + getrandbits(rho)

def gen_vector(rho, eta, gamma, m, p, K):
    v = vector([sample(rho, eta, gamma, p) for i in range(m)])
    return K*v 
    
rho = 6
m = 3
eta = 288
gamma = 512
p = getPrime(gamma)
q = getPrime(gamma)
n = p * q
e = 65537
phi = (p - 1) * (q - 1)
c = pow(bytes_to_long(flag), e, n)
print(n)
print(c)

pp = p >> (gamma - eta)
assert isPrime(pp)
K = Matrix.random(Integers(pp), m, m).lift()
t1 = [gen_vector(rho, eta, gamma, m, pp, K) for i in range(1024)]
print(t1)
for i in range(4):
    t2 = [gen_vector(rho, eta, gamma, m, pp, K) for i in range(512)]
    print(t2)

思路分析:

第一部分

K ∗ v = ( k 0 k 1 k 2 k 3 k 4 k 5 k 6 k 7 k 8 ) ∗ ( s 0 s 1 s 2 ) = ( s 0 ∗ k 0 + s 1 ∗ k 1 + s 2 ∗ k 2 s 0 ∗ k 3 + s 1 ∗ k 4 + s 2 ∗ k 5 s 0 ∗ k 6 + s 1 ∗ k 7 + s 2 ∗ k 8 ) \begin{array}{ll}K*v\\= \begin{pmatrix} k_0 & k_1 & k_2\\ k_3 & k_4 & k_5\\ k_6 & k_7 & k_8\\ \end{pmatrix}* \begin{pmatrix} s_0 & s_1 & s_2 \end{pmatrix}\\= \begin{pmatrix} s_0*k_0+s_1*k_1+s_2*k_2 & s_0*k_3+s_1*k_4+s_2*k_5 & s_0*k_6+s_1*k_7+s_2*k_8 \end{pmatrix}\end{array} Kv= k0k3k6k1k4k7k2k5k8 (s0s1s2)=(s0k0+s1k1+s2k2s0k3+s1k4+s2k5s0k6+s1k7+s2k8)

这是一个gen_vector的输出

其中 s 0 , s 1 , s 2 s_0,s_1,s_2 s0,s1,s2

def sample(p:'288 bit'):
    seed(urandom(8))
    return p * getrandbits(224) + getrandbits(6)

sample函数的输出,每一个都不一样

r 224 r_{224} r224 为244 bit的随机数, r 6 r_6 r6 同理

K ∗ v K*v Kv 的第一个值为例,将 p p p 提出,为
( r 224 ∗ k 0 + r 224 ∗ k 1 + r 224 ∗ k 2 ) ∗ p + ( r 6 ∗ k 0 + r 6 ∗ k 1 + r 6 ∗ k 2 ) (r_{224}*k_0+r_{224}*k_1+r_{224}*k_2)*p+(r_6*k_0+r_6*k_1+r_6*k_2) (r224k0+r224k1+r224k2)p+(r6k0+r6k1+r6k2)
注意到其中的rho=6,范围较小,即上式第二项一共只有 2 18 2^{18} 218 种情况

而一共给了 4096 4096 4096 个输出,代一下生日悖论的公式 P = 1 − e − n ∗ ( n − 1 ) 2 N P=1-e^{-\frac{n*(n-1)}{2N}} P=1e2Nn(n1),必然会有 18 b i t 18bit 18bit 的 3 个 r 6 r_6 r6 都相同的情况。

但这还不够

通过上式的第一部分以及题目的标题,不难看出要找到碰撞的情况,消去 r 6 r_6 r6 后,使用 gcd 求出 pp 的值,但是只有这 18bit 的碰撞还不够,因为两个碰撞了相减后只有一个数,要再找一组碰撞,减出一个数后跟这个数 gcd才行

懒得算概率了,跑一跑就知道有没有结果了

output.txt 的内容提取出后,d 中有 4096 组长度为3的元组,代表所有gen_vector 的输出

psb = set()
for i in trange(len(d)):
     for j in range(i+1,len(d)):
         a = [d[i][k]-d[j][k] for k in range(3)]
         gg = lambda m,n:gcd(a[m],a[n])
         g = [gg(0,1),gg(0,2),gg(2,1)]
         for k in g:
             if k.bit_length() == 288:
                 psb.add(k)

遍历每两个输出,分别计算第一项,第二项和第三项的差值,并两两计算 gcd,如果 gcd 的结果为 288bit 长度,则认为这是一个候选p,添加到 psb = set()

遍历完成后,结果是正好找到了1个候选pp

第二部分

pp和p的关系是pp = p >> (gamma - eta),这里是直接套Factoring with high bits known攻击即可

这里贴上ctf wiki的链接 https://ctf-wiki.org/crypto/asymmetric/rsa/rsa_coppersmith_attack/#factoring-with-high-bits-known
或者直接搜也能搜到很多帖子

用sage的small_roots函数得到p的低位,和pp相加得到完整 p,通过RSA解密直接得到flag
在这里插入图片描述

顺便吐槽一下玄学的beta
在这里插入图片描述

完整代码

from Crypto.Util.number import *
from math import gcd
from tqdm import *

o = [eval(i) for i in open('D:\\Desktop\\pace\\output6.txt').read().strip().split('\n')]
n = o[0]
c = o[1]
e = 0x10001
d = []
for i in o[2:]:
    for j in i:
        d.append(j)
PR.<x> = PolynomialRing(Zmod(n))
psb = set()

            
for i in trange(len(d)):
     for j in range(i+1,len(d)):
         a = [d[i][k]-d[j][k] for k in range(3)]
         gg = lambda m,n:gcd(a[m],a[n])
         g = [gg(0,1),gg(0,2),gg(2,1)]
         for k in range(len(g)):
             if g[k].bit_length() == 288:
                 psb.add(g[k])

psb = list(psb)

for pp in psb:
    f = x + (pp<<224)
    r = f.small_roots(X=2^224,beta=0.4)
    try:
        p = int(r[0] + (pp<<224))
        q = n // p
        assert(p*q == n)
        phin = p*q-p-q+1
        d = inverse(e,phin)
        print(bytes.fromhex(hex(pow(c,d,n))[2:]))
    except:
        pass

# b'flag{...}'
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值