b00tl3gRSA3
This is a simple challenge about RSA. The challenge gives you a hint about what is wrong about this implementation of RSA
Why use p and q when I can use more?
Let’s Recap:
RSA is a public-key cryptosystem based on the difficulty of the Factoring Problem, which is computationally hard. The RSA algorithm uses two large, randomly chosen prime numbers, and , and multiplies them together to generate a composite number , which will be used in both the public and private key.
Alice will compute Euler’s totient function , where . Since in this scenario with primes, we have .
Euler's TheoremLet be a positive integer. If , then .
If is a prime, then it follows from Fermat’s Little Theorem. Otherwise, assume is a composite number and take
The public exponent has become a de facto standard in RSA, mostly because it’s relatively small prime number and a Fermat Number , which ensures that it is coprime with for most of choices os , and the private-key is the multiplicative inverse of on the quotient ring .
Bob receives from Alice the pair and encrypts the message , after that Alice decrypts it using Euler’s Thereom simply by computing .
Solve:
Once we connect to nc jupiter.challenges.picoctf.org 51575, the tuple is displayed on the screen. My first idea was to try factoring , since once we know its prime factors, we can compute , and then determine the private key such that .
To do this, I used Sage’s implementation of the Lenstra Elliptic Curve Factorization algorithm, which runs in sub-exponational time. Then, I iteratively computed the product for each of the prime factors to obtain .
From there, recovering the original message is pretty straightforward — and just like that, we get the flag.
picoCTF{too_many_fact0rs_0731311}
Code implementation:
import socket
import re
from Crypto.Util.number import long_to_bytes
host = 'jupiter.challenges.picoctf.org'
port = 51575
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
data = sock.recv(1024).decode()
numbers = re.findall(r':\s*(\d+)', data)
c, n, e = int(numbers[0]), int(numbers[1]), int(numbers[2])
sock.close()
factors = ecm.factor(n)
phi = 1
for factor in factors:
phi *= (factor-1)
d = pow(e, -1, phi)
long_to_bytes(pow(c,d,n))

just a CS major interested in cryptography.