Skip to content

Instantly share code, notes, and snippets.

@kezzyhko
Last active September 17, 2020 08:39
Show Gist options
  • Save kezzyhko/21a7c7d356cccfd6f4c0d99ee5f3e4f8 to your computer and use it in GitHub Desktop.
Save kezzyhko/21a7c7d356cccfd6f4c0d99ee5f3e4f8 to your computer and use it in GitHub Desktop.
The RSA common modulus attack
# Some parts of this code is taken from
# https://0day.work/how-i-recovered-your-private-key-or-why-small-keys-are-bad/
from Crypto.PublicKey import RSA
from base64 import b64decode
from binascii import unhexlify
# load keys (n, e1, e2)
key1 = RSA.importKey(open("key1_pub.pem").read())
key2 = RSA.importKey(open("key2_pub.pem").read())
if (key1.n != key2.n):
print("Public modulus are different!")
exit()
n = key1.n
e1 = key1.e
e2 = key2.e
key1 = None
key2 = None
# load messages and change their format to int
c1 = int(b64decode(open("message1").read()).hex(), 16)
c2 = int(b64decode(open("message2").read()).hex(), 16)
# define some useful functions
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
gcd, x, y = egcd(a, m)
if gcd != 1:
return None # modular inverse does not exist
else:
return x % m
# now, the attack itself
# find the linear combination of exponents
gcd, x, y = egcd(e1, e2)
assert(e1*x + e2*y == gcd)
# if x or y are negative, this will cause problems with c^x mod n
# but luckily, it can be fixed as follows:
if (x<0):
x = -x
c1 = modinv(c1, n)
if (y<0):
y = -y
c2 = modinv(c2, n)
# restore the original message
m = pow(c1, x, n) * pow(c2, y, n)
m %= n
print(unhexlify(hex(m)[2:]).decode('ascii'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment