Skip to content

Commit 5acf41c

Browse files
author
root
committed
Added solver when n is prime. Fixed URL to factordb. Closes RsaCtfTool#54 and closes RsaCtfTool#55
1 parent c06454b commit 5acf41c

File tree

1 file changed

+41
-5
lines changed

1 file changed

+41
-5
lines changed

RsaCtfTool.py

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
from Crypto.PublicKey import RSA
1616
import signal
1717
import gmpy2
18+
19+
from Crypto.Util.number import bytes_to_long, long_to_bytes
20+
1821
from rsalibnum import *
1922
import requests
2023
from requests.packages.urllib3.exceptions import InsecureRequestWarning
@@ -136,6 +139,7 @@ def __init__(self, args):
136139
self.pubkeyfile = args.publickey
137140
self.pub_key = PublicKey(key)
138141
self.priv_key = None
142+
self.partitial_priv_key = None
139143
self.displayed = False # have we already spammed the user with this private key?
140144
self.args = args
141145
self.unciphered = None
@@ -210,12 +214,32 @@ def solveforp(equation):
210214

211215
# Factors available online?
212216
try:
213-
url_1 = 'https://factordb.com/index.php?query=%i'
214-
url_2 = 'https://factordb.com/index.php?id=%s'
217+
url_1 = 'http://factordb.com/index.php?query=%i'
218+
url_2 = 'http://factordb.com/index.php?id=%s'
215219
s = requests.Session()
216220
r = s.get(url_1 % self.pub_key.n, verify=False)
217221
regex = re.compile("index\.php\?id\=([0-9]+)", re.IGNORECASE)
218222
ids = regex.findall(r.text)
223+
# check if only 1 factor is returned
224+
if len(ids) == 2:
225+
# theres a chance that the only factor returned is prime, and so we can derive the priv key from it
226+
regex = re.compile("<td>P<\/td>")
227+
prime = regex.findall(r.text)
228+
if len(prime) == 1:
229+
# n is prime, so lets get the key from it
230+
d = invmod(self.pub_key.e, self.pub_key.n - 1)
231+
# construct key using only n and d
232+
try:
233+
# pycrypto >=2.5
234+
impl = RSA.RSAImplementation(use_fast_math=False)
235+
self.partitial_priv_key = impl.construct((self.pub_key.n, 0L))
236+
self.partitial_priv_key.key.d = d
237+
except TypeError:
238+
# pycrypto <=2.4.1
239+
self.partitial_priv_key = RSA.construct((self.pub_key.n, 0L, d))
240+
241+
return
242+
219243
p_id = ids[1]
220244
q_id = ids[2]
221245
# bugfix: See https://github.com/sourcekris/RsaCtfTool/commit/16d4bb258ebb4579aba2bfc185b3f717d2d91330#commitcomment-21878835
@@ -533,10 +557,16 @@ def attack(self):
533557
getattr(self, attack.__name__)()
534558

535559
# check and print resulting private key
536-
if self.priv_key is not None:
560+
if self.priv_key is not None or self.partitial_priv_key is not None:
537561
if self.args.private and not self.displayed:
538-
print(self.priv_key)
562+
if self.priv_key is not None:
563+
print(self.priv_key)
564+
else:
565+
print("d: %i" % self.partitial_priv_key.key.d)
566+
print("e: %i" % self.partitial_priv_key.key.e)
567+
print("n: %i" % self.partitial_priv_key.key.n)
539568
self.displayed = True
569+
540570
break
541571

542572
if self.unciphered is not None:
@@ -546,13 +576,19 @@ def attack(self):
546576
if self.cipher and self.priv_key is not None:
547577
self.unciphered = self.priv_key.decrypt(self.cipher)
548578
print("[+] Clear text : %s" % str(self.unciphered))
579+
elif self.cipher and self.partitial_priv_key is not None:
580+
# needed, if n is prime and so we cant calc p and q
581+
enc_msg = bytes_to_long(self.cipher)
582+
dec_msg = self.partitial_priv_key.key._decrypt(enc_msg)
583+
self.unciphered = long_to_bytes(dec_msg)
584+
print("[+] Clear text : %s" % str(self.unciphered))
549585
elif self.unciphered is not None:
550586
print("[+] Clear text : %s" % str(self.unciphered))
551587
else:
552588
if self.cipher is not None and self.args.attack is None:
553589
print("[-] Sorry, cracking failed")
554590

555-
if self.priv_key is None and self.args.private:
591+
if self.priv_key is None and self.partitial_priv_key is None and self.args.private:
556592
print("[-] Sorry, cracking failed")
557593

558594
implemented_attacks = [nullattack, hastads, factordb, pastctfprimes,

0 commit comments

Comments
 (0)