#!/usr/bin/python
# NSA P2P Chat Client
# -*- coding: utf-8 -*-
import sys
import socket
import base64
import random
import string
import hashlib
from Crypto.Cipher import AES
from Crypto import Random
from threading import Thread
import getpass
class CryptoClient(object):
def __init__(self):
print("Welcome to CryptoChat, a secure P2P chat client")
print("You wanna encrypt ok lad he ye go!!!")
self.IP = input("Please enter the IP address you wish to chat with: ")
self.PORT = int(input("Enter the port for communication: "))
print()
print("Now enter the keys for the different encryption methods, make sure they are different.")
print("Please note they will not be printed for your security.")
print()
self.EncryptKeyXOR = getpass.getpass("Enter desired key for XOR encryption: ")
self.EncryptKeyAES = hashlib.md5(getpass.getpass("Enter a secure passphrase for AES: ").encode()).hexdigest()
print()
input("Press enter when both clients are ready.")
###Shit for AES padding
BS = 16
self.pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
self.unpad = lambda s: s[:-ord(s[len(s) - 1:])]
###Start chat server and client
try:
Thread(target=self.RecvMSG, args=()).start()
except socket.error as e:
print(self.IP + " is not ready! Press enter when " + self.IP + " is ready.")
input()
Thread(target=self.RecvMSG, args=()).start()
self.SendMSG()
def EncryptAES(self, raw):
raw = self.pad(raw)
iv = Random.new().read(AES.block_size)
cipher = AES.new(self.EncryptKeyAES.encode(), AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(raw.encode())).decode()
def DecryptAES(self, enc):
enc = base64.b64decode(enc)
iv = enc[:16]
cipher = AES.new(self.EncryptKeyAES.encode(), AES.MODE_CBC, iv)
return self.unpad(cipher.decrypt(enc[16:])).decode()
def XOR(self, securekey, data, mode):
if mode == 1:
securekey = securekey[::-1]
temp = ''
for char in securekey:
for x in data:
temp += chr(ord(x) ^ ord(char))
data = temp
temp = ''
return data
def EncryptMSG(self, data):
data = self.XOR(self.EncryptKeyXOR, data, 0)
data = self.EncryptAES(data)
return data
def DecryptMSG(self, data):
data = self.DecryptAES(data)
data = self.XOR(self.EncryptKeyXOR, data, 1)
return data
def SendMSG(self):
clientsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
print()
print("You are now talking to '" + self.IP + "'")
while True:
message = input("")
if message.startswith("/send"): # send file command
self.SendFILE(message.split(" ")[1])
continue
if message == "/leave":
message = self.EncryptMSG("\x03")
clientsock.sendto(message.encode(), (self.IP, self.PORT))
sys.exit(0)
if message.startswith("/msg"):
self.IP = message.split(" ")[1]
print("[CLIENT] You are now talking to '" + self.IP + "'")
continue
else:
message = self.EncryptMSG("\x01" + message)
clientsock.sendto(message.encode(), (self.IP, self.PORT))
def SendFILE(self, file_):
if file_.startswith(".") or file_.startswith("/"): # added security measure.
print("[CLIENT] For security and safety reasons, filenames starting with '.' or '/' will not be sent. Aborting.")
else:
clientsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
data = "\x02" + file_ + "\xFF"
with open(file_, "rb") as f:
data += f.read()
data = self.EncryptMSG(data)
clientsock.sendto(data.encode(), (self.IP, self.PORT))
print("[CLIENT] File Sent!")
def RandStr(self, length):
return ''.join(random.choice(string.ascii_letters) for _ in range(length))
def RecvMSG(self):
serversocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
serversocket.bind(('', self.PORT))
while True:
data, addr = serversocket.recvfrom(1073741824) # buffer size is 1 gbit (for large files/images)
data = self.DecryptMSG(data.decode())
if data.startswith("\x02"):
filename = ''
data = list(data)
del data[0]
for i in data:
if i == "\xFF":
break
else:
filename += i
del data[0] # delete protocol char
del data[:len(filename)] # delete file end char
if filename.startswith(".") or filename.startswith("/"): # attempted exploit!
print("[!!!ALERT!!!] " + addr[0] + " has attempted to overwrite your " + filename)
else:
print("[CLIENT] " + addr[0] + " has sent " + filename)
print("[CLIENT] Downloading...") # download dat shit
data = ''.join(data)
with open(filename, "wb") as f:
f.write(data.encode())
print("[CLIENT] Saved.")
elif data.startswith("\x01"): # all messages start with "\x01" to prevent file spamming
data = list(data)
del data[0]
data = ''.join(data)
print("[" + addr[0] + "] > | " + data)
elif data.startswith("\x03"):
print("[CLIENT] " + addr[0] + " has left.")
sys.exit(0)
if __name__ == "__main__":
CryptoClient()