# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   File Name :      p_leak_attack
   Description :
   Author :         x3nny
   date :           2021/7/18
-------------------------------------------------
   Change Activity:
                    2021/7/18: Init
-------------------------------------------------
"""


# This file was *autogenerated* from the file p_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)
from Crypto.Util.number import *

def high_p_leak(pbar, n, bits):
    PR = PolynomialRing(Zmod(n), names=('x',)); (x,) = PR._first_ngens(1)
    f = x + pbar
    roots = f.small_roots(X=_sage_const_2 **bits, beta=_sage_const_0p4 ) # find root < 2^kbits with factor >= n^0.4
    if not roots:
        return None, None
    p = int(roots[_sage_const_0 ]+pbar)
    return p, n // p

def low_p_leak(pbar, n, bits):
    PR = PolynomialRing(Zmod(n), names=('x',)); (x,) = PR._first_ngens(1)
    ZmodN = Zmod(n)
    f = x*ZmodN(power(_sage_const_2 , pbar.bit_length())) + pbar
    f = f.monic()
    roots = f.small_roots(X=_sage_const_2 **bits, beta=_sage_const_0p4 ) # find root < 2^kbits with factor >= n^0.4
    if not roots:
        return None, None
    p = roots[_sage_const_0 ]+pbar
    return p, n // p

def attack(pbar, n, bits=None):
    if bits is None:
        bits = (n.bit_length() // _sage_const_2 ) - pbar.bit_length()
    p,q = high_p_leak(pbar, n, bits)
    if p is None:
        return low_p_leak(pbar, n, bits)
    return p, q

