210 lines
6.4 KiB
Python

# mallory.py, a mitm attack to learn ratchet gossip about your CSE 539 instructor
# jedimaestro@asu.edu
import secrets
import sys
import os.path
import time
import os
import re
from colorama import Fore, Back, Style
import signal
g = 10697987386528634556132351984988679277669693771233806587823166397646257882356751154924044166012048802718827287365490918762116743604708315476073224232944329
p = 21395974773057269112264703969977358555339387542467613175646332795292515764713502309848088332024097605437654574730981837524233487209416630952146448465888659
if (len(sys.argv) < 3) or sys.argv[1] == sys.argv[2]:
print("No! RTFSC!")
exit(0)
flog = open("mallorylog.txt", "w")
myname = sys.argv[1]
theirname = sys.argv[2]
imfirst = myname > theirname
if imfirst:
fn = "/tmp/" + myname + "-and-" + theirname + ".txt"
else:
fn = "/tmp/" + theirname + "-and-" + myname + ".txt"
#if os.path.isfile(fn):
# os.remove(fn)
def handler(signum, frame):
print(Style.RESET_ALL + "Ctrl-c was pressed. Exiting...")
exit(0)
signal.signal(signal.SIGINT, handler)
messagenumber = 6
leakerslatestratchet = 0
otherslatestratchet = 0
mylatestprivatekeyforleaker = 0
mylatestprivatekeyforother = 0
def otp(plainorcipher, encordec, key):
# plainorcipher is the text for plaintext or ciphertext
# encordec is "enc" to encrypt or "dec" to decrypt
# key is a large integer with hopefully enough key material
if encordec == "enc":
sign = 1
elif encordec == "dec":
sign = -1
else:
return "Bad use of bad API"
keystream = []
ki = key
while ki > 0:
keystream.append(ki % 26)
ki = int(ki / 26)
whattoreturn = ""
for i in range(len(plainorcipher)):
letter = ord(plainorcipher[i]) - ord('A')
c = (letter + keystream[i]*sign) % 26
c = c + ord('A')
whattoreturn = whattoreturn + str(chr(c))
return whattoreturn
olderlatestratchet = 0
olderciphertext = ""
ciphertext = ""
while not os.path.isfile("/tmp/oops.txt"):
if os.path.isfile(fn):
fin = open(fn, "r")
if fin:
newotherslatestratchet = int(fin.readline())
if otherslatestratchet != newotherslatestratchet:
olderlatestratchet = otherslatestratchet
otherslatestratchet = newotherslatestratchet
flog.write("ratchet")
flog.write("\n")
flog.write(str(otherslatestratchet))
flog.write("\n")
newciphertext = fin.readline().rstrip('\n')
if ciphertext != newciphertext:
olderciphertext = ciphertext
ciphertext = newciphertext
flog.write("ciphertext")
flog.write("\n")
flog.write(ciphertext)
flog.write("\n")
fin.close()
time.sleep(0.3)
oops = open("/tmp/oops.txt", "r")
mylatestprivatekeyforother = int(oops.readline().rstrip('\n'))
oops.close()
os.remove("/tmp/oops.txt")
fin = open(fn, "r")
leakerslatestratchet = int(fin.readline())
newerciphertext = fin.readline().rstrip('\n')
fin.close()
# We can decrypt one message already
s = pow(otherslatestratchet, mylatestprivatekeyforother, p)
plaintext = otp(newerciphertext, "dec", s)
print("Eavesdropped " + theirname + ": " + plaintext)
flog.write("stolenkey")
flog.write("\n")
flog.write(str(mylatestprivatekeyforother))
flog.write("\n")
while True:
# Wait for the other to update the file
while os.path.isfile(fn):
time.sleep(0.001)
while not os.path.isfile(fn):
time.sleep(0.001)
time.sleep(0.3)
# Read the info and delete the file
fin = open(fn, "r")
theline = fin.readline()
#print(theline)
otherslatestratchet = int(theline)
ciphertext = fin.readline().rstrip('\n')
fin.close()
os.remove(fn)
# Do part of a key exchange with other, decrypt if possible
s = pow(otherslatestratchet, mylatestprivatekeyforother, p)
plaintext = otp(ciphertext, "dec", s)
flog.write("ciphertextforleaker")
flog.write("\n")
flog.write(ciphertext)
flog.write("\n")
print("Eavesdropped " + myname + ": " + plaintext)
# Do a key exchange with leaker
mylatestprivatekeyforleaker = secrets.randbelow(p)
mylatestprivatekeyforother = secrets.randbelow(p)
flog.write("keys")
flog.write("\n")
flog.write(str(mylatestprivatekeyforleaker))
flog.write("\n")
flog.write(str(mylatestprivatekeyforother))
flog.write("\n")
myratchetforleaker = pow(g, mylatestprivatekeyforleaker, p)
s = pow(leakerslatestratchet, mylatestprivatekeyforleaker, p)
# Reencrypt and make file
ciphertext = otp(plaintext, "enc", s)
fout = open(fn, "w")
flog.write("ratchetsleaker")
flog.write("\n")
flog.write(str(leakerslatestratchet))
flog.write("\n")
fout.write(str(myratchetforleaker))
fout.write("\n")
fout.write(ciphertext)
fout.write("\n")
fout.flush()
fout.close()
# Wait for the leaker to update the file
while os.path.isfile(fn):
time.sleep(0.001)
while not os.path.isfile(fn):
time.sleep(0.001)
time.sleep(0.3)
# Read the info and delete the file
fin = open(fn, "r")
theline = fin.readline()
#print(theline)
leakerslatestratchet = int(theline)
ciphertext = fin.readline().rstrip('\n')
fin.close()
os.remove(fn)
# Do a key exchange with other, decrypt if possible
myratchetforother = pow(g, mylatestprivatekeyforother, p)
s = pow(leakerslatestratchet, mylatestprivatekeyforleaker, p)
plaintext = otp(ciphertext, "dec", s)
flog.write("ciphertextforother")
flog.write("\n")
flog.write(ciphertext)
flog.write("\n")
print("Eavesdropped " + theirname + ": " + plaintext)
# Reencrypt and make file
s = pow(otherslatestratchet, mylatestprivatekeyforother, p)
ciphertext = otp(plaintext, "enc", s)
fout = open(fn, "w")
flog.write("ratchetsother")
flog.write("\n")
flog.write(str(otherslatestratchet))
flog.write("\n")
fout.write(str(myratchetforother))
fout.write("\n")
fout.write(ciphertext)
fout.write("\n")
fout.flush()
fout.close()
messagenumber = messagenumber + 2
if (False and messagenumber == 16):
print("droppingtheball...")
time.sleep(40)