64 lines
1.7 KiB
Python
Executable File
64 lines
1.7 KiB
Python
Executable File
import argparse
|
|
import sys
|
|
|
|
from math import gcd
|
|
|
|
sys.setrecursionlimit(1500)
|
|
|
|
parser = argparse.ArgumentParser(description='RSA Common modulus attack')
|
|
required_named = parser.add_argument_group('required named arguments')
|
|
required_named.add_argument('-n', '--modulus', help='Common modulus', required=True)
|
|
required_named.add_argument('-e1', '--e1', help='First exponent', required=True)
|
|
required_named.add_argument('-e2', '--e2', help='Second exponent', required=True)
|
|
required_named.add_argument('-ct1', '--ct1', help='First ciphertext', required=True)
|
|
required_named.add_argument('-ct2', '--ct2', help='Second ciphertext', required=True)
|
|
|
|
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):
|
|
g, x, y = egcd(a, m)
|
|
if g != 1:
|
|
raise ValueError('Modular inverse does not exist.')
|
|
else:
|
|
return x % m
|
|
|
|
def attack(c1, c2, e1, e2, N):
|
|
if gcd(e1, e2) != 1:
|
|
raise ValueError("Exponents e1 and e2 must be coprime")
|
|
s1 = modinv(e1,e2)
|
|
s2 = int((gcd(e1,e2) - e1 * s1) / e2)
|
|
temp = modinv(c2, N)
|
|
m1 = pow(c1,s1,N)
|
|
m2 = pow(temp,-s2,N)
|
|
return (m1 * m2) % N
|
|
|
|
def main():
|
|
args = parser.parse_args()
|
|
n = int(args.modulus, 16)
|
|
ct1 = int(args.ct1, 16)
|
|
ct2 = int(args.ct2, 16)
|
|
e1 = int(args.e1, 16)
|
|
e2 = int(args.e2, 16)
|
|
print(n)
|
|
print(ct1)
|
|
print(ct2)
|
|
print(e1)
|
|
print(e2)
|
|
print('[+] Started attack...')
|
|
try:
|
|
message = attack(ct1, ct2, e1, e2, n)
|
|
print('[+] Attack finished!')
|
|
print(type(message))
|
|
print('\nPlaintext message:\n%s' % format(message, 'x'))
|
|
except Exception as e:
|
|
print('[+] Attack failed!')
|
|
print(e.message)
|
|
|
|
main()
|
|
|