def partial_p(p0, kbits, n): # Ensure n is an integer (as it should be), and create the polynomial ring over Z/nZ PR.<x> = PolynomialRing(Zmod(n)) nbits = n.nbits() # Get the number of bits in n f = Integer(2)^kbits * x + Integer(p0) # Ensure all numbers are integers f = f.monic() # Make the polynomial monic # Find small roots of the polynomial try: roots = f.small_roots(X=Integer(2)**(nbits // 2 - kbits), beta=RealNumber('0.3')) except Exception as e: print(f"Error in small_roots: {e}") return None if roots: x0 = Integer(roots[0]) # Get the first root and ensure it's an integer p = gcd(Integer(2)^kbits * x0 + p0, n) # Compute gcd to find p return ZZ(p) # Return p as an integer return None def find_p(d0, kbits, e, n): X = var('X') # Define a symbolic variable X # Iterate through possible values of k for k in range(1, e + 1): # Solve the modular equation for possible values of p0 results = solve_mod([e * d0 * X - k * X * (n - X + 1) + k * n == X], 2^kbits) for x in results: p0 = ZZ(x[0]) # Convert the solution to an integer p = partial_p(p0, kbits, n) # Try to find p using partial_p if p: return p # Return p if found return None if __name__ == '__main__': n = 0xcc5b706f373a79c680cec9527aac573fd435129cf16c23334085bf97832e5a6c78b633c2f244b12a62f87ec5295dd89fcf3c808c39e45a9afdbda2f8d2d0b50d61b685c0fe9eb41a7018a40f98892f96d738e2a4e740d4e507bcbd07f68c1ecb2ca10bd780ce65265a7e4da00f1031a5db9d038878a29a5ffefcaf2119720005 e = 65537 d0 = 0x20142ae2802b877eb4dfa8a462e7d017c4d348181c367fd1a661ec9b6bbcca9dcb6601ccb6c10416b7f3c20129527346bbc136ee60f9945125cba03a9bba3720f7411 nbits = n.nbits() # Get the number of bits in n print(f"nbits: {nbits}") kbits = d0.nbits() # Number of bits in the given part of d print(f"kbits: {kbits}") print(f"lower {kbits} bits (of {nbits} bits) are given") # Attempt to find p p = find_p(d0, kbits, e, n) if p: print(f"Found p: {p}") q = n // p # Compute q print(f"Found q: {q}") private_exponent = inverse_mod(e, (p - 1) * (q - 1)) # Compute the private exponent print(f"Private exponent: {private_exponent}") else: print("Failed to find p.")