From f6876754c5eb4272914d329874af916a71799bd5 Mon Sep 17 00:00:00 2001 From: Scratchcat1 Date: Fri, 20 Oct 2017 17:24:46 +0100 Subject: [PATCH] Add files via upload -Working on a method to mitigate the potential attack vector of a Man in The Middle attack by allowing presaved public keys in the source code of the program. The program will encrypt the AES encryption keys using the public key which only the valid private key owner can decrypt, i.e the server. --- AATC_Config.py | 35 +++++++-- AATC_Crypto.py | 200 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 188 insertions(+), 47 deletions(-) diff --git a/AATC_Config.py b/AATC_Config.py index cc7be40..65decf9 100644 --- a/AATC_Config.py +++ b/AATC_Config.py @@ -1,16 +1,41 @@ -PRE_SHARED_ENCRYPTION_KEYS_ENABLE = False -PRE_SHARED_AES_KEY = b"00000000000000000000000000000000" -PRE_SHARED_IV_KEY = b"00000000000000000000000000000000" +SERVER_NAME = "AATC" +SERVER_PRIVATE_KEY = b'0\x82\t)\x02\x01\x00\x02\x82\x02\x01\x00\x9a`\xfa\xdf\x0e%\x8bv\x82\x94v\xe1gt\xafK\'\xa1\x87l\xef\xaeV\xc5\x9e\xfb\x8e\x00\xbal1u\xab\xbe\x92"\xd6\t\xad\x12\xdbx4\x0c\x9d\xdb\xf9\xcf\x08\x8au+\xa8[n\x1b\x86i\xb76N~\x82\xcf\xdd\xd0\xa1c\xb7\xbf\xbcT\x93\x9fT\x1c\xbb\x85\xf2\xd5\xa6\xfbx,\xf1i\xecv{\x85\x92\xd6\xc5a\x168\x93.\xa4t`\x06D\xbd\x969\xba\xec\xda<&\xaf\x8d\xb0\xc6\x99\xb6k\x86\x96\x0c\x19\x0b\x1a\x82T\x1c\xcbI\xe4P\x00\xd0\x0f\x9eP\x1cw\x06\xc1\x18\x1b\xc46g\xe2\xd8iSy\xc2?\tP\xef\xd1jlf\x97C?\xfa*\x92\x1c\xd8\xf0l\x02\xd3\xc2W7\xc4\xd8\xb2\xd2\xa5\x00?\xe9K\xce\x0e\xc0\xa3\x8c\xc7\xee\xd8\x9aq\xe0\xe2n6~\xd9-_OE]Ui9w#\x7f\xf9\x11QE\xb9^/\xdc0=\x9d\x12+nU\xd4\xc6H\xebAK\x010)OV\xab3\x1b\x0f\xe8\xa99\xbe\x18\xab\xadE\x9cs\xd7\x1co\xa3FD\xcf\x96\x88\xb6\xcay\x02\xcb!\x97x{\x13\x80\'\xdd\\\x1awL\xd63\xb4\x85\xa3\x10\xf9\xe8s\xa6\xb6\xd5\xd8P\xba\xe1\x81\x07Az4\x8f\x94\x9aR\x89\xae\xb4\x18\x9b9Q\xfeVe\xb4\xf7\xfe\xb1\xa0\xd3j5\x89 r\x92\xc0\x06\xbd\xa4sf\xdc\xd0y:=M0\xe2Y\xeez\xe2^\xd0?\xd8\xf6\xe1\xa62\x840\x91d\x99\xf7{\x909\xf4\xe4\xcd\x8c\x02\x03{\x1e\xe7]\xe4\xc4 \x94 \xe5\xcbw4\xbf\xc7\xe7J\xba\x1a\xf9\x13\xedN\xff\x85UA\xcf%V\xa8\xfa0I\xb5\x05%\x9bo@\xae]\x82\xb1-\xe1\x87\x82z\xfb\x9bA\xd8\x991\xceNx\x91\xba\x87`\x1c\x9f\xc5Y+\x8b\x87[\xd1\xb8)\x92\xb0\xfc\xee\xb7\xd1\xcf\xa1OF\xc0;\xf3\xf2\xe9\xbez"\xaf\xd3\xd4\xa4\xddG\xb0]ro\xf7\x82\xfc\x1a\xf1\xed\xb92$\xcbd%j\x98\xcbd\x7f\x1b!\xc6l\xd2<\x9d8\x97\xe5\xa0\xac\xc7G\xb9\xda\x90\xce~\xb1\xc1\xab\xe2\xcd\xef\x8d\xf8g\xd1I\x02\x03\x01\x00\x01\x02\x82\x02\x00\x0e!7\xf8\xfc8\x1c\xbf\x8a4Y<\xa8}\xce1\x06e\xb3\t\xda\x16\xa6\x7f\xc4=A:)\x15\xef\xc1u\xc8\x95\xa2\xcd]\x19\x9b\x97\x1d\x95\x82\xfd\x9cU\x8d\x18\xda\xa6^\x8atb\xdb\xafU\xe3\xf4[#\x1ai8\xe3\xc8o\xc2p\xd0\xc5\x9bt\xda\xeb\x9d\xd0\xc4\xe0\xff\xfdvz\x83\x96\x96\xb3a\xfb\x1f\xed[\'\xb7\x93RJS\xb8H\x95.K\xbdq\x17~\'\xfb\xd7-\x1c~|p\xf3x\xbc:\xe5\xcc\xd1~\xb9\xc4\xc5\xd5g\xf4\x17\x0b\xf9\xff!\xf5\xf2c\x05\t\xdd\xa1e\xf86R5\x8dO[\xfe\xb6\xcb\r\x1e\xc4\x17\xb5\xe7\xfej\x83\xf3\xab[\x8f\xfb\x1d\xa7?+\x7fWA\x06\x19\xf0\xe5\x15\x7f\xd49\xaf\xcb\xe2\x7f\x08\x81!H\x07\xc8|\t\x91\xa3\xf5\x86.\xed\xc7\x92Ov\x9bS\x8c\x14N\xda\x1e\xd3rQ;\xc6\x06\x82\xa4b1K\tQZ\x17\x05V\x85|\xc6\x87\x0bo\xce\x80\x8f\xdf\x17\xb8!+\x02\xfbV\x91\xf9\x04\x1c\xed\x9f\xd7\xcd\x12\x80B\xf5\xe1\xff\xb7 \xb9\xe19\xa8>\xe0,\xd9U\x92\xd9r\x9aU\xc5\xa5\xe7U\x0b\x87\xd7\xa3-\xdb\xd0\xeeH`\xdbrJ\xc1\xfc^\xe6\\\xea\t\x14\x8e\x15\x01\xb1\xe4\xa9he\xac\xa7;\xf6\xc5\xc6\xa7X,\xcb"\xe3\x98\x94eOs\xab\x91\x0c&/\xa8\xfd}\xc1O\xa8MA\xef\xb2B\x95\xffP\xfff\xed\x1b\xdd+"\xac\xbd\x98\x0b{\x02\xab\x0eh\x9d"}\xa8\xe3\xc46E\x0ex\xc2\xe9\xea:\xaa\xe4\x89\x0f\x01\xfd\xb3^\xfb\x85\xb3\xa1?IZ]\x15\x14lv>7\x96\xeb\xc4\xc6\x0b.\r\xac@-.\xb2\xb3\xc7\n\x0f6\x97.\xe2\xce\xff\x90\x86\xd8s\xb3\x18\xebVA\x82\xc8\x1d;\xdf"\xfc#\x7f\x98`\x1e\xc2\xeb%\x97W\xae\x99H\x90\x9a\xe2\xf3\x0c\xca\xc9\xa5\x9c\xdb?V\xe5\xa5\xaf\xe4\xe0\x0f\xfcZj\xab\x0e\xf1\x02\x82\x01\x01\x00\x88\xd8\xda:\x97\x1c\x1e\x1b3o\xbe\x01\x00\xdc\x84\xa48\xd12\xed\x0e\x972\x96\xc9\x02<\xc3\xf1\xd5\x98\xcf\x8e\xf8\xe0\xb4\xf0C\x92\x14\xedq\xf8\r#\xe5$[\x1a\x14\x17\xdd\xdd\x9d!\xb1\x82\xc1\xa1\\\xa0\xa9\xad\x9d(\xe4\xb7\xfd\xb5\xbd\x98\xb0n\xf4g\xb4$\x11\xc0\xd8;\x122\xfa\t\r^B\x1c\x94\xd1\x97Y\xd0\x96\xd1\xa9@\x14Q\x8f\x15\xa9\xb2\xf5:~o\xf2/Qo\xd2%\xa8\xeb\x95\xec6\xb2\x00m_o\xdeF{k\x17Y\xca)\x1f\xc6\xddz\xb2\xefY;\x92\rxRI\xff\xd2\xc9\x05q\x1aHh\xaeI\xdf\xab\xc3\xc5)\xd5P\xe4\x82N\x0b\xfb\x81\x02\x82\x01\x00\x07\x9f\x0b\x02\xc5\xb4\xd2\xbdRy\xf4aq\xa3\xf5\xce\x17\r\xb6\x13\xf9\xed}\xbc\xf9\xfe\\\xb2\x8f\xee\x1f\xf4\xbb\xbe\x8d\xee:\xb4\xeb%\xbf2ya\x9f\x87\x88\xe0]\xa1\x9a{\xdd\xb5\x04,4V\xe8\xd1\xfd\'I\xc18\xedG\x88\xe1<\xd7\xda\x1b\x19\xef\xad\xc2{\x9e\x13\xdb\xc3%b\xe5\x12CJ\xc0F\xd1\xbd\xd4\xcd|\xff2I;mp\xaa\x05X\xf8\xedNI\x93\xca\x91\xd9\x83\x8e\x04\xe2|\xf5\xa1O\xfbq~;\xb0o\xb0-\x03\xca\x1a\xc25is\xb0F\xc0L\xe5U\xb20!g&c\xb9\x19\xc6[o8{\x87a\xfe<\xfb\x8c\xc4U\x18Bz\xe8D\xdfd9\x88\xe9\xfa\x9f|\x8f\x1f#U\xad\xbf\xe2\x17\x12\xd4\xff\x05\x83FV=\xab\x06x\xc6\xe4>?\x9aMFg\x85]K\xc2\xd4\x02\x88J\x87\x89`\x1a\xac\xcb\xa9\x03\x05\xcb^\xf5i\x00\xce%\x00H, \xa9~\xdd\x8e\x9b{,\x82\x04Z\x94\xd7\xd2\xbe\xd7\x94b\x1bJ*yP\x8c\xe76\xd4' + + +SET_ENCRYPTION_KEYS_ENABLE = False +SET_AES_KEY = b"00000000000000000000000000000000" +SET_IV_KEY = b"00000000000000000000000000000000" + DEFAULT_AES_KEYSIZE = 32 ALLOWED_AES_KEYSIZES = [16,24,32] - DEFAULT_RSA_KEYSIZE = 2048 +ENCRYPTION_USE_PRESHARED_KEYS = False +AUTO_GENERATE_FALLBACK = False +CERTIFICATES = { + "AATC":[ + { + "ServerName":"AATC", + "NotBefore":1, + "NotAfter":1000000000, + "PublicKey":b'0\x82\x02"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x000\x82\x02\n\x02\x82\x02\x01\x00\x9a`\xfa\xdf\x0e%\x8bv\x82\x94v\xe1gt\xafK\'\xa1\x87l\xef\xaeV\xc5\x9e\xfb\x8e\x00\xbal1u\xab\xbe\x92"\xd6\t\xad\x12\xdbx4\x0c\x9d\xdb\xf9\xcf\x08\x8au+\xa8[n\x1b\x86i\xb76N~\x82\xcf\xdd\xd0\xa1c\xb7\xbf\xbcT\x93\x9fT\x1c\xbb\x85\xf2\xd5\xa6\xfbx,\xf1i\xecv{\x85\x92\xd6\xc5a\x168\x93.\xa4t`\x06D\xbd\x969\xba\xec\xda<&\xaf\x8d\xb0\xc6\x99\xb6k\x86\x96\x0c\x19\x0b\x1a\x82T\x1c\xcbI\xe4P\x00\xd0\x0f\x9eP\x1cw\x06\xc1\x18\x1b\xc46g\xe2\xd8iSy\xc2?\tP\xef\xd1jlf\x97C?\xfa*\x92\x1c\xd8\xf0l\x02\xd3\xc2W7\xc4\xd8\xb2\xd2\xa5\x00?\xe9K\xce\x0e\xc0\xa3\x8c\xc7\xee\xd8\x9aq\xe0\xe2n6~\xd9-_OE]Ui9w#\x7f\xf9\x11QE\xb9^/\xdc0=\x9d\x12+nU\xd4\xc6H\xebAK\x010)OV\xab3\x1b\x0f\xe8\xa99\xbe\x18\xab\xadE\x9cs\xd7\x1co\xa3FD\xcf\x96\x88\xb6\xcay\x02\xcb!\x97x{\x13\x80\'\xdd\\\x1awL\xd63\xb4\x85\xa3\x10\xf9\xe8s\xa6\xb6\xd5\xd8P\xba\xe1\x81\x07Az4\x8f\x94\x9aR\x89\xae\xb4\x18\x9b9Q\xfeVe\xb4\xf7\xfe\xb1\xa0\xd3j5\x89 r\x92\xc0\x06\xbd\xa4sf\xdc\xd0y:=M0\xe2Y\xeez\xe2^\xd0?\xd8\xf6\xe1\xa62\x840\x91d\x99\xf7{\x909\xf4\xe4\xcd\x8c\x02\x03{\x1e\xe7]\xe4\xc4 \x94 \xe5\xcbw4\xbf\xc7\xe7J\xba\x1a\xf9\x13\xedN\xff\x85UA\xcf%V\xa8\xfa0I\xb5\x05%\x9bo@\xae]\x82\xb1-\xe1\x87\x82z\xfb\x9bA\xd8\x991\xceNx\x91\xba\x87`\x1c\x9f\xc5Y+\x8b\x87[\xd1\xb8)\x92\xb0\xfc\xee\xb7\xd1\xcf\xa1OF\xc0;\xf3\xf2\xe9\xbez"\xaf\xd3\xd4\xa4\xddG\xb0]ro\xf7\x82\xfc\x1a\xf1\xed\xb92$\xcbd%j\x98\xcbd\x7f\x1b!\xc6l\xd2<\x9d8\x97\xe5\xa0\xac\xc7G\xb9\xda\x90\xce~\xb1\xc1\xab\xe2\xcd\xef\x8d\xf8g\xd1I\x02\x03\x01\x00\x01' + }, + ], + + + + } + + + + + DEFAULT_DRONE_BATTERY_VALUE = 100 DEFAULT_DRONE_ATWAYPOINT_SIZES = (0.001,0.001,5) DEFAULT_DRONE_COORDINATE = (0,0,0) +DRONE_BATTERY_DRAIN_MULT = 1 -DRONE_BATTERY_DRAIN_MULT = 1 +NOFLYZONE_THRESHOLD_COST = 50 diff --git a/AATC_Crypto.py b/AATC_Crypto.py index d99635d..481cbd0 100644 --- a/AATC_Crypto.py +++ b/AATC_Crypto.py @@ -1,5 +1,5 @@ #AATC crypto module -import codecs,recvall,ast,binascii,os,AATC_Config +import codecs,recvall,ast,binascii,os,AATC_Config,time from Crypto.Cipher import AES,PKCS1_OAEP from Crypto.PublicKey import RSA @@ -21,11 +21,8 @@ class Crypter: """ def __init__(self, con, mode = "CLIENT",AutoGenerate = True): self.con = con - self.SetMode(mode) - if AATC_Config.PRE_SHARED_ENCRYPTION_KEYS_ENABLE: #Allows preshared encryption keys to be used - self.SetEncryptionKeys(AATC_Config.PRE_SHARED_AES_KEY, AATC_Config.PRE_SHARED_IV_KEY) - - elif AutoGenerate: + self.SetMode(mode) + if AutoGenerate: self.GenerateKey() def SetMode(self,mode): @@ -44,33 +41,77 @@ def GenerateKey(self,key_size = AATC_Config.DEFAULT_RSA_KEYSIZE): def ClientGenerateKey(self,RSA_KeySize,AES_KeySize= AATC_Config.DEFAULT_AES_KEYSIZE): + + self.Send(("GetServerName",())) + Sucess,Message,Data = self.SplitData(self.Recv()) + if not Sucess: + raise ValueError("Server did not recognise command"+Message) + ServerName = Data[0] + + if AATC_Config.SET_ENCRYPTION_KEYS_ENABLE: #Allows preshared encryption keys to be used + self.SetEncryptionKeys(AATC_Config.SET_AES_KEY, AATC_Config.SET_IV_KEY) + + elif AATC_Config.ENCRYPTION_USE_PRESHARED_KEYS: + self.ClientPreSharedKeys(ServerName,RSA_KeySize,AES_KeySize) + + else: + self.ClientExchangeKeys(RSA_KeySize,AES_KeySize) + + + + + self.Send(("Exit",())) + Sucess,Message,Data = self.SplitData(self.Recv()) + if not Sucess: + raise Exception("Server failed to exit"+Message) + + + + def ClientPreSharedKeys(self,ServerName,RSA_KeySize,AES_KeySize): + AESKey,IV = GenerateKeys(AES_KeySize) + Certificate = GetCertificates(ServerName) + + if Certificate: + publicKey = Certificate["PublicKey"] + PKO = PKCS1_OAEP.new(RSA.import_key(publicKey)) + EncryptedAESKey = PKO.encrypt(AESKey) + EncryptedIV = PKO.encrypt(IV) + self.SetEncryptionKeys(AESKey,IV) + self.Send(("SetKey",(EncryptedAESKey,EncryptedIV))) + data = self.Recv() + + + else: + print("No Valid Certificates found") + if AATC_Config.AUTO_GENERATE_FALLBACK: + self.ClientExchangeKeys(RSA_KeySize,AES_KeySize) + else: + raise Exception("No valid certificate found. Exception raised") + + + + def ClientExchangeKeys(self,RSA_KeySize,AES_KeySize): RSAKey = RSA.generate(RSA_KeySize) privateKey = RSAKey.exportKey("DER") publicKey = RSAKey.publickey().exportKey("DER") - self.Send(("ExchangeKey",(publicKey,AES_KeySize))) #Format ("ExchangeKey",("a1b2c3.....",)) - data = self.Recv() - Sucess,Message = data[0],data[1] #Format (Sucess,("a2c3d4...")) - if Sucess == False: - raise Exception("Error occured while exchanging keys") - - self.Send(("Exit",())) - data = self.Recv() - if data[0] == False: - raise Exception("Server failed to commit to exit") + self.Send(("GenerateKey",(publicKey,AES_KeySize))) + Sucess,Message,data = self.SplitData(self.Recv()) RSAPrivateKey = RSA.import_key(privateKey) RSAPrivateObject = PKCS1_OAEP.new(RSAPrivateKey) - self.AESKey = RSAPrivateObject.decrypt(Message[0]) - self.IV = RSAPrivateObject.decrypt(Message[1]) - - self.SetEncryptionKeys(self.AESKey,self.IV) - + AESKey = RSAPrivateObject.decrypt(data[0]) + IV = RSAPrivateObject.decrypt(data[1]) + if Sucess == False: + raise Exception("Error occured while exchanging keys") + + self.SetEncryptionKeys(AESKey,IV) + ################################################################ def ServerGenerateKey(self): @@ -79,29 +120,59 @@ def ServerGenerateKey(self): data = self.Recv() Command, Arguments = data[0],data[1] - if Command == "ExchangeKey": - publicKey,AES_KeySize = Arguments[0],Arguments[1] - if AES_KeySize not in AATC_Config.ALLOWED_AES_KEYSIZES: - AES_KeySize = AATC_Config.DEFAULT_AES_KEYSIZE #If key size is not valid set size to default of AATC_Config.DEFAULT_AES_KEYSIZE - - self.AESKey = binascii.b2a_hex(os.urandom(AES_KeySize//2)) # Here to allow regeneration of AES key while still in loop if required. - self.IV = binascii.b2a_hex(os.urandom(AES_KeySize//2)) - - RSAPrivateKey = RSA.import_key(publicKey) - PublicKeyObject = PKCS1_OAEP.new(RSAPrivateKey) + if Command == "GenerateKey": + Sucess,Message,Data = self.ServerGenerateKeys(Arguments) + + elif Command == "GetServerName": + Sucess,Message,Data = self.GetServerName(Arguments) + + elif Command == "SetKey": + Sucess,Message,Data = self.ServerSetKey(Arguments) - EncryptedAESKey = PublicKeyObject.encrypt(self.AESKey) - EncryptedIV = PublicKeyObject.encrypt(self.IV) - self.Send((True,(EncryptedAESKey,EncryptedIV))) elif Command == "Exit": - self.Send((True,())) + Sucess,Message,Data = True,"Exiting",[] Exit = True else: - self.Send((False,("Command does not exist",))) + Sucess,Message,Data = False,"Command does not exist",[] - self.SetEncryptionKeys(self.AESKey,self.IV) + self.Send((Sucess,Message,Data)) + + + + + def ServerGenerateKeys(self,Arguments): + publicKey,AES_KeySize = Arguments[0],Arguments[1] + + if AES_KeySize not in AATC_Config.ALLOWED_AES_KEYSIZES: + AES_KeySize = AATC_Config.DEFAULT_AES_KEYSIZE #If key size is not valid set size to default of AATC_Config.DEFAULT_AES_KEYSIZE + + AESKey,IV = GenerateKeys(AES_KeySize) + + PublicKeyObject = PKCS1_OAEP.new( RSA.import_key(publicKey)) + + EncryptedAESKey = PublicKeyObject.encrypt(AESKey) + EncryptedIV = PublicKeyObject.encrypt(IV) + + self.SetEncryptionKeys(AESKey,IV) + return True,"Instated encryption keys",[EncryptedAESKey,EncryptedIV] + + def GetServerName(self,Arguments = None): + return True,"Server Name",[AATC_Config.SERVER_NAME] + + def ServerSetKey(self,Arguments): + PKO = PKCS1_OAEP.new(RSA.import_key(AATC_Config.SERVER_PRIVATE_KEY)) + AESKey,IV = Arguments[0],Arguments[1] + AESKey,IV = PKO.decrypt(AESKey),PKO.decrypt(IV) + self.SetEncryptionKeys(AESKey,IV) + return True,"Keys set",[] + + + + + + ############################################### def SetEncryptionKeys(self,AESKey,IV): @@ -116,16 +187,29 @@ def SetEncryptionKeys(self,AESKey,IV): + + + + + + + + + + + + + + + + + def Encrypt(self,data): -## pad_size = 16-len(data)%16 -## data += b" "*pad_size return self.EncryptAES.encrypt(data) def Decrypt(self,data): -## pad_size = 16-len(data)%16 # - should not be nessesary as data will come in 16 size blocks and change in message would thwart decryption. -## data += b" "*pad_size return self.DecryptAES.decrypt(data) @@ -136,6 +220,38 @@ def Send(self,data): def Recv(self): data = recvall.recvall(self.con) data = ast.literal_eval(codecs.decode(data)) - # (Command,Arguments) return data + def SplitData(self,data): + return data[0],data[1],data[2] + + + + + +def GenerateKeys(AES_KeySize): + AESKey = binascii.b2a_hex(os.urandom(AES_KeySize//2)) # Here to allow regeneration of AES key while still in loop if required. + IV = binascii.b2a_hex(os.urandom(AES_KeySize//2)) + return AESKey,IV + +def GetCertificates(ServerName): + Certificates = AATC_Config.CERTIFICATES.get(ServerName) + if Certificates == None: + return False + + found = False + for Certificate in Certificates: + if Validate(Certificate): + found = True + break + + if not found: + return False + + return Certificate + +def Validate(Certificate): + if Certificate["NotBefore"] <= time.time() and Certificate["NotAfter"] >= time.time(): + return True + else: + return False