

# This file was *autogenerated* from the file xenny/ctf/crypto/modern/asymmetric/rsa/copper_smith/d_leak_attack.sage
from sage.all_cmdline import *   # import sage library

_sage_const_2 = Integer(2); _sage_const_0p4 = RealNumber('0.4'); _sage_const_0 = Integer(0); _sage_const_1 = Integer(1)# from xenny.ctf.crypto.modern.asymmetric.rsa.copper_smith.p_leak_attack import low_p_leak

def partial_p(p0, kbits, n):
    PR = PolynomialRing(Zmod(n), 'x')
    x = PR.gen()
    nbits = n.bit_length()
    f = (_sage_const_2 **kbits)*x + p0
    f = f.monic()
    roots = f.small_roots(X=_sage_const_2 **(nbits//_sage_const_2 -kbits), beta=_sage_const_0p4 )  # find root < 2^(nbits//2-kbits) with factor >= n^0.3
    if roots:
        x0 = roots[_sage_const_0 ]
        p = gcd((_sage_const_2 **kbits)*x0 + p0, n)
        return ZZ(p)

def find_p(d0, kbits, e, n):
    X = var('X')
    for k in range(_sage_const_1 , e+_sage_const_1 ):
        results = solve_mod([e*d0*X - k*X*(n-X+_sage_const_1 ) + k*n == X], _sage_const_2 **kbits)
        for x in results:
            p0 = ZZ(x[_sage_const_0 ])
            try:
                p = partial_p(p0, kbits, n)
                # p,q = low_p_leak(p0, n, pbits)
                if p:
                    return p
            except Exception:
                pass

